[clang] [Clang][CodeGen] Use EmitLoadOfLValue instead of EmitLoadOfScalar to get LHS for complex compound assignment (PR #166798)
Benjamin Stott via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 18 06:12:22 PST 2025
https://github.com/BStott6 updated https://github.com/llvm/llvm-project/pull/166798
>From eab7dd02ab238c0029c2f0fc9a7f8f3ce1ab055c Mon Sep 17 00:00:00 2001
From: BStott <Benjamin.Stott at sony.com>
Date: Thu, 6 Nov 2025 16:25:54 +0000
Subject: [PATCH 1/7] [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 <Benjamin.Stott at sony.com>
Date: Fri, 7 Nov 2025 16:39:58 +0000
Subject: [PATCH 2/7] 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 <Benjamin.Stott at sony.com>
Date: Mon, 10 Nov 2025 10:20:27 +0000
Subject: [PATCH 3/7] 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 <Benjamin.Stott at sony.com>
Date: Tue, 11 Nov 2025 16:38:21 +0000
Subject: [PATCH 4/7] 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 <Benjamin.Stott at sony.com>
Date: Tue, 11 Nov 2025 16:50:01 +0000
Subject: [PATCH 5/7] 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 <Benjamin.Stott at sony.com>
Date: Wed, 12 Nov 2025 14:16:24 +0000
Subject: [PATCH 6/7] 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
}
>From 03d0c67ab8a6642df46aa5a4401ac624847515d0 Mon Sep 17 00:00:00 2001
From: BStott <Benjamin.Stott at sony.com>
Date: Tue, 18 Nov 2025 14:11:57 +0000
Subject: [PATCH 7/7] Remove UBSan complex bitfield crash test
---
.../CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c | 10 ----------
1 file changed, 10 deletions(-)
delete 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
deleted file mode 100644
index 51ec1e9bc1d3f..0000000000000
--- a/clang/test/CodeGen/2025-11-10-UBSanComplexBitfieldCrash.c
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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); }
More information about the cfe-commits
mailing list