[clang] [Clang] Fix atomic boolean compound assignment (#33210) (PR #178220)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 5 08:16:10 PST 2026
https://github.com/kiran-isaac updated https://github.com/llvm/llvm-project/pull/178220
>From f1583f9e09febf7b3c2d9cec69df52514b30cd41 Mon Sep 17 00:00:00 2001
From: Kiran Sturt <kiran.sturt at arm.com>
Date: Tue, 30 Dec 2025 18:05:53 +0000
Subject: [PATCH 1/3] [Clang] Fix atomic boolean compound assignment (#33210)
---
clang/lib/CodeGen/CGExprScalar.cpp | 7 ++++
.../CodeGen/compound-assign-atomic-bool.c | 33 +++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 clang/test/CodeGen/compound-assign-atomic-bool.c
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 11af497390671..0d92be12959a9 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1591,6 +1591,13 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (DstType->isBooleanType())
return EmitConversionToBool(Src, SrcType);
+ // Also handle conversions to atomic bools
+ if (const AtomicType *atomicType = DstType->getAs<AtomicType>()) {
+ QualType ValueType = atomicType->getValueType();
+ if (ValueType->isBooleanType())
+ return EmitConversionToBool(Src, ValueType);
+ }
+
llvm::Type *DstTy = ConvertType(DstType);
// Cast from half through float if half isn't a native type.
diff --git a/clang/test/CodeGen/compound-assign-atomic-bool.c b/clang/test/CodeGen/compound-assign-atomic-bool.c
new file mode 100644
index 0000000000000..8a39a76788e66
--- /dev/null
+++ b/clang/test/CodeGen/compound-assign-atomic-bool.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+// When performing compound assignment on atomic_bool, ensure that we
+// correctly handle the conversion from integer to boolean, by comparing
+// with zero rather than truncating.
+
+#include <stdatomic.h>
+#include <stdbool.h>
+
+
+// CHECK: @compund_assign_add
+int compund_assign_add(void) {
+ atomic_bool b;
+
+ b += 2;
+ // CHECK: add
+ // CHECK-NEXT: icmp ne
+ // CHECK-NEXT: zext
+ // CHECK-NEXT: cmpxchg
+ return b;
+}
+
+// CHECK: @compund_assign_minus
+int compund_assign_minus(void) {
+ atomic_bool b;
+
+ b -= 2;
+ // CHECK: sub
+ // CHECK-NEXT: icmp ne
+ // CHECK-NEXT: zext
+ // CHECK-NEXT: cmpxchg
+ return b;
+}
>From f015dde439add64eaa0fd2cc168ac1c8de3b4866 Mon Sep 17 00:00:00 2001
From: Kiran Sturt <kiran.sturt at arm.com>
Date: Thu, 5 Feb 2026 15:54:56 +0000
Subject: [PATCH 2/3] Style changes, add release notes
Change-Id: I98669a9543f0c93a08fa939655ebd12a2f321ae5
---
clang/docs/ReleaseNotes.rst | 3 +++
clang/lib/CodeGen/CGExprScalar.cpp | 4 ++--
clang/test/CodeGen/compound-assign-atomic-bool.c | 8 ++------
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 4d2ff6e6e4e40..4be4607a528c9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -195,6 +195,9 @@ Improvements to Coverage Mapping
Bug Fixes in This Version
-------------------------
+
+- Fixed atomic boolean compound assignment; the conversion back to atomic bool would be miscompiled. (#GH33210)
+
- Fixed a failed assertion in the preprocessor when ``__has_embed`` parameters are missing parentheses. (#GH175088)
- Fix lifetime extension of temporaries in for-range-initializers in templates. (#GH165182)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 0d92be12959a9..86fa740908f75 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1592,8 +1592,8 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
return EmitConversionToBool(Src, SrcType);
// Also handle conversions to atomic bools
- if (const AtomicType *atomicType = DstType->getAs<AtomicType>()) {
- QualType ValueType = atomicType->getValueType();
+ if (const auto *DstAsAtomic = DstType->getAs<AtomicType>()) {
+ QualType ValueType = DstAsAtomic->getValueType();
if (ValueType->isBooleanType())
return EmitConversionToBool(Src, ValueType);
}
diff --git a/clang/test/CodeGen/compound-assign-atomic-bool.c b/clang/test/CodeGen/compound-assign-atomic-bool.c
index 8a39a76788e66..4e8f351b49b81 100644
--- a/clang/test/CodeGen/compound-assign-atomic-bool.c
+++ b/clang/test/CodeGen/compound-assign-atomic-bool.c
@@ -4,13 +4,9 @@
// correctly handle the conversion from integer to boolean, by comparing
// with zero rather than truncating.
-#include <stdatomic.h>
-#include <stdbool.h>
-
-
// CHECK: @compund_assign_add
int compund_assign_add(void) {
- atomic_bool b;
+ _Atomic _Bool b;
b += 2;
// CHECK: add
@@ -22,7 +18,7 @@ int compund_assign_add(void) {
// CHECK: @compund_assign_minus
int compund_assign_minus(void) {
- atomic_bool b;
+ _Atomic _Bool b;
b -= 2;
// CHECK: sub
>From da62e75d4ed297ec243b51c12ea4b89b4404093a Mon Sep 17 00:00:00 2001
From: Kiran Sturt <kiran.sturt at arm.com>
Date: Thu, 5 Feb 2026 16:15:52 +0000
Subject: [PATCH 3/3] Lift the conversion from EmitScalerConversion to
EmitCompoundAssignLValue.
Atomics aren't really scaler, are they.
Change-Id: Ida3cc76eecde6b426c0f29ac52034b89b45f6816
---
clang/lib/CodeGen/CGExprScalar.cpp | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 86fa740908f75..20c5475f32a9a 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1591,13 +1591,6 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
if (DstType->isBooleanType())
return EmitConversionToBool(Src, SrcType);
- // Also handle conversions to atomic bools
- if (const auto *DstAsAtomic = DstType->getAs<AtomicType>()) {
- QualType ValueType = DstAsAtomic->getValueType();
- if (ValueType->isBooleanType())
- return EmitConversionToBool(Src, ValueType);
- }
-
llvm::Type *DstTy = ConvertType(DstType);
// Cast from half through float if half isn't a native type.
@@ -4045,10 +4038,15 @@ LValue ScalarExprEmitter::EmitCompoundAssignLValue(
if (LHSLV.isBitField()) {
Previous = Result;
Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc);
- } else
+ } else if (const auto *atomicTy = LHSTy->getAs<AtomicType>()) {
+ Result = EmitScalarConversion(Result, PromotionTypeCR,
+ atomicTy->getValueType(), Loc,
+ ScalarConversionOpts(CGF.SanOpts));
+ } else {
Result = EmitScalarConversion(Result, PromotionTypeCR, LHSTy, Loc,
ScalarConversionOpts(CGF.SanOpts));
-
+ }
+
if (atomicPHI) {
llvm::BasicBlock *curBlock = Builder.GetInsertBlock();
llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn);
More information about the cfe-commits
mailing list