Fix stringify of $vaexpr #2301.

This commit is contained in:
Christoffer Lerno
2025-07-15 17:13:10 +02:00
parent 3cce90bba1
commit af91f35017
4 changed files with 70 additions and 9 deletions

View File

@@ -51,6 +51,7 @@
- Fixed bug splatting constants into constants.
- Resize bug when resizing memory down in ArenaAllocator, DynamicArenaAllocator, BackedArenaAllocator.
- Error message for missing arg incorrect for methods with zero args #2296.
- Fix stringify of $vaexpr #2301.
### Stdlib changes
- Improve contract for readline. #2280

View File

@@ -659,7 +659,7 @@ static Expr *parse_ct_stringify(ParseContext *c, Expr *left, SourceSpan lhs_star
ASSIGN_EXPR_OR_RET(Expr *inner, parse_expr(c), poisoned_expr);
const char *end = c->lexer.lexing_start - 1;
CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr);
if (inner->expr_kind == EXPR_HASH_IDENT)
if (inner->expr_kind == EXPR_HASH_IDENT || (inner->expr_kind == EXPR_CT_ARG && inner->ct_arg_expr.type == TOKEN_CT_VAEXPR))
{
Expr *expr = expr_new(EXPR_STRINGIFY, start_span);
expr->inner_expr = inner;

View File

@@ -10591,18 +10591,31 @@ static inline bool sema_expr_analyse_ct_stringify(SemaContext *context, Expr *ex
{
Expr *inner = expr->inner_expr;
// Only hash ident style stringify reaches here.
ASSERT_SPAN(expr, inner->expr_kind == EXPR_HASH_IDENT);
while (true)
{
Decl *decl = sema_resolve_symbol(context, inner->ct_ident_expr.identifier, NULL, inner->span);
if (!decl) return false;
inner = decl->var.init_expr;
while (inner->expr_kind == EXPR_OTHER_CONTEXT)
switch (inner->expr_kind)
{
context = inner->expr_other_context.context;
inner = inner->expr_other_context.inner;
case EXPR_CT_ARG:
{
ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(inner->ct_arg_expr.arg), NULL), false);
inner = arg_expr;
continue;
}
case EXPR_OTHER_CONTEXT:
context = inner->expr_other_context.context;
inner = inner->expr_other_context.inner;
continue;
case EXPR_HASH_IDENT:
{
Decl *decl = sema_resolve_symbol(context, inner->ct_ident_expr.identifier, NULL, inner->span);
if (!decl) return false;
inner = decl->var.init_expr;
continue;
}
default:
break;
}
if (inner->expr_kind != EXPR_HASH_IDENT) break;
break;
}
const char *desc = span_to_string(inner->span);
if (!desc)

View File

@@ -0,0 +1,47 @@
// #target: macos-x64
module test;
import std::io;
fn int main(String[] args)
{
String a = @foo1(args);
String b = @foo2(args);
String c = @foo3(args);
return 0;
}
macro @foo1(#expr)
{
return $stringify(#expr);
}
macro @foo2(...)
{
return $stringify($vaexpr[0]);
}
macro @foo3(#expr)
{
return @foo2(#expr);
}
/* #expect: test.ll
@.str = private unnamed_addr constant [5 x i8] c"args\00", align 1
@.str.1 = private unnamed_addr constant [5 x i8] c"args\00", align 1
@.str.2 = private unnamed_addr constant [5 x i8] c"args\00", align 1
define i32 @test.main(ptr %0, i64 %1) #0 {
entry:
%args = alloca %"char[][]", align 8
%a = alloca %"char[]", align 8
%b = alloca %"char[]", align 8
%c = alloca %"char[]", align 8
store ptr %0, ptr %args, align 8
%ptradd = getelementptr inbounds i8, ptr %args, i64 8
store i64 %1, ptr %ptradd, align 8
store %"char[]" { ptr @.str, i64 4 }, ptr %a, align 8
store %"char[]" { ptr @.str.1, i64 4 }, ptr %b, align 8
store %"char[]" { ptr @.str.2, i64 4 }, ptr %c, align 8
ret i32 0
}