[clang] [Clang][Sema] Preserve bit-field info in conditional operator (PR #169480)
Mitch Briles via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 25 02:25:16 PST 2025
https://github.com/MitchBriles created https://github.com/llvm/llvm-project/pull/169480
Fixes #169197. This also seems to improve diagnostics in some cases. Let me know if this is not the expected behavior.
Note: I am new to this part of the project. I would appreciate any feedback/nits.
cc: @Sirraide, @Fznamznon
>From e0df041167306660224dc152920e502956fd76c4 Mon Sep 17 00:00:00 2001
From: Mitch <mitchbriles at gmail.com>
Date: Tue, 25 Nov 2025 02:33:38 -0700
Subject: [PATCH] [Clang][Sema] Preserve bit-field info in conditional operator
---
clang/lib/AST/Expr.cpp | 7 +++++++
.../CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp | 4 ++--
clang/test/CXX/drs/cwg3xx.cpp | 1 +
clang/test/SemaCXX/bitfield-cond-promotion.cpp | 16 ++++++++++++++++
clang/test/SemaCXX/conditional-expr.cpp | 6 +++++-
5 files changed, 31 insertions(+), 3 deletions(-)
create mode 100644 clang/test/SemaCXX/bitfield-cond-promotion.cpp
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1d914fa876759..67197274f51bf 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -4247,6 +4247,13 @@ FieldDecl *Expr::getSourceBitField() {
if (UnOp->isPrefix() && UnOp->isIncrementDecrementOp())
return UnOp->getSubExpr()->getSourceBitField();
+ if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) {
+ if (FieldDecl *FD = Cond->getTrueExpr()->getSourceBitField())
+ return FD;
+ if (FieldDecl *FD = Cond->getFalseExpr()->getSourceBitField())
+ return FD;
+ }
+
return nullptr;
}
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp
index 3e8f18c93077e..72ee1ce400d8d 100644
--- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp
@@ -41,8 +41,8 @@ namespace PR6066 {
namespace test3 {
struct A {
- unsigned bitX : 4; // expected-note 3 {{bit-field is declared here}}
- unsigned bitY : 4; // expected-note {{bit-field is declared here}}
+ unsigned bitX : 4; // expected-note 6 {{bit-field is declared here}}
+ unsigned bitY : 4; // expected-note 2 {{bit-field is declared here}}
unsigned var;
void foo();
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index bbd87c060801a..c1864abd0e466 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -397,6 +397,7 @@ namespace cwg324 { // cwg324: 3.6
// expected-error at -1 {{non-const reference cannot bind to bit-field}}
int *f = &(true ? s.n : s.n);
// expected-error at -1 {{address of bit-field requested}}
+ // expected-note@#cwg324-n {{bit-field is declared here}}
int &g = (void(), s.n);
// expected-error at -1 {{non-const reference cannot bind to bit-field 'n'}}
// expected-note@#cwg324-n {{bit-field is declared here}}
diff --git a/clang/test/SemaCXX/bitfield-cond-promotion.cpp b/clang/test/SemaCXX/bitfield-cond-promotion.cpp
new file mode 100644
index 0000000000000..2f287193e351f
--- /dev/null
+++ b/clang/test/SemaCXX/bitfield-cond-promotion.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++14
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++17
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++20
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s -std=c++23
+
+void test_runtime_behavior() {
+ struct {
+ unsigned f : 1;
+ } constexpr s{};
+
+ constexpr int result = (0 ? throw 0 : s.f) - 1;
+ static_assert(result == -1, "Bit-field should promote to int"); // expected-no-diagnostics
+ constexpr int result2 = (1 ? s.f : s.f) - 1;
+ static_assert(result2 == -1, "Bit-field should promote to int"); // expected-no-diagnostics
+}
diff --git a/clang/test/SemaCXX/conditional-expr.cpp b/clang/test/SemaCXX/conditional-expr.cpp
index 8f17555fd806f..d081be60d5520 100644
--- a/clang/test/SemaCXX/conditional-expr.cpp
+++ b/clang/test/SemaCXX/conditional-expr.cpp
@@ -42,7 +42,8 @@ struct BadBase { operator BadDerived&(); };
struct BadDerived : BadBase {};
struct Fields {
- int i1, i2, b1 : 3, b2 : 3;
+ int i1, i2, b1 : 3, b2 : 3; // expected-note 2 {{bit-field is declared here}}
+ unsigned u1: 1;
};
struct MixedFields {
int i;
@@ -201,6 +202,9 @@ void test()
(void)&(i1 ? flds.b1 : flds.i1); // expected-error {{address of bit-field requested}}
(void)&(i1 ? flds.i1 : flds.b1); // expected-error {{address of bit-field requested}}
+ // shouldn't be considered narrowing
+ unsigned char uc1{0 ? throw 0 : flds.u1};
+ unsigned char uc2{1 ? flds.u1 : flds.u1};
unsigned long test0 = 5;
test0 = test0 ? (long) test0 : test0; // expected-warning {{operand of ? changes signedness: 'long' to 'unsigned long'}}
More information about the cfe-commits
mailing list