From 5918d5120f249654962a7fc5d8f823cbd93b495d Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 30 Sep 2024 21:32:33 +0200 Subject: [PATCH] Foreach over distinct pointer failed to be caught as error #1506. --- releasenotes.md | 1 + src/compiler/sema_stmts.c | 17 +++++++++++++---- .../statements/foreach_distinct_pointer_1506.c3 | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 test/test_suite/statements/foreach_distinct_pointer_1506.c3 diff --git a/releasenotes.md b/releasenotes.md index 65dda63e1..fd48147fe 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -68,6 +68,7 @@ - Fix bug when reading zip manifest, that would not return a zero terminated string. #1490 - Fix thread tests. - Detect recursion errors on non-recursive mutexes in safe mode. +- Foreach over distinct pointer failed to be caught as error #1506. ### Stdlib changes - Additional init functions for hashmap. diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index e2f794757..9cc877650 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1442,15 +1442,15 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen } // Insert a single deref as needed. - Type *flattened_type = enumerator->type->canonical; - if (flattened_type->type_kind == TYPE_UNTYPED_LIST) + Type *canonical = enumerator->type->canonical; + if (canonical->type_kind == TYPE_UNTYPED_LIST) { RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate a compile time 'untyped' list at runtime, but you can use the compile time `$foreach` with the list."); } - if (flattened_type->type_kind == TYPE_POINTER) + if (canonical->type_kind == TYPE_POINTER) { // Something like Foo** will not be dereferenced, only Foo* - if (flattened_type->pointer->type_kind == TYPE_POINTER) + if (canonical->pointer->type_kind == TYPE_POINTER) { RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type)); } @@ -1463,6 +1463,15 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen // Check that we can even index this expression. Type *value_type = type_get_indexed_type(enumerator->type); + // Special case, we might have "distinct Foo = char*" in which case the + // deref didn't happen above, but it will get a value_type. + // However, that would make the code later assume it's possible + // To use foreach on it. + if (canonical->type_kind == TYPE_DISTINCT && type_flatten(canonical)->type_kind == TYPE_POINTER) + { + value_type = NULL; + } + if (value_type && value_by_ref) value_type = type_get_ptr(value_type); Decl *len = NULL; diff --git a/test/test_suite/statements/foreach_distinct_pointer_1506.c3 b/test/test_suite/statements/foreach_distinct_pointer_1506.c3 new file mode 100644 index 000000000..5e6c2d262 --- /dev/null +++ b/test/test_suite/statements/foreach_distinct_pointer_1506.c3 @@ -0,0 +1,14 @@ +distinct Type = char*; +fn usz Type.len(str) +{ + return 0; +} +fn int main(String[] args) +{ + Type x = "AAAAA"; // Or ZString + foreach(y : x) // #error: It's not possible to enumerate an expression + { + + } + return 0; +} \ No newline at end of file