Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -119,9 +119,13 @@ const CXXRecordDecl *ToDecl = getRecordDecl(CE); assert(ToDecl); const Record *R = getRecord(FromDecl); - const Record::Base *ToBase = R->getBase(ToDecl); - assert(ToBase); + const Record::Base *ToBase; + if (FromDecl->isVirtuallyDerivedFrom(ToDecl)) + ToBase = R->getVirtualBase(ToDecl); + else + ToBase = R->getBase(ToDecl); + assert(ToBase); return this->emitGetPtrBase(ToBase->Offset, CE); } @@ -515,7 +519,9 @@ if (const auto *FD = dyn_cast(Member)) { const RecordDecl *RD = FD->getParent(); const Record *R = getRecord(RD); + assert(R); const Record::Field *F = R->getField(FD); + assert(F); // Leave a pointer to the field on the stack. if (F->Decl->getType()->isReferenceType()) return this->emitGetFieldPop(PT_Ptr, F->Offset, E); Index: clang/lib/AST/Interp/Descriptor.cpp =================================================================== --- clang/lib/AST/Interp/Descriptor.cpp +++ clang/lib/AST/Interp/Descriptor.cpp @@ -122,7 +122,8 @@ static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable, bool IsActive, Descriptor *D) { const bool IsUnion = D->ElemRecord->isUnion(); - auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) { + auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase, + bool Recurse = true) { auto *Desc = reinterpret_cast(Ptr + SubOff) - 1; Desc->Offset = SubOff; Desc->Desc = F; @@ -131,6 +132,10 @@ Desc->IsActive = IsActive && !IsUnion; Desc->IsConst = IsConst || F->IsConst; Desc->IsMutable = IsMutable || F->IsMutable; + + if (!Recurse) + return; + if (auto Fn = F->CtorFn) Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsMutable, Desc->IsActive, F); }; @@ -139,7 +144,7 @@ for (const auto &F : D->ElemRecord->fields()) CtorSub(F.Offset, F.Desc, /*isBase=*/false); for (const auto &V : D->ElemRecord->virtual_bases()) - CtorSub(V.Offset, V.Desc, /*isBase=*/true); + CtorSub(V.Offset, V.Desc, /*isBase=*/true, false); } static void dtorRecord(Block *B, char *Ptr, Descriptor *D) { Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -335,3 +335,24 @@ // expected-error {{must be initialized by a constant expression}} // FIXME: Missing reason for rejection. }; + +namespace VirtBases { + struct VB { + int a; + }; + + struct S : virtual VB {}; // ref-note {{struct with virtual base class is not a literal type}} \ + // expected-note {{struct with virtual base class is not a literal type}} \ + // ref-note {{virtual base class declared here}} \ + // expected-note {{virtual base class declared here}} + + + constexpr S s; // ref-error {{cannot have non-literal type 'const S'}} \ + // expected-error {{cannot have non-literal type 'const S'}} + + S s2; + constexpr VB *v = &s2; +// static_assert(v->a); FIXME: Loading from s should error out, since +// it's not a constant expression. + +};