diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 6b4b51aac41e8..52e3efff2359d 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -971,6 +971,11 @@ bool ByteCodeExprGen::visitInitList(ArrayRef Inits, unsigned InitIndex = 0; for (const Expr *Init : Inits) { + // Skip unnamed bitfields. + while (InitIndex < R->getNumFields() && + R->getField(InitIndex)->Decl->isUnnamedBitField()) + ++InitIndex; + if (!this->emitDupPtr(E)) return false; diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index e6f22e79451e9..2c8c6781b3483 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -312,6 +312,11 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { // Reserve space for fields. Record::FieldList Fields; for (const FieldDecl *FD : RD->fields()) { + // Note that we DO create fields and descriptors + // for unnamed bitfields here, even though we later ignore + // them everywhere. That's because so the FieldDecl's + // getFieldIndex() matches. + // Reserve space for the field's descriptor and the offset. BaseSize += align(sizeof(InlineDescriptor)); diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 2c33fa1bf8843..3e52354a4a106 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1317,3 +1317,16 @@ namespace { F f; static_assert(f.Z == 12, ""); } + +namespace UnnamedBitFields { + struct A { + int : 1; + double f; + int : 1; + char c; + }; + + constexpr A a = (A){1.0, 'a'}; + static_assert(a.f == 1.0, ""); + static_assert(a.c == 'a', ""); +}