diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1384,6 +1384,7 @@ if (!this->emitPopPtr(Initializer)) return false; + ++InitIndex; } else { // Initializer for a direct base class. if (const Record::Base *B = R->getBase(Init->getType())) { @@ -1395,6 +1396,8 @@ if (!this->emitPopPtr(Initializer)) return false; + // Base initializers don't increase InitIndex, since they don't count + // into the Record's fields. } else { const Record::Field *FieldToInit = R->getField(InitIndex); // Non-primitive case. Get a pointer to the field-to-initialize @@ -1407,9 +1410,9 @@ if (!this->emitPopPtr(Initializer)) return false; + ++InitIndex; } } - ++InitIndex; } return true; diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp --- a/clang/test/AST/Interp/cxx20.cpp +++ b/clang/test/AST/Interp/cxx20.cpp @@ -583,3 +583,20 @@ constexpr Outer O; static_assert(O.bar() == 12); } + +namespace BaseAndFieldInit { + struct A { + int a; + }; + + struct B : A { + int b; + }; + + struct C : B { + int c; + }; + + constexpr C c = {1,2,3}; + static_assert(c.a == 1 && c.b == 2 && c.c == 3); +}