diff --git a/releasenotes.md b/releasenotes.md index f85bd6502..4eab1377e 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -86,6 +86,7 @@ - Assigning a const zero to an aliased distinct caused an error. - `--path` is now properly respected. - `--test` will now provide the full filename and the column. +- Fix of bug in `defer (catch err)` with a direct return error. ### Stdlib changes diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 735149698..30b68fc0d 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -223,7 +223,11 @@ static inline void llvm_emit_return(GenContext *c, Ast *ast) if (ast->return_stmt.cleanup_fail) { llvm_value_rvalue(c, &be_value); + LLVMValueRef error_out = llvm_emit_alloca_aligned(c, type_anyfault, "reterr"); + llvm_store_to_ptr(c, error_out, &be_value); + c->defer_error_var = error_out; llvm_emit_statement_chain(c, ast->return_stmt.cleanup_fail); + c->defer_error_var = NULL; } llvm_emit_return_abi(c, NULL, &be_value); return; diff --git a/test/src/tester.py b/test/src/tester.py index cff92f73e..66a4fdbdc 100644 --- a/test/src/tester.py +++ b/test/src/tester.py @@ -105,8 +105,8 @@ class Issues: self.exit_error("Illegal error result: " + line) if not self.check_line(parts[0], parts[1], parts[2], parts[3], parts[4]): self.set_failed() - print("Unexpected " + parts[0].lower() + " in " + parts[1] + " line " + parts[2] + ":", end="") - print('"' + parts[3] + '"') + print("Unexpected " + parts[0].lower() + " in " + os.path.basename(parts[1]) + " line " + parts[2] + ":", end="") + print('"' + parts[4] + '"') if len(self.errors) > 0: self.set_failed() print("Expected errors that never occurred:") diff --git a/test/test_suite/defer/defer_catch_direct_error.c3t b/test/test_suite/defer/defer_catch_direct_error.c3t new file mode 100644 index 000000000..98c0d06be --- /dev/null +++ b/test/test_suite/defer/defer_catch_direct_error.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test; +import std::io; +fn void! example_fn() +{ + defer try { + int a = 1; + } + + defer (catch err) { + anyfault f = err; + } + return io::IoError.FILE_NOT_FOUND?; +} + +/* #expect: test.ll + +define i64 @test.example_fn() #0 { +entry: + %reterr = alloca i64, align 8 + %err = alloca i64, align 8 + %f = alloca i64, align 8 + store i64 ptrtoint (ptr @"std.io.IoError$FILE_NOT_FOUND" to i64), ptr %reterr, align 8 + %0 = load i64, ptr %reterr, align 8 + store i64 %0, ptr %err, align 8 + %1 = load i64, ptr %err, align 8 + store i64 %1, ptr %f, align 8 + ret i64 ptrtoint (ptr @"std.io.IoError$FILE_NOT_FOUND" to i64) +}