From 967f14148f8da7e9ede53e64ebdd0ca58086f2e8 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 10 Oct 2024 13:42:12 +0200 Subject: [PATCH] Bug when defers and $if were combined in a macro, which would cause miscompilation. --- releasenotes.md | 1 + src/compiler/sema_stmts.c | 2 +- test/test_suite/compile_time/ct_if.c3t | 1 + .../test_suite/compile_time/ct_if_folding.c3t | 32 +++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/test_suite/compile_time/ct_if_folding.c3t diff --git a/releasenotes.md b/releasenotes.md index fe2d0e26c..8836c3e9f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -21,6 +21,7 @@ - Fix broken sincos function. - Bug when a continue is copied in a defer. - Compiler error when any/interface initialized using {} #1533. +- Bug when defers and $if were combined in a macro, which would cause miscompilation. ### Stdlib changes - Remove unintended print of `char[]` as String diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index db0556cbd..d1e786d68 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -2148,7 +2148,7 @@ static inline bool sema_analyse_compound_statement_no_scope(SemaContext *context all_ok = false; } } - AstId *next = ast ? &ast->next : &compound_statement->compound_stmt.first_stmt; + AstId *next = ast ? &ast_last(ast)->next : &compound_statement->compound_stmt.first_stmt; context_pop_defers(context, next); return all_ok; } diff --git a/test/test_suite/compile_time/ct_if.c3t b/test/test_suite/compile_time/ct_if.c3t index 8770f2e24..fe7b39df6 100644 --- a/test/test_suite/compile_time/ct_if.c3t +++ b/test/test_suite/compile_time/ct_if.c3t @@ -1,3 +1,4 @@ +// #target: macos-x64 int x @if(false) = 1; int d @if(true) = 5; diff --git a/test/test_suite/compile_time/ct_if_folding.c3t b/test/test_suite/compile_time/ct_if_folding.c3t new file mode 100644 index 000000000..97126d475 --- /dev/null +++ b/test/test_suite/compile_time/ct_if_folding.c3t @@ -0,0 +1,32 @@ +// #target: macos-x64 +module test; + +macro void @test(bool $skip = false) +{ + $if $skip: + + $else + int a; + int b; + defer + { + a = b; + } + $endif +} + +fn int main() { + @test(); + return 0; +} +/* #expect: test.ll + +entry: + %a = alloca i32, align 4 + %b = alloca i32, align 4 + store i32 0, ptr %a, align 4 + store i32 0, ptr %b, align 4 + %0 = load i32, ptr %b, align 4 + store i32 %0, ptr %a, align 4 + ret i32 0 +}