From 8c741c617c5e8feac1324b34fc990c8a0850ab22 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 15 May 2025 09:36:16 +0200 Subject: [PATCH] Variable aliases of aliases would not resolve correctly. #2131 Variable aliases could not be assigned to. --- releasenotes.md | 2 ++ src/compiler/ast.c | 4 ++-- src/compiler/compiler_internal.h | 4 ++-- src/compiler/context.c | 4 ++-- src/compiler/copying.c | 2 +- src/compiler/enums.h | 4 ++-- src/compiler/json_output.c | 2 +- src/compiler/llvm_codegen.c | 2 +- src/compiler/parse_global.c | 2 +- src/compiler/sema_decls.c | 15 ++++++++++----- src/compiler/sema_expr.c | 7 ++++--- src/compiler/sema_liveness.c | 2 +- src/compiler/sema_types.c | 2 +- src/compiler/semantic_analyser.c | 2 +- test/test_suite/define/alias_alias.c3t | 21 +++++++++++++++++++++ 15 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 test/test_suite/define/alias_alias.c3t diff --git a/releasenotes.md b/releasenotes.md index 98f01711d..1867a9b2b 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -19,6 +19,8 @@ - attrdef with any invalid name causes compiler assert #2128. - Correctly error on `@attrdef Foo = ;`. - Contract on trying to use Object without initializing it. +- Variable aliases of aliases would not resolve correctly. #2131 +- Variable aliases could not be assigned to. ### Stdlib changes - Added `String.quick_ztr` and `String.is_zstr` diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 965ddfadd..8ec7d81bf 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -112,7 +112,7 @@ const char *decl_to_a_name(Decl *decl) case DECL_CT_EXEC: return "compile time exec include"; case DECL_CT_INCLUDE: return "an include"; case DECL_DECLARRAY: return "a declarray"; - case DECL_DEFINE: case DECL_TYPEDEF: return "a define"; + case DECL_ALIAS: case DECL_TYPEDEF: return "an alias"; case DECL_DISTINCT: return "a distinct type"; case DECL_ENUM: return "an enum"; case DECL_ENUM_CONSTANT: return "an enum value"; @@ -401,7 +401,7 @@ bool decl_needs_prefix(Decl *decl) switch (decl->decl_kind) { case DECL_VAR: - case DECL_DEFINE: + case DECL_ALIAS: case DECL_FUNC: case DECL_MACRO: case DECL_FAULT: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 37804792d..32f3997b8 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -3200,7 +3200,7 @@ INLINE bool decl_poison(Decl *decl) static inline Decl *decl_raw(Decl *decl) { - while (decl->decl_kind == DECL_DEFINE) + while (decl->decl_kind == DECL_ALIAS) { decl = decl->define_decl.alias; } @@ -3227,7 +3227,7 @@ INLINE bool decl_is_user_defined_type(Decl *decl) INLINE Decl *decl_flatten(Decl *decl) { - if (decl->decl_kind == DECL_DEFINE) + if (decl->decl_kind == DECL_ALIAS) { return decl->define_decl.alias; } diff --git a/src/compiler/context.c b/src/compiler/context.c index 4de2311ab..47c8d541d 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -175,7 +175,7 @@ void decl_register(Decl *decl) case DECL_STRUCT: case DECL_TYPEDEF: case DECL_UNION: - case DECL_DEFINE: + case DECL_ALIAS: case DECL_FUNC: case DECL_MACRO: case DECL_VAR: @@ -248,7 +248,7 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl) vec_add(unit->faults, decl); decl_register(decl); break; - case DECL_DEFINE: + case DECL_ALIAS: ASSERT(decl->name); vec_add(unit->generic_defines, decl); decl_register(decl); diff --git a/src/compiler/copying.c b/src/compiler/copying.c index e9d2992ac..78ba9808b 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -1103,7 +1103,7 @@ Decl *copy_decl(CopyStruct *c, Decl *decl) MACRO_COPY_DECL_LIST(decl->attr_decl.params); decl->attr_decl.attrs = copy_attributes(c, decl->attr_decl.attrs); break; - case DECL_DEFINE: + case DECL_ALIAS: if (decl->resolve_status == RESOLVE_DONE) { fixup_decl(c, &decl->define_decl.alias); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 7bba26579..961214ed3 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -659,7 +659,7 @@ typedef enum DECL_CT_EXEC, DECL_CT_INCLUDE, DECL_DECLARRAY, - DECL_DEFINE, + DECL_ALIAS, DECL_DISTINCT, DECL_ENUM, DECL_ENUM_CONSTANT, @@ -1630,7 +1630,7 @@ typedef enum // -- Decl helper macros #define NON_TYPE_DECLS DECL_IMPORT: case DECL_MACRO: \ case DECL_DECLARRAY: case DECL_ATTRIBUTE: case DECL_LABEL: \ - case DECL_DEFINE: case DECL_CT_ASSERT: case DECL_CT_EXEC: case DECL_FAULT: \ + case DECL_ALIAS: case DECL_CT_ASSERT: case DECL_CT_EXEC: case DECL_FAULT: \ case DECL_CT_ECHO: case DECL_CT_INCLUDE: case DECL_GROUP: \ case DECL_BODYPARAM: case DECL_VAR: case DECL_ENUM_CONSTANT: \ case DECL_POISONED diff --git a/src/compiler/json_output.c b/src/compiler/json_output.c index 2767e7236..3cb44d0cf 100644 --- a/src/compiler/json_output.c +++ b/src/compiler/json_output.c @@ -87,7 +87,7 @@ static inline const char *decl_type_to_string(Decl *type) case DECL_CT_ECHO: return "$echo"; case DECL_CT_EXEC: return "$exec"; case DECL_CT_INCLUDE: return "$include"; - case DECL_DEFINE: return "def"; + case DECL_ALIAS: return "alias"; case DECL_DISTINCT: return "typedef"; case DECL_ENUM: return "enum"; case DECL_ENUM_CONSTANT: return "enum_const"; diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 0eb945899..9be75411d 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -1345,7 +1345,7 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl) llvm_append_function_attributes(c, decl); llvm_set_decl_linkage(c, decl); return backend_ref; - case DECL_DEFINE: + case DECL_ALIAS: return llvm_get_ref(c, decl->define_decl.alias); case DECL_FAULT: return llvm_create_fault(c, decl); diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 04266984b..e7f55f029 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -2174,7 +2174,7 @@ static inline Decl *parse_alias_ident(ParseContext *c) } // 3. Set up the "define". - Decl *decl = decl_new(DECL_DEFINE, symstr(c), c->span); + Decl *decl = decl_new(DECL_ALIAS, symstr(c), c->span); if (decl->name == kw_main) { diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 4e54e01dd..81560d008 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -53,7 +53,7 @@ static Decl *sema_find_exact_typed_operator_in_list(Decl **methods, OperatorOver static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl, bool *erase_decl); static bool sema_analyse_variable_type(SemaContext *context, Type *type, SourceSpan span); -static inline bool sema_analyse_define(SemaContext *context, Decl *decl, bool *erase_decl); +static inline bool sema_analyse_alias(SemaContext *context, Decl *decl, bool *erase_decl); static inline bool sema_analyse_distinct(SemaContext *context, Decl *decl, bool *erase_decl); static CompilationUnit *unit_copy(Module *module, CompilationUnit *unit); @@ -4965,7 +4965,7 @@ static inline bool sema_analyse_attribute_decl(SemaContext *context, SemaContext return true; } -static inline bool sema_analyse_define(SemaContext *context, Decl *decl, bool *erase_decl) +static inline bool sema_analyse_alias(SemaContext *context, Decl *decl, bool *erase_decl) { if (!sema_analyse_attributes(context, decl, decl->attributes, ATTR_ALIAS, erase_decl)) return decl_poison(decl); if (*erase_decl) return true; @@ -4981,7 +4981,12 @@ static inline bool sema_analyse_define(SemaContext *context, Decl *decl, bool *e RETURN_SEMA_ERROR(expr, "A global variable or function name was expected here."); } Decl *symbol = expr->ident_expr; - if (!sema_analyse_decl(context, symbol)) return false; + while (true) + { + if (!sema_analyse_decl(context, symbol)) return false; + if (symbol->decl_kind != DECL_ALIAS) break; + symbol = symbol->define_decl.alias; + } bool should_be_const = char_is_upper(decl->name[0]); if (should_be_const) { @@ -5136,8 +5141,8 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl) case DECL_FAULT: if (!sema_analyse_fault(context, decl, &erase_decl)) goto FAILED; break; - case DECL_DEFINE: - if (!sema_analyse_define(context, decl, &erase_decl)) goto FAILED; + case DECL_ALIAS: + if (!sema_analyse_alias(context, decl, &erase_decl)) goto FAILED; break; case DECL_POISONED: case DECL_IMPORT: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index a14c3a550..2ef5bce52 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -798,7 +798,7 @@ static inline bool sema_cast_ident_rvalue(SemaContext *context, Expr *expr) case DECL_IMPORT: case DECL_ATTRIBUTE: case DECL_CT_ASSERT: - case DECL_DEFINE: + case DECL_ALIAS: case DECL_CT_ECHO: UNREACHABLE case DECL_POISONED: @@ -1065,7 +1065,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, case DECL_MACRO: message = "Macros from other modules must be prefixed with the module name."; break; - case DECL_DEFINE: + case DECL_ALIAS: message = "Aliases from other modules must be prefixed with the module name."; break; case DECL_FAULT: @@ -1085,6 +1085,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, sema_display_deprecated_warning_on_use(decl, expr->span); unit_register_external_symbol(context, decl); + decl = decl_flatten(decl); if (decl->decl_kind == DECL_VAR) { decl->var.is_read = true; @@ -9089,7 +9090,7 @@ static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr) case DECL_IMPORT: case DECL_LABEL: case DECL_MACRO: - case DECL_DEFINE: + case DECL_ALIAS: RETURN_SEMA_ERROR(main_var, "'%s' does not have an external name.", decl->name); case DECL_FAULT: goto RETURN_CT; diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index 62f0cb5f8..93cdc13c1 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -594,7 +594,7 @@ RETRY: case DECL_TYPEDEF: sema_trace_type_liveness(decl->type); return; - case DECL_DEFINE: + case DECL_ALIAS: decl = decl->define_decl.alias; goto RETRY; case DECL_ENUM: diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index feb0b4089..c7bdafe68 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -256,7 +256,7 @@ static bool sema_resolve_type_identifier(SemaContext *context, TypeInfo *type_in return true; } FALLTHROUGH; - case DECL_DEFINE: + case DECL_ALIAS: case DECL_FUNC: case DECL_ENUM_CONSTANT: case DECL_IMPORT: diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index e710fa7bc..fd32f7d5c 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -240,7 +240,7 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls) case DECL_BODYPARAM: case DECL_GROUP: UNREACHABLE - case DECL_DEFINE: + case DECL_ALIAS: case DECL_DISTINCT: case DECL_ENUM: case DECL_STRUCT: diff --git a/test/test_suite/define/alias_alias.c3t b/test/test_suite/define/alias_alias.c3t new file mode 100644 index 000000000..71f075c94 --- /dev/null +++ b/test/test_suite/define/alias_alias.c3t @@ -0,0 +1,21 @@ +// #target: macos-x64 +module test; +int x = 0; +alias y = x; +alias z = y; +alias w = z; +fn int main() +{ + z = 4; + w = 3; + return 0; +} + +/* #expect: test.ll + +entry: + store i32 4, ptr @test.x, align 4 + store i32 3, ptr @test.x, align 4 + ret i32 0 +} +