diff --git a/releasenotes.md b/releasenotes.md index 08f8050a5..04ececc9b 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -79,6 +79,7 @@ - Bug when reporting error in a macro return would crash the compiler #2326. - Short body return expression would not have the correct span. - Fix issue where recursively creating a dir would be incorrectly marked as a failure the first time. +- `@format` did not work correctly with macros #2341. ### Stdlib changes - Improve contract for readline. #2280 diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index e622469bd..5f0eb42f4 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -1722,6 +1722,21 @@ static inline ArrayIndex sema_len_from_expr(Expr *expr) return range_const_len(&expr->slice_expr.range); } +INLINE Type *sema_get_va_type(SemaContext *context, Expr *expr, Variadic variadic) +{ + if (variadic == VARIADIC_RAW) + { + if (expr->resolve_status != RESOLVE_DONE) + { + expr = copy_expr_single(expr); + if (!sema_analyse_expr(context, expr)) return poisoned_type; + } + return type_flatten(expr->type); + } + assert(expr->expr_kind == EXPR_MAKE_ANY); + return type_flatten(expr->make_any_expr.typeid->const_expr.typeid); +} + INLINE bool sema_call_evaluate_arguments(SemaContext *context, CalledDecl *callee, Expr *call, bool *optional, bool *no_match_ref) { @@ -2074,9 +2089,8 @@ NEXT_FLAG: } if (idx == vacount) goto TOO_FEW_ARGUMENTS; expr = vaargs[idx]; - assert(expr->expr_kind == EXPR_MAKE_ANY); - Type *type = expr->make_any_expr.typeid->const_expr.typeid; - type = type_flatten(type); + Type *type = sema_get_va_type(context, expr, variadic); + if (!type_ok(type)) return false; // Possible variable width if (c == '*') @@ -2089,9 +2103,8 @@ NEXT_FLAG: c = data[i]; if (++idx == vacount) goto TOO_FEW_ARGUMENTS; expr = vaargs[idx]; - assert(expr->expr_kind == EXPR_MAKE_ANY); - type = expr->make_any_expr.typeid->const_expr.typeid; - type = type_flatten(type); + type = sema_get_va_type(context, expr, variadic); + if (!type_ok(type)) return false; } else { @@ -2115,9 +2128,7 @@ NEXT_FLAG: c = data[i]; if (++idx == vacount) goto TOO_FEW_ARGUMENTS; expr = vaargs[idx]; - assert(expr->expr_kind == EXPR_MAKE_ANY); - type = expr->make_any_expr.typeid->const_expr.typeid; - type = type_flatten(type); + if (!type_ok(type)) return false; } else { diff --git a/test/test_suite/attributes/format_macros.c3t b/test/test_suite/attributes/format_macros.c3t new file mode 100644 index 000000000..31b6b7080 --- /dev/null +++ b/test/test_suite/attributes/format_macros.c3t @@ -0,0 +1,9 @@ +import std; + +module abort_test; + +fn int main() +{ + int n; + abort("%d", n); +} \ No newline at end of file