From 6d9906db0ae9233afaf18bc3befaf27ecc72ec1c Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 31 Jul 2025 16:21:50 +0200 Subject: [PATCH] Fix implicit linking from macros when it's not valid to add dependencies. --- src/compiler/parse_global.c | 2 +- src/compiler/sema_expr.c | 10 ++++++---- test/test_suite/globals/links_global.c3 | 13 +++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 test/test_suite/globals/links_global.c3 diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 2a3611c5f..a5b2be072 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -266,9 +266,9 @@ bool parse_module(ParseContext *c, AstId contracts) { unsigned args = vec_size(attr->exprs); if (args < 1) RETURN_PRINT_ERROR_AT(false, attr, "'@link' needs at least 1 argument."); - } vec_add(c->unit->attr_links, attr); continue; + } case ATTRIBUTE_IF: if (c->unit->if_attr) RETURN_PRINT_ERROR_AT(false, attr, "'@if' appeared more than once."); c->unit->if_attr = attr; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index fef01bc98..f17649283 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2571,12 +2571,13 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s bool is_always_const = decl->func_decl.signature.attrs.always_const; if (decl->resolved_attributes && decl->attrs_resolved && decl->attrs_resolved->links) { - Decl *func = context->call_env.current_function; - if (!func) + if (context->call_env.kind != CALL_ENV_FUNCTION && context->call_env.kind != CALL_ENV_FUNCTION_STATIC) { - RETURN_SEMA_ERROR(call_expr, "Cannot call macro with '@links' outside of a function."); + goto SKIP_LINK; } - assert(func->resolved_attributes); + Decl *func = context->call_env.current_function; + ASSERT_SPAN(func, func); + ASSERT_SPAN(func, func->resolved_attributes); if (!func->attrs_resolved) { func->attrs_resolved = MALLOCS(ResolvedAttrData); @@ -2589,6 +2590,7 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s } func->attrs_resolved->links = updated; } + SKIP_LINK:; bool is_outer = call_expr->call_expr.is_outer_call; ASSERT_SPAN(call_expr, decl->decl_kind == DECL_MACRO); diff --git a/test/test_suite/globals/links_global.c3 b/test/test_suite/globals/links_global.c3 new file mode 100644 index 000000000..001ae7f90 --- /dev/null +++ b/test/test_suite/globals/links_global.c3 @@ -0,0 +1,13 @@ +module test; +import std; +import some_module; + +fn int main(String[] args) +{ + int z = some_module::A_CONST{22}; + return 0; +} + +module some_module { F }; +import std; +const A_CONST = 12 + 2 * math::log2(F / 25); // #error: This expression cannot be evaluated at compile time \ No newline at end of file