From: Douglas Gregor Date: Mon, 21 Jan 2013 16:16:40 +0000 (+0000) Subject: When deserializing a declaration, don't look for redeclarations if its X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9cfdc03fe7abab2f413bb7fdc59e9be15c382a74;p=clang When deserializing a declaration, don't look for redeclarations if its kind indicates that it can never be redeclared. Good for a 1% speedup, and redeclaration searching drops off the profile. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173054 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index df87165df7..6ac4a2688d 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -141,5 +141,68 @@ const Decl *serialization::getDefinitiveDeclContext(const DeclContext *DC) { } return 0; +} + +bool serialization::isRedeclarableDeclKind(unsigned Kind) { + switch (static_cast(Kind)) { + case Decl::TranslationUnit: // Special case of a "merged" declaration. + case Decl::Namespace: + case Decl::NamespaceAlias: // FIXME: Not yet redeclarable, but will be. + case Decl::Typedef: + case Decl::TypeAlias: + case Decl::Enum: + case Decl::Record: + case Decl::CXXRecord: + case Decl::ClassTemplateSpecialization: + case Decl::ClassTemplatePartialSpecialization: + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + case Decl::Var: + case Decl::FunctionTemplate: + case Decl::ClassTemplate: + case Decl::TypeAliasTemplate: + case Decl::ObjCProtocol: + case Decl::ObjCInterface: + return true; + + // Never redeclarable. + case Decl::UsingDirective: + case Decl::Label: + case Decl::UnresolvedUsingTypename: + case Decl::TemplateTypeParm: + case Decl::EnumConstant: + case Decl::UnresolvedUsingValue: + case Decl::IndirectField: + case Decl::Field: + case Decl::ObjCIvar: + case Decl::ObjCAtDefsField: + case Decl::ImplicitParam: + case Decl::ParmVar: + case Decl::NonTypeTemplateParm: + case Decl::TemplateTemplateParm: + case Decl::Using: + case Decl::UsingShadow: + case Decl::ObjCMethod: + case Decl::ObjCCategory: + case Decl::ObjCCategoryImpl: + case Decl::ObjCImplementation: + case Decl::ObjCProperty: + case Decl::ObjCCompatibleAlias: + case Decl::LinkageSpec: + case Decl::ObjCPropertyImpl: + case Decl::FileScopeAsm: + case Decl::AccessSpec: + case Decl::Friend: + case Decl::FriendTemplate: + case Decl::StaticAssert: + case Decl::Block: + case Decl::ClassScopeFunctionSpecialization: + case Decl::Import: + return false; + } + llvm_unreachable("Unhandled declaration kind"); } diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index f9db1f0f94..d930854231 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -70,6 +70,9 @@ unsigned ComputeHash(Selector Sel); /// multiple definitions. const Decl *getDefinitiveDeclContext(const DeclContext *DC); +/// \brief Determine whether the given declaration kind is redeclarable. +bool isRedeclarableDeclKind(unsigned Kind); + } // namespace serialization } // namespace clang diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 146065866b..4ae67a04e7 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -116,29 +116,25 @@ namespace clang { ASTReader &Reader; GlobalDeclID FirstID; mutable bool Owning; + Decl::Kind DeclKind; void operator=(RedeclarableResult &) LLVM_DELETED_FUNCTION; public: - RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID) - : Reader(Reader), FirstID(FirstID), Owning(true) { } + RedeclarableResult(ASTReader &Reader, GlobalDeclID FirstID, + Decl::Kind DeclKind) + : Reader(Reader), FirstID(FirstID), Owning(true), DeclKind(DeclKind) { } RedeclarableResult(const RedeclarableResult &Other) - : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) + : Reader(Other.Reader), FirstID(Other.FirstID), Owning(Other.Owning) , + DeclKind(Other.DeclKind) { Other.Owning = false; } ~RedeclarableResult() { - // FIXME: We want to suppress this when the declaration is local to - // a function, since there's no reason to search other AST files - // for redeclarations (they can't exist). However, this is hard to - // do locally because the declaration hasn't necessarily loaded its - // declaration context yet. Also, local externs still have the function - // as their (semantic) declaration context, which is wrong and would - // break this optimize. - - if (FirstID && Owning && Reader.PendingDeclChainsKnown.insert(FirstID)) + if (FirstID && Owning && isRedeclarableDeclKind(DeclKind) && + Reader.PendingDeclChainsKnown.insert(FirstID)) Reader.PendingDeclChains.push_back(FirstID); } @@ -151,7 +147,7 @@ namespace clang { Owning = false; } }; - + /// \brief Class used to capture the result of searching for an existing /// declaration of a specific kind and name, along with the ability /// to update the place where this result was found (the declaration @@ -1562,7 +1558,8 @@ ASTDeclReader::VisitRedeclarable(Redeclarable *D) { // The result structure takes care to note that we need to load the // other declaration chains for this ID. - return RedeclarableResult(Reader, FirstDeclID); + return RedeclarableResult(Reader, FirstDeclID, + static_cast(D)->getKind()); } /// \brief Attempts to merge the given declaration (D) with another declaration diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 7a57bad736..dca93f7fda 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1277,7 +1277,10 @@ template void ASTDeclWriter::VisitRedeclarable(Redeclarable *D) { T *First = D->getFirstDeclaration(); if (First->getMostRecentDecl() != First) { - // There is more than one declaration of this entity, so we will need to + assert(isRedeclarableDeclKind(static_cast(D)->getKind()) && + "Not considered redeclarable?"); + + // There is more than one declaration of this entity, so we will need to // write a redeclaration chain. Writer.AddDeclRef(First, Record); Writer.Redeclarations.insert(First);