diff options
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 9a21732b63e3..d56c7e2ab8c0 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallSet.h" #include "llvm/Support/Format.h" @@ -1186,11 +1187,10 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { // Query the external layout to see if it provides an offset. bool HasExternalLayout = false; if (UseExternalLayout) { - // FIXME: This appears to be reversed. if (Base->IsVirtual) - HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset); - else HasExternalLayout = External.getExternalVBaseOffset(Base->Class, Offset); + else + HasExternalLayout = External.getExternalNVBaseOffset(Base->Class, Offset); } // Clang <= 6 incorrectly applied the 'packed' attribute to base classes. @@ -2107,7 +2107,7 @@ static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, if (MD->isImplicit()) continue; - if (MD->isInlineSpecified()) + if (MD->isInlineSpecified() || MD->isConstexpr()) continue; if (MD->hasInlineBody()) @@ -2568,9 +2568,11 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { // information about the bases, such as required alignment and the presence of // zero sized members. const ASTRecordLayout *PreviousBaseLayout = nullptr; + bool HasPolymorphicBaseClass = false; // Iterate through the bases and lay out the non-virtual ones. for (const CXXBaseSpecifier &Base : RD->bases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + HasPolymorphicBaseClass |= BaseDecl->isPolymorphic(); const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl); // Mark and skip virtual bases. if (Base.isVirtual()) { @@ -2594,11 +2596,23 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { layoutNonVirtualBase(RD, BaseDecl, BaseLayout, PreviousBaseLayout); } // Figure out if we need a fresh VFPtr for this class. - if (!PrimaryBase && RD->isDynamicClass()) - for (CXXRecordDecl::method_iterator i = RD->method_begin(), - e = RD->method_end(); - !HasOwnVFPtr && i != e; ++i) - HasOwnVFPtr = i->isVirtual() && i->size_overridden_methods() == 0; + if (RD->isPolymorphic()) { + if (!HasPolymorphicBaseClass) + // This class introduces polymorphism, so we need a vftable to store the + // RTTI information. + HasOwnVFPtr = true; + else if (!PrimaryBase) { + // We have a polymorphic base class but can't extend its vftable. Add a + // new vfptr if we would use any vftable slots. + for (CXXMethodDecl *M : RD->methods()) { + if (MicrosoftVTableContext::hasVtableSlot(M) && + M->size_overridden_methods() == 0) { + HasOwnVFPtr = true; + break; + } + } + } + } // If we don't have a primary base then we have a leading object that could // itself lead with a zero-sized object, something we track. bool CheckLeadingLayout = !PrimaryBase; @@ -2993,7 +3007,8 @@ void MicrosoftRecordLayoutBuilder::computeVtorDispSet( llvm::SmallPtrSet<const CXXRecordDecl *, 2> BasesWithOverriddenMethods; // Seed the working set with our non-destructor, non-pure virtual methods. for (const CXXMethodDecl *MD : RD->methods()) - if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD) && !MD->isPure()) + if (MicrosoftVTableContext::hasVtableSlot(MD) && + !isa<CXXDestructorDecl>(MD) && !MD->isPure()) Work.insert(MD); while (!Work.empty()) { const CXXMethodDecl *MD = *Work.begin(); @@ -3222,7 +3237,8 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, if (D->hasExternalLexicalStorage() && !D->getDefinition()) getExternalSource()->CompleteType(const_cast<ObjCInterfaceDecl*>(D)); D = D->getDefinition(); - assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!"); + assert(D && !D->isInvalidDecl() && D->isThisDeclarationADefinition() && + "Invalid interface decl!"); // Look up this layout, if already laid out, return what we have. const ObjCContainerDecl *Key = |