Skip to content

Commit

Permalink
Foreach over distinct pointer failed to be caught as error #1506.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Sep 30, 2024
1 parent 0d73f2f commit 5918d51
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
1 change: 1 addition & 0 deletions releasenotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
17 changes: 13 additions & 4 deletions src/compiler/sema_stmts.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand All @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions test/test_suite/statements/foreach_distinct_pointer_1506.c3
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 5918d51

Please sign in to comment.