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(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'}}