From 03cfa42eb6f268fd15ac880d09b27b47968bc551 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 20 Jul 2024 03:39:33 +0200 Subject: [PATCH] Duplicate symbols with static variable declared in macro #1248. Improved error message when trying user foreach with an untyped list. --- releasenotes.md | 2 + src/compiler/llvm_codegen.c | 6 +- src/compiler/sema_stmts.c | 7 +- test/test_suite/variables/static_in_macro.c3t | 76 +++++++++++++++++++ 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 test/test_suite/variables/static_in_macro.c3t diff --git a/releasenotes.md b/releasenotes.md index 384047d26..333848b12 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -23,6 +23,7 @@ - `manifest.json` is now checked for incorrect keys. - Added `--list-manifest-properties` to list the available properties in `manifest.json`. - Indexing into a constant array / struct now works at compile time. +- Improved error message when trying user foreach with an untyped list. ### Fixes - Error with unsigned compare in `@ensure` when early returning 0 #1207. @@ -48,6 +49,7 @@ - `ordinal` is no longer a valid associated value name for enums. - Constants defined by indexing into another constant could fail codegen. - Stdlib nolibc code bugs fixed. +- Regression: duplicate symbols with static variable declared in macro #1248. ### Stdlib changes - Added `remove_first_item` `remove_last_item` and `remove_item` as aliases for the `match` functions. diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 5d79b2ac8..19aa839f4 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -572,12 +572,16 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) LLVMSetGlobalConstant(global_ref, decl->var.kind == VARDECL_CONST); + if (str_eq(decl->name, "x")) + { + puts("a"); + } if (decl->is_extern) { LLVMSetLinkage(global_ref, LLVMExternalLinkage); if (optional_ref) LLVMSetLinkage(optional_ref, LLVMExternalLinkage); } - else if (decl_is_externally_visible(decl)) + else if (decl_is_externally_visible(decl) && !decl->var.is_static) { LLVMSetVisibility(global_ref, LLVMDefaultVisibility); if (optional_ref) LLVMSetVisibility(optional_ref, LLVMDefaultVisibility); diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 84e2c310f..1d51cfafa 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1500,13 +1500,16 @@ 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) + { + 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) { // Something like Foo** will not be dereferenced, only Foo* if (flattened_type->pointer->type_kind == TYPE_POINTER) { - SEMA_ERROR(enumerator, "It is not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type)); - return false; + RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate an expression of type %s.", type_quoted_error_string(enumerator->type)); } expr_rewrite_insert_deref(enumerator); } diff --git a/test/test_suite/variables/static_in_macro.c3t b/test/test_suite/variables/static_in_macro.c3t new file mode 100644 index 000000000..7de212799 --- /dev/null +++ b/test/test_suite/variables/static_in_macro.c3t @@ -0,0 +1,76 @@ +// #target: macos-x64 +module test; +import asdf; +import foo; +import std::io; + +fn int main(String[] args) { + bar(); + bar2(); + foo::bar(); + foo::bar2(); + return 0; +} + +fn void bar() { + asdf::get_static(); +} + +fn void* bar2() { + return asdf::get_static_ref(); +} + +module foo; +import asdf; +import std::io; + +// Same function name +fn void bar() { + asdf::get_static(); +} + +fn void* bar2() { + return asdf::get_static_ref(); +} + +module asdf; + +macro get_static() { + static char x; + return x; +} + +macro get_static_ref() { + static char x; + return &x; +} + +/* #expect: foo.ll + +@bar.x = internal local_unnamed_addr global i8 0, align 1 +@bar2.x = internal global i8 0, align 1 + +define void @foo.bar() #0 { +entry: + ret void +} + +define ptr @foo.bar2() #0 { +entry: + ret ptr @bar2.x +} + +// #expect: test.ll + +@bar.x = internal local_unnamed_addr global i8 0, align 1 +@bar2.x = internal global i8 0, align 1 + +define void @test.bar() #0 { +entry: + ret void +} + +define ptr @test.bar2() #0 { +entry: + ret ptr @bar2.x +}