Skip to content

Commit

Permalink
Add array to void* implicit cast (#541)
Browse files Browse the repository at this point in the history
  • Loading branch information
Akuli authored Dec 31, 2024
1 parent e638fcd commit ea9892e
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
4 changes: 3 additions & 1 deletion self_hosted/typecheck.jou
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
8 changes: 6 additions & 2 deletions src/typecheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
17 changes: 17 additions & 0 deletions tests/should_succeed/array_to_voidptr.jou
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit ea9892e

Please sign in to comment.