From f53df2398e07d13be9962b95aebc19b31706fa33 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 7 Dec 2009 04:35:11 +0000 Subject: [PATCH] Move key functions to a separate map. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90745 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 12 ++++++ include/clang/AST/RecordLayout.h | 18 +-------- lib/AST/ASTContext.cpp | 14 +++++++ lib/AST/RecordLayoutBuilder.cpp | 68 ++++++++++++++++---------------- lib/AST/RecordLayoutBuilder.h | 1 + lib/CodeGen/CGVtable.cpp | 4 +- lib/Sema/SemaDeclCXX.cpp | 8 +++- 7 files changed, 70 insertions(+), 55 deletions(-) diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1e32a25a2c..fe270272dd 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -45,6 +45,8 @@ namespace clang { class SourceManager; class TargetInfo; // Decls + class CXXMethodDecl; + class CXXRecordDecl; class Decl; class FieldDecl; class ObjCIvarDecl; @@ -106,6 +108,9 @@ class ASTContext { llvm::DenseMap ASTRecordLayouts; llvm::DenseMap ObjCLayouts; + /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. + llvm::DenseMap KeyFunctions; + /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap ObjCImpls; @@ -852,6 +857,13 @@ public: const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D); + /// getKeyFunction - Get the key function for the given record decl. + /// The key function is, according to the Itanium C++ ABI section 5.2.3: + /// + /// ...the first non-pure virtual function that is not inline at the point + /// of class definition. + const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + void CollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl &Fields); diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 5d2973ea9d..a8334b6940 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -119,13 +119,6 @@ private: /// VBaseOffsets - Contains a map from vbase classes to their offset. /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) llvm::DenseMap VBaseOffsets; - - /// KeyFunction - The key function, according to the Itanium C++ ABI, - /// section 5.2.3: - /// - /// ...the first non-pure virtual function that is not inline at the point - /// of class definition. - const CXXMethodDecl *KeyFunction; }; /// CXXInfo - If the record layout is for a C++ record, this will have @@ -154,8 +147,7 @@ private: const std::pair *bases, unsigned numbases, const std::pair *vbases, - unsigned numvbases, - const CXXMethodDecl *KeyFunction) + unsigned numvbases) : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) { if (FieldCount > 0) { @@ -171,7 +163,6 @@ private: CXXInfo->BaseOffsets[bases[i].first] = bases[i].second; for (unsigned i = 0; i != numvbases; ++i) CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second; - CXXInfo->KeyFunction = KeyFunction; } ~ASTRecordLayout() { @@ -254,13 +245,6 @@ public: return CXXInfo->VBaseOffsets[VBase]; } - /// getKeyFunction - Get the key function. - const CXXMethodDecl *getKeyFunction() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - - return CXXInfo->KeyFunction; - } - primary_base_info_iterator primary_base_begin() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index cc96a5dc0e..490f338d38 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1104,6 +1104,20 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) { return *NewEntry; } +const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { + RD = cast(RD->getDefinition(*this)); + assert(RD && "Cannot get key function for forward declarations!"); + + const CXXMethodDecl *&Entry = KeyFunctions[RD]; + if (!Entry) + Entry = ASTRecordLayoutBuilder::ComputeKeyFunction(RD); + else + assert(Entry == ASTRecordLayoutBuilder::ComputeKeyFunction(RD) && + "Key function changed!"); + + return Entry; +} + //===----------------------------------------------------------------------===// // Type creation/memoization methods //===----------------------------------------------------------------------===// diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 088673916f..550a32b0d0 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -663,35 +663,6 @@ void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) { Alignment = NewAlignment; } -static const CXXMethodDecl *GetKeyFunction(const CXXRecordDecl *RD) { - if (!RD->isDynamicClass()) - return 0; - - for (CXXRecordDecl::method_iterator I = RD->method_begin(), - E = RD->method_end(); I != E; ++I) { - const CXXMethodDecl *MD = *I; - - if (!MD->isVirtual()) - continue; - - if (MD->isPure()) - continue; - - // Ignore implicit member functions, they are always marked as inline, but - // they don't have a body until they're defined. - if (MD->isImplicit()) - continue; - - if (MD->hasInlineBody()) - continue; - - // We found it. - return MD; - } - - return 0; -} - const ASTRecordLayout * ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, const RecordDecl *D) { @@ -715,8 +686,6 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, uint64_t NonVirtualSize = IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize; - const CXXMethodDecl *KeyFunction = GetKeyFunction(cast(D)); - return new ASTRecordLayout(Builder.Size, Builder.Alignment, DataSize, Builder.FieldOffsets.data(), Builder.FieldOffsets.size(), @@ -726,8 +695,7 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, Builder.Bases.data(), Builder.Bases.size(), Builder.VBases.data(), - Builder.VBases.size(), - KeyFunction); + Builder.VBases.size()); } const ASTRecordLayout * @@ -743,3 +711,37 @@ ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx, Builder.FieldOffsets.data(), Builder.FieldOffsets.size()); } + +const CXXMethodDecl * +ASTRecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { + assert(RD->isDynamicClass() && "Class does not have any virtual methods!"); + + // If a class isnt' polymorphic it doesn't have a key function. + if (!RD->isPolymorphic()) + return 0; + + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + const CXXMethodDecl *MD = *I; + + if (!MD->isVirtual()) + continue; + + if (MD->isPure()) + continue; + + // Ignore implicit member functions, they are always marked as inline, but + // they don't have a body until they're defined. + if (MD->isImplicit()) + continue; + + if (MD->hasInlineBody()) + continue; + + // We found it. + return MD; + } + + return 0; +} + diff --git a/lib/AST/RecordLayoutBuilder.h b/lib/AST/RecordLayoutBuilder.h index 69e0498917..d4171d3cc9 100644 --- a/lib/AST/RecordLayoutBuilder.h +++ b/lib/AST/RecordLayoutBuilder.h @@ -151,6 +151,7 @@ public: static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx, const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl); + static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); }; } // end namespace clang diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 6fda6a4404..d227a5e47e 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1433,10 +1433,8 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { if (!RD->isDynamicClass()) return; - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - // Get the key function. - const CXXMethodDecl *KeyFunction = Layout.getKeyFunction(); + const CXXMethodDecl *KeyFunction = CGM.getContext().getKeyFunction(RD); if (KeyFunction) { // We don't have the right key function. diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 2df172e76e..1e96bf525a 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -5090,8 +5090,12 @@ void Sema::MaybeMarkVirtualImplicitMembersReferenced(SourceLocation Loc, return; CXXRecordDecl *RD = MD->getParent(); - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - const CXXMethodDecl *KeyFunction = Layout.getKeyFunction(); + + // Ignore classes without a vtable. + if (!RD->isDynamicClass()) + return; + + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); if (!KeyFunction) { // This record does not have a key function, so we assume that the vtable -- 2.40.0