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 <[email protected]>
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@-1 {{non-const reference cannot bind to bit-field}}
   int *f = &(true ? s.n : s.n);
   // expected-error@-1 {{address of bit-field requested}}
+  //   expected-note@#cwg324-n {{bit-field is declared here}}
   int &g = (void(), s.n);
   // expected-error@-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'}}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to