From dc1e5323abe427c1c1f52f5784b5d28a908c1f44 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 27 Jun 2025 23:00:14 +0200 Subject: [PATCH] Segfault in the compiler when using a bitstruct constant defined using a cast with an operator #2248. --- releasenotes.md | 1 + src/compiler/sema_expr.c | 4 ++- .../bitstruct/bitstruct_no_inline_bit.c3t | 29 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/test_suite/bitstruct/bitstruct_no_inline_bit.c3t diff --git a/releasenotes.md b/releasenotes.md index 9cb6d661c..b7fa8062c 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -68,6 +68,7 @@ - Assert comparing untyped lists #2240. - Fix bugs relating to optional interface addr-of #2244. - Compiler null pointer when building a static-lib with -o somedir/... #2246 +- Segfault in the compiler when using a bitstruct constant defined using a cast with an operator #2248. ### Stdlib changes - Deprecate `String.is_zstr` and `String.quick_zstr` #2188. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 6557300e1..2084dbf8d 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -7515,6 +7515,8 @@ static bool sema_expr_analyse_bit(SemaContext *context, Expr *expr, Expr *left, } else if (is_bitstruct) { + // Avoid merging with value casts, eg (Bitstruct)1 + if (!expr_is_const_initializer(left) || !expr_is_const_initializer(right)) goto DONE; ConstInitializer *merged = sema_merge_bitstruct_const_initializers(left->const_expr.initializer, right->const_expr.initializer, op); expr->const_expr.initializer = merged; @@ -7537,7 +7539,7 @@ static bool sema_expr_analyse_bit(SemaContext *context, Expr *expr, Expr *left, } } } - +DONE: // 5. Assign the type expr_binary_unify_failability(expr, left, right); return true; diff --git a/test/test_suite/bitstruct/bitstruct_no_inline_bit.c3t b/test/test_suite/bitstruct/bitstruct_no_inline_bit.c3t new file mode 100644 index 000000000..50106b39f --- /dev/null +++ b/test/test_suite/bitstruct/bitstruct_no_inline_bit.c3t @@ -0,0 +1,29 @@ +// #target: macos-x64 +module test; + +bitstruct BitstructFlags : uint +{ + bool first; + bool second; +} +const BitstructFlags B_FIRST = { true, false }; +const BitstructFlags B_FIRST2 = (BitstructFlags) 1; +const BitstructFlags B_SECOND = { false, true }; + +fn void main() +{ + BitstructFlags x = B_FIRST2 | B_SECOND; +} + +/* #expect: test.ll + +@test.B_FIRST = local_unnamed_addr constant i32 1, align 4 +@test.B_FIRST2 = local_unnamed_addr constant i32 1, align 4 +@test.B_SECOND = local_unnamed_addr constant i32 2, align 4 + +define void @test.main() #0 { +entry: + %x = alloca i32, align 4 + store i32 1, ptr %x, align 4 + ret void +} \ No newline at end of file