diff --git a/releasenotes.md b/releasenotes.md index 5a36d8c5f..d2a9e7254 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -3,6 +3,7 @@ ## 0.7.7 Change list ### Changes / improvements +- Error when using $vaarg/$vacount/$vasplat and similar in a macro without vaargs #2510. ### Fixes - Bug in `io::write_using_write_byte`. diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 394d793e9..56536615f 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1800,6 +1800,7 @@ struct SemaContext_ Type *expected_block_type; Ast **block_returns; Expr **macro_varargs; + bool macro_has_vaargs; Decl **macro_params; bool macro_has_ensures; Decl** ct_locals; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 75c6c5f38..6e36092a8 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -2695,7 +2695,8 @@ static inline bool sema_expr_setup_call_analysis(SemaContext *context, CalledDec expr->expr_other_context.inner = expr_inner; expr->expr_other_context.context = context; } - macro_context->macro_varargs = callee->macro && callee->signature->variadic == VARIADIC_RAW ? call_expr->call_expr.varargs : NULL; + macro_context->macro_has_vaargs = callee->macro && callee->signature->variadic == VARIADIC_RAW; + macro_context->macro_varargs = macro_context->macro_has_vaargs ? call_expr->call_expr.varargs : NULL; macro_context->original_inline_line = context->original_inline_line ? context->original_inline_line : call_expr->span.row; macro_context->original_module = context->original_module ? context->original_module : context->compilation_unit->module; macro_context->macro_params = params; @@ -10986,9 +10987,9 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty { ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_RUNNING); TokenType type = expr->ct_arg_expr.type; - if (!context->current_macro) + if (!context->macro_has_vaargs) { - RETURN_SEMA_ERROR(expr, "'%s' can only be used inside of a macro.", token_type_to_string(type)); + RETURN_SEMA_ERROR(expr, "'%s' can only be used inside of a macro with untyped vaargs.", token_type_to_string(type)); } switch (type) { diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index df16cd5e7..bcb6a9eeb 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -403,9 +403,9 @@ INLINE bool sema_resolve_typefrom(SemaContext *context, TypeInfo *type_info, Res // $vatype(...) INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info) { - if (!context->current_macro) + if (!context->macro_has_vaargs) { - RETURN_SEMA_ERROR(type_info, "'%s' can only be used inside of a macro.", token_type_to_string(TOKEN_CT_VATYPE)); + RETURN_SEMA_ERROR(type_info, "'%s' can only be used inside of a macro with untyped vaargs.", token_type_to_string(TOKEN_CT_VATYPE)); } ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, type_info->unresolved_type_expr, NULL), false); if (!sema_analyse_expr(context, arg_expr)) return false; diff --git a/test/test_suite/macros/macro_vaarg_no.c3 b/test/test_suite/macros/macro_vaarg_no.c3 new file mode 100644 index 000000000..2e0630300 --- /dev/null +++ b/test/test_suite/macros/macro_vaarg_no.c3 @@ -0,0 +1,14 @@ +import std; + +macro void example(String... x) +{ + $for var $i = 0; $i < $vacount; $i++: // #error: can only be used inside of a macro with untyped + io::printn($vaarg[$i]); + $endfor +} + +fn void main() +{ + example(); +} +