diff --git a/lib/std/math/math_nolibc/sincos.c3 b/lib/std/math/math_nolibc/sincos.c3 index 720bdfe46..6c2aed421 100644 --- a/lib/std/math/math_nolibc/sincos.c3 +++ b/lib/std/math/math_nolibc/sincos.c3 @@ -16,7 +16,7 @@ module std::math::nolibc @if(env::NO_LIBC); * ==================================================== */ -fn void sincosf(float x, float *sin, float *cos) @extern("sincosf") @weak @nostrip +fn void sincosf(float x, float *sin, float *cos) @extern("__sincosf") @weak @nostrip { uint ix = bitcast(x, uint); @@ -105,7 +105,7 @@ fn void sincosf(float x, float *sin, float *cos) @extern("sincosf") @weak @nostr } -fn void sincos(double x, double *sin, double *cos) @extern("sincos") @weak @nostrip +fn void sincos(double x, double *sin, double *cos) @extern("__sincos") @weak @nostrip { // High word of x. uint ix = (uint)(bitcast(x, ulong) >> 32); diff --git a/releasenotes.md b/releasenotes.md index acc5625f0..7de44e93a 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -18,6 +18,7 @@ - Using no module with `-` would reject the program. - Unintended deref of pointers with methods caused regression with hash function. - Fix broken sincos function. +- Bug when a continue is copied in a defer. ### Stdlib changes - Remove unintended print of `char[]` as String diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 8c0f3ed1d..558cefe45 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -1071,6 +1071,7 @@ void llvm_emit_break(GenContext *c, Ast *ast) void llvm_emit_continue(GenContext *c, Ast *ast) { + assert(ast->contbreak_stmt.is_resolved); llvm_emit_statement_chain(c, ast->contbreak_stmt.defers); Ast *jump_target = astptr(ast->contbreak_stmt.ast); LLVMBasicBlockRef jump; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 5535983c4..db0556cbd 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -247,6 +247,7 @@ static inline bool sema_analyse_continue_stmt(SemaContext *context, Ast *stateme // Link the parent and add the defers. statement->contbreak_stmt.ast = astid(parent); + statement->contbreak_stmt.is_resolved = true; statement->contbreak_stmt.defers = context_get_defers(context, context->active_scope.defer_last, defer_id, true); return true; } diff --git a/test/test_suite/statements/defer_break.c3t b/test/test_suite/statements/defer_break.c3t index df8159196..19f166d84 100644 --- a/test/test_suite/statements/defer_break.c3t +++ b/test/test_suite/statements/defer_break.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 module foo; extern fn void printf(char* message, ...); diff --git a/test/test_suite/statements/defer_break_switch.c3t b/test/test_suite/statements/defer_break_switch.c3t index abec39467..2e03a42c3 100644 --- a/test/test_suite/statements/defer_break_switch.c3t +++ b/test/test_suite/statements/defer_break_switch.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 fn void test1() {} diff --git a/test/test_suite/statements/defer_continue_bug.c3t b/test/test_suite/statements/defer_continue_bug.c3t new file mode 100644 index 000000000..c8c89e5d0 --- /dev/null +++ b/test/test_suite/statements/defer_continue_bug.c3t @@ -0,0 +1,59 @@ +// #target: macos-aarch64 +module test; + +fn int main() +{ + int[4] x = { 1, 4, 5, 7 }; + defer + { + foreach (i : x) + { + if (i % 2 == 0) continue; + int a = 123; + } + } + return 0; +} + +/* #expect: test.ll + +entry: + %x = alloca [4 x i32], align 4 + %.anon = alloca i64, align 8 + %i = alloca i32, align 4 + %a = alloca i32, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 16, i1 false) + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %loop.inc, %entry + %0 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 4, %0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + %ptroffset = getelementptr inbounds [4 x i8], ptr %x, i64 %1 + %2 = load i32, ptr %ptroffset, align 4 + store i32 %2, ptr %i, align 4 + %3 = load i32, ptr %i, align 4 + %smod = srem i32 %3, 2 + %eq = icmp eq i32 %smod, 0 + br i1 %eq, label %if.then, label %if.exit + +if.then: ; preds = %loop.body + br label %loop.inc + +if.exit: ; preds = %loop.body + store i32 123, ptr %a, align 4 + br label %loop.inc + +loop.inc: ; preds = %if.exit, %if.then + %4 = load i64, ptr %.anon, align 8 + %addnuw = add nuw i64 %4, 1 + store i64 %addnuw, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + ret i32 0 +} diff --git a/test/test_suite/statements/defer_in_defer.c3t b/test/test_suite/statements/defer_in_defer.c3t index 91211749a..eefb0a289 100644 --- a/test/test_suite/statements/defer_in_defer.c3t +++ b/test/test_suite/statements/defer_in_defer.c3t @@ -1,4 +1,4 @@ - +// #target: macos-aarch64 fn void test1() {} fn void test2() {} fn void test3() {} diff --git a/test/test_suite/statements/defer_next_switch.c3t b/test/test_suite/statements/defer_next_switch.c3t index 011484cd5..0c0afb59d 100644 --- a/test/test_suite/statements/defer_next_switch.c3t +++ b/test/test_suite/statements/defer_next_switch.c3t @@ -1,4 +1,4 @@ - +// #target: macos-aarch64 fn void test1() {}