Bug in AST copying would make operator overloading like += compile incorrectly #2217

This commit is contained in:
Christoffer Lerno
2025-06-17 16:01:44 +02:00
parent 95137db64b
commit 99e29bff8d
4 changed files with 38 additions and 5 deletions

View File

@@ -43,6 +43,7 @@
- In some cases, the compiler would dereference a compile time null. #2215
- Incorrect codegen if a macro ends with unreachable and is assigned to something. #2210
- Fix error for named arguments-order with compile-time arguments #2212
- Bug in AST copying would make operator overloading like `+=` compile incorrectly #2217.
### Stdlib changes
- Deprecate `String.is_zstr` and `String.quick_zstr` #2188.

View File

@@ -297,8 +297,8 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
switch (source_expr->expr_kind)
{
case EXPR_TWO:
MACRO_COPY_EXPR(source_expr->two_expr.first);
MACRO_COPY_EXPR(source_expr->two_expr.last);
MACRO_COPY_EXPR(expr->two_expr.first);
MACRO_COPY_EXPR(expr->two_expr.last);
return expr;
case EXPR_TYPECALL:
case EXPR_CT_SUBSCRIPT:
@@ -333,7 +333,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
}
return expr;
case EXPR_MEMBER_GET:
fixup_decl(c, &source_expr->member_get_expr);
fixup_decl(c, &expr->member_get_expr);
break;
case EXPR_SWIZZLE:
MACRO_COPY_EXPRID(expr->swizzle_expr.parent);
@@ -525,7 +525,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
MACRO_COPY_TYPE(expr->expr_compound_literal.type_info);
return expr;
case EXPR_POISONED:
return source_expr;
return expr;
case EXPR_RETHROW:
MACRO_COPY_EXPR(expr->rethrow_expr.inner);
return expr;

View File

@@ -221,9 +221,9 @@ bool expr_may_addr(Expr *expr)
case EXPR_ACCESS_RESOLVED:
return expr_may_addr(expr->access_resolved_expr.parent);
case EXPR_SUBSCRIPT:
case EXPR_SLICE:
case EXPR_MEMBER_GET:
return true;
case EXPR_SLICE:
case EXPR_BENCHMARK_HOOK:
case EXPR_TEST_HOOK:
case EXPR_VECTOR_FROM_ARRAY:

View File

@@ -0,0 +1,32 @@
// #target: macos-aarch64
module test;
typedef Foo = int;
macro Foo Foo.add(self1, Foo other) @operator(+) => self1;
macro Foo Foo.add_self(&self, Foo other) @operator(+=) => *self = *self + other;
macro Foo Foo.test(&self2) => *self2 += (Foo)0;
fn int main()
{
Foo b;
defer b.test();
return 0;
}
/* #expect: test.ll
define i32 @main() #0 {
entry:
%b = alloca i32, align 4
%self1 = alloca i32, align 4
store i32 0, ptr %b, align 4
%neq = icmp ne ptr %b, null
call void @llvm.assume(i1 %neq)
%neq1 = icmp ne ptr %b, null
call void @llvm.assume(i1 %neq1)
%0 = load i32, ptr %b, align 4
store i32 %0, ptr %self1, align 4
%1 = load i32, ptr %self1, align 4
store i32 %1, ptr %b, align 4
ret i32 0
}