From 32675161c4946592c1d9104b02f0ce7eaeda24f7 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 22 Jan 2026 19:47:37 +0100 Subject: [PATCH] - Attrdef eval environment lacked rtype, causing error on invalid args #2797 --- releasenotes.md | 1 + src/compiler/sema_decls.c | 6 ++++-- test/test_suite/attributes/attr_eval_with_return.c3 | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 test/test_suite/attributes/attr_eval_with_return.c3 diff --git a/releasenotes.md b/releasenotes.md index a397ae3fd..6abff1ebe 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -105,6 +105,7 @@ - Instantiating an alias of a user-defined type was not properly caught #2798 - Too deeply nested scopes was a fatal crash and not a regular semantic error. #2796 - Recursive definition of tag not detected with nested tag/tagof #2790 +- Attrdef eval environment lacked rtype, causing error on invalid args #2797 ### Stdlib changes - Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads. diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index b3b7d1c72..5b007ace9 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -3668,8 +3668,7 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA SemaContext eval_context; sema_context_init(&eval_context, attr_decl->unit); eval_context.macro_call_depth = context->macro_call_depth + 1; - eval_context.call_env = (CallEnv) { .kind = CALL_ENV_ATTR, .attr_declaration = decl }; - + eval_context.call_env = (CallEnv) { .kind = CALL_ENV_ATTR, .attr_declaration = decl, }; // We copy the compilation unit. eval_context.compilation_unit = context->unit; @@ -3683,6 +3682,7 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA if (!sema_resolve_type_info(context, type_infoptr(param->var.type_info), RESOLVE_TYPE_DEFAULT)) return false; Type *type = typeget(param->var.type_info); ASSERT_SPAN(decl, type); + eval_context.rtype = type; if (!sema_analyse_inferred_expr(context, type, expr, NULL)) goto ERR; if (!cast_implicit(context, expr, type, false)) goto ERR; if (!sema_cast_const(expr)) @@ -3693,6 +3693,7 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA } else { + eval_context.rtype = type_void; if (!sema_analyse_ct_expr(context, args[j])) goto ERR; } params[j]->var.init_expr = expr; @@ -3701,6 +3702,7 @@ static inline bool sema_analyse_custom_attribute(SemaContext *context, ResolvedA // (Yes this is messy) sema_add_local(&eval_context, params[j]); } + eval_context.rtype = type_void; // Now we've added everything to the evaluation context, so we can (recursively) // apply it to the contained attributes, which in turn may be derived attributes. if (!sema_analyse_attributes_inner(&eval_context, attr_data_ref, decl, attributes, domain, top ? top : attr_decl, erase_decl)) goto ERR; diff --git a/test/test_suite/attributes/attr_eval_with_return.c3 b/test/test_suite/attributes/attr_eval_with_return.c3 new file mode 100644 index 000000000..7818f9cb9 --- /dev/null +++ b/test/test_suite/attributes/attr_eval_with_return.c3 @@ -0,0 +1,4 @@ +attrdef @Aa(x) = @tag("", @pool() { return; }); // #error: Expected a constant value here, usage is: '@tag(name, value)' + +fn void a() @Aa({}) +{}