diff --git a/self_hosted/typecheck.jou b/self_hosted/typecheck.jou index 56baeaeb..3eddb036 100644 --- a/self_hosted/typecheck.jou +++ b/self_hosted/typecheck.jou @@ -31,6 +31,7 @@ def can_cast_implicitly(from: Type*, to: Type*) -> bool: return ( from == to or (from->kind == TypeKind::Array and to->kind == TypeKind::Pointer and from->array.item_type == to->value_type) + or (from->kind == TypeKind::Array and to->kind == TypeKind::VoidPointer) or ( from->is_integer_type() and to->is_integer_type() @@ -46,6 +47,7 @@ def can_cast_explicitly(from: Type*, to: Type*) -> bool: return ( from == to or (from->kind == TypeKind::Array and to->kind == TypeKind::Pointer and from->array.item_type == to->value_type) + or (from->kind == TypeKind::Array and to->kind == TypeKind::VoidPointer) or (from->is_pointer_type() and to->is_pointer_type()) or (from->is_number_type() and to->is_number_type()) or (from->is_integer_type() and to->kind == TypeKind::Enum) @@ -165,7 +167,7 @@ class ExpressionTypes: fail_with_implicit_cast_error(error_location, error_template, from, to) self->implicit_cast_type = to - if from->kind == TypeKind::Array and to->kind == TypeKind::Pointer: + if from->kind == TypeKind::Array and to->is_pointer_type(): self->implicit_array_to_pointer_cast = True ensure_can_take_address( self->expression, diff --git a/src/typecheck.c b/src/typecheck.c index 387c1f39..57246bf8 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -541,8 +541,11 @@ static bool can_cast_implicitly(const Type *from, const Type *to) return from == to || ( - // array to pointer implicitly + // array to pointer with same item type from->kind == TYPE_ARRAY && to->kind == TYPE_POINTER && from->data.array.membertype == to->data.valuetype + ) || ( + // array to void* + from->kind == TYPE_ARRAY && to->kind == TYPE_VOID_POINTER ) || ( // Cast to bigger integer types implicitly, unless it is signed-->unsigned. is_integer_type(from) @@ -594,7 +597,7 @@ static void do_implicit_cast( fail_with_implicit_cast_error(location, errormsg_template, from, to); types->implicit_cast_type = to; - types->implicit_array_to_pointer_cast = (from->kind == TYPE_ARRAY && to->kind == TYPE_POINTER); + types->implicit_array_to_pointer_cast = (from->kind == TYPE_ARRAY && is_pointer_type(to)); if (types->implicit_array_to_pointer_cast) ensure_can_take_address( fom, @@ -620,6 +623,7 @@ static void do_explicit_cast(const FunctionOrMethodTypes *fom, ExpressionTypes * if ( from != to && !(from->kind == TYPE_ARRAY && to->kind == TYPE_POINTER && from->data.array.membertype == to->data.valuetype) + && !(from->kind == TYPE_ARRAY && to->kind == TYPE_VOID_POINTER) && !(is_pointer_type(from) && is_pointer_type(to)) && !(is_number_type(from) && is_number_type(to)) && !(is_integer_type(from) && to->kind == TYPE_ENUM) diff --git a/tests/should_succeed/array_to_voidptr.jou b/tests/should_succeed/array_to_voidptr.jou new file mode 100644 index 00000000..11cc6e6c --- /dev/null +++ b/tests/should_succeed/array_to_voidptr.jou @@ -0,0 +1,17 @@ +import "stdlib/io.jou" +import "stdlib/mem.jou" + + +def main() -> int: + # Implicit cast + array = [1, 2, 3, 4] + p: void* = array + memset(p, 0, 4) + printf("[%d, %d, %d]\n", array[0], array[1], array[2]) # Output: [0, 2, 3] + + # Explicit cast + array = [1, 2, 3, 4] + memset(array as void*, 0, 4) + printf("[%d, %d, %d]\n", array[0], array[1], array[2]) # Output: [0, 2, 3] + + return 0