https://github.com/BStott6 updated https://github.com/llvm/llvm-project/pull/166798
>From eab7dd02ab238c0029c2f0fc9a7f8f3ce1ab055c Mon Sep 17 00:00:00 2001 From: BStott <[email protected]> Date: Thu, 6 Nov 2025 16:25:54 +0000 Subject: [PATCH 1/6] [Clang][CodeGen] Use EmitLoadOfLValue instead of EmitLoadOfScalar to get LHS for complex compound assignment --- clang/lib/CodeGen/CGExprComplex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index f8a946a76554a..47435758fcde7 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -1283,7 +1283,7 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, else OpInfo.LHS = EmitComplexToComplexCast(LHSVal, LHSTy, OpInfo.Ty, Loc); } else { - llvm::Value *LHSVal = CGF.EmitLoadOfScalar(LHS, Loc); + llvm::Value *LHSVal = CGF.EmitLoadOfLValue(LHS, Loc).getScalarVal(); // For floating point real operands we can directly pass the scalar form // to the binary operator emission and potentially get more efficient code. if (LHSTy->isRealFloatingType()) { >From ab4e0ee3d2004f8f53f80764329d45aa5359268b Mon Sep 17 00:00:00 2001 From: BStott <[email protected]> Date: Fri, 7 Nov 2025 16:39:58 +0000 Subject: [PATCH 2/6] Replace EmitStoreOfScalar with EmitStoreThroughLValue too --- clang/lib/CodeGen/CGExprComplex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 47435758fcde7..d281c4c20616a 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -1318,7 +1318,7 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E, } else { llvm::Value *ResVal = CGF.EmitComplexToScalarConversion(Result, OpInfo.Ty, LHSTy, Loc); - CGF.EmitStoreOfScalar(ResVal, LHS, /*isInit*/ false); + CGF.EmitStoreThroughLValue(RValue::get(ResVal), LHS, /*isInit*/ false); Val = RValue::get(ResVal); } >From 5a203e606a45852242bec4bcab579ef97d35062a Mon Sep 17 00:00:00 2001 From: BStott <[email protected]> Date: Mon, 10 Nov 2025 10:20:27 +0000 Subject: [PATCH 3/6] Introduce test for fixed crash --- .../CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 clang/test/CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c diff --git a/clang/test/CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c b/clang/test/CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c new file mode 100644 index 0000000000000..51ec1e9bc1d3f --- /dev/null +++ b/clang/test/CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c @@ -0,0 +1,10 @@ +// Reduced from https://github.com/llvm/llvm-project/issues/166512 +// RUN: %clang_cc1 %s -emit-obj -std=c23 -fsanitize=bool -o %t + +struct { + int : 7; + int : 7; + int : 7; + bool bobf : 1; +} bits; +int main() { bits.bobf /= __builtin_complex(.125f, .125f); } >From 6ca51cdfa13a2dfbc0dbe97971f9b65888337744 Mon Sep 17 00:00:00 2001 From: BStott <[email protected]> Date: Tue, 11 Nov 2025 16:38:21 +0000 Subject: [PATCH 4/6] Add test for correct codegen --- .../complex-compound-assign-bitfield.c | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 clang/test/CodeGen/complex-compound-assign-bitfield.c diff --git a/clang/test/CodeGen/complex-compound-assign-bitfield.c b/clang/test/CodeGen/complex-compound-assign-bitfield.c new file mode 100644 index 0000000000000..ed02ac80afc2d --- /dev/null +++ b/clang/test/CodeGen/complex-compound-assign-bitfield.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 %s -std=c23 -emit-llvm -o - | FileCheck %s + +struct Bits { + int pad1: 30; + bool b: 1; + int pad2: 1; +}; + +int main(void) { +// CHECK-LABEL: define dso_local i32 @main() #0 { + struct Bits b; + b.b = b.b += __builtin_complex(-1.0f, 0.0f); +// CHECK: %bf.load = load i32, ptr %b, align 4 +// CHECK-NEXT: %bf.lshr = lshr i32 %bf.load, 30 +// CHECK-NEXT: %bf.clear = and i32 %bf.lshr, 1 +// CHECK-NEXT: %bf.cast = trunc i32 %bf.clear to i1 +// CHECK-NEXT: %conv = uitofp i1 %bf.cast to float + +// CHECK: %0 = zext i1 %tobool1 to i32 +// CHECK-NEXT: %bf.load2 = load i32, ptr %b, align 4 +// CHECK-NEXT: %bf.shl = shl i32 %0, 30 +// CHECK-NEXT: %bf.clear3 = and i32 %bf.load2, -1073741825 +// CHECK-NEXT: %bf.set = or i32 %bf.clear3, %bf.shl +// CHECK-NEXT: store i32 %bf.set, ptr %b, align 4 +} >From 1232acd1c3ed33bb7aa226ee3740966607ab51d8 Mon Sep 17 00:00:00 2001 From: BStott <[email protected]> Date: Tue, 11 Nov 2025 16:50:01 +0000 Subject: [PATCH 5/6] Add release note for fix --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ae21c69b2d3c5..934221d4623b4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -447,6 +447,7 @@ Bug Fixes in This Version - Fixed a failed assertion with empty filename in ``#embed`` directive. (#GH162951) - Fixed a crash triggered by unterminated ``__has_embed``. (#GH162953) - Accept empty enumerations in MSVC-compatible C mode. (#GH114402) +- Fix a bug leading to incorrect code generation with complex number compound assignment and bitfield values, which also caused a crash with UBsan. (#GH166798) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >From 76b16c92b5efee9bc556673dd4e9a2a924da7f06 Mon Sep 17 00:00:00 2001 From: BStott <[email protected]> Date: Wed, 12 Nov 2025 14:16:24 +0000 Subject: [PATCH 6/6] Clarify test --- clang/test/CodeGen/complex-compound-assign-bitfield.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang/test/CodeGen/complex-compound-assign-bitfield.c b/clang/test/CodeGen/complex-compound-assign-bitfield.c index ed02ac80afc2d..fe3397e1d7e98 100644 --- a/clang/test/CodeGen/complex-compound-assign-bitfield.c +++ b/clang/test/CodeGen/complex-compound-assign-bitfield.c @@ -8,18 +8,18 @@ struct Bits { int main(void) { // CHECK-LABEL: define dso_local i32 @main() #0 { - struct Bits b; - b.b = b.b += __builtin_complex(-1.0f, 0.0f); -// CHECK: %bf.load = load i32, ptr %b, align 4 + struct Bits x; + x.b += __builtin_complex(-1.0f, 0.0f); +// CHECK: %bf.load = load i32, ptr %x, align 4 // CHECK-NEXT: %bf.lshr = lshr i32 %bf.load, 30 // CHECK-NEXT: %bf.clear = and i32 %bf.lshr, 1 // CHECK-NEXT: %bf.cast = trunc i32 %bf.clear to i1 // CHECK-NEXT: %conv = uitofp i1 %bf.cast to float // CHECK: %0 = zext i1 %tobool1 to i32 -// CHECK-NEXT: %bf.load2 = load i32, ptr %b, align 4 +// CHECK-NEXT: %bf.load2 = load i32, ptr %x, align 4 // CHECK-NEXT: %bf.shl = shl i32 %0, 30 // CHECK-NEXT: %bf.clear3 = and i32 %bf.load2, -1073741825 // CHECK-NEXT: %bf.set = or i32 %bf.clear3, %bf.shl -// CHECK-NEXT: store i32 %bf.set, ptr %b, align 4 +// CHECK-NEXT: store i32 %bf.set, ptr %x, align 4 } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
