From 0b52819090ca820d14f9441058e96c539288b1e5 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 27 Nov 2025 12:53:12 +0100 Subject: [PATCH] - Bug on rethrow in return with defer #2603. --- releasenotes.md | 1 + src/compiler/llvm_codegen_expr.c | 5 ++-- src/compiler/llvm_codegen_function.c | 1 + .../statements/defer_rethrow_return.c3t | 30 +++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 test/test_suite/statements/defer_rethrow_return.c3t diff --git a/releasenotes.md b/releasenotes.md index d76791c5d..c12c93d23 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -45,6 +45,7 @@ - `String.to_integer` does not correctly return in some cases where it should #2590. - Resolving a missing property on a const enum with inline, reached an assert #2597. - Unexpected maybe-deref subscript error with out parameter #2600. +- Bug on rethrow in return with defer #2603. ### Stdlib changes - Add `CGFloat` `CGPoint` `CGSize` `CGRect` types to core_foundation (macOS). diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 52d33bdaf..fe7210f95 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -4379,8 +4379,9 @@ static inline void llvm_emit_rethrow_expr(GenContext *c, BEValue *be_value, Expr // Restore. POP_CATCH(); + // Emit success and to end. - llvm_emit_br(c, no_err_block); + bool emit_no_err = llvm_emit_br(c, no_err_block); // Emit else llvm_emit_block(c, guard_block); @@ -4406,7 +4407,7 @@ static inline void llvm_emit_rethrow_expr(GenContext *c, BEValue *be_value, Expr } } - llvm_emit_block(c, no_err_block); + if (emit_no_err) llvm_emit_block(c, no_err_block); } diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index bace67f7b..a085d8a88 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -353,6 +353,7 @@ void llvm_emit_return_abi(GenContext *c, BEValue *return_value, BEValue *optiona } if (prototype->ret_rewrite != RET_NORMAL) { + if (return_value && prototype->ret_rewrite == RET_OPTIONAL_VALUE) { ASSERT(return_value->value); diff --git a/test/test_suite/statements/defer_rethrow_return.c3t b/test/test_suite/statements/defer_rethrow_return.c3t new file mode 100644 index 000000000..bf0e7ef38 --- /dev/null +++ b/test/test_suite/statements/defer_rethrow_return.c3t @@ -0,0 +1,30 @@ +// #target: macos-aarch64 +module test; +fn int main() +{ + foo()!!; + return 0; +} + +fn int? foo() +{ + defer thing(); + return NOT_FOUND?!; +} + +fn void thing() {} + +/* #expect: test.ll + +define i64 @test.foo(ptr %0) #0 { +entry: + %reterr = alloca i64, align 8 + %error_var = alloca i64, align 8 + store i64 ptrtoint (ptr @std.core.builtin.NOT_FOUND to i64), ptr %error_var, align 8 + br label %guard_block + +guard_block: ; preds = %entry + call void @test.thing() + %1 = load i64, ptr %error_var, align 8 + ret i64 %1 +}