diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 00f9d4205581ee..e978a190a19584 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9607,7 +9607,7 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E, for (const auto *I : RD->fields()) { // -- if T is a reference type, no initialization is performed. - if (I->getType()->isReferenceType()) + if (I->isUnnamedBitfield() || I->getType()->isReferenceType()) continue; LValue Subobject = This; diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp index 1d9fefb6cbe505..75428a44eb32ad 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp @@ -201,3 +201,22 @@ namespace CTADPartialOrder { template a> struct X { static constexpr int n = 4; }; static_assert(X::n == 4); } + +namespace UnnamedBitfield { + struct A { + int : 16; + }; + // Make sure we don't distinguish between the unnamed bit-field being + // uninitialized and it being zeroed. Those are not distinct states + // according to [temp.type]p2. + // + // FIXME: We shouldn't track a value for unnamed bit-fields, nor number + // them when computing field indexes. + template struct X {}; + constexpr A a; + using T = X; + using T = X; + using T = X<(A())>; + // Once we support bit-casts involving bit-fields, this should be valid too. + using T = X<__builtin_bit_cast(A, (unsigned short)0)>; // expected-error {{constant}} expected-note {{not yet supported}} +}