]> granicus.if.org Git - clang/commitdiff
When deserializing a declaration, don't look for redeclarations if its
authorDouglas Gregor <dgregor@apple.com>
Mon, 21 Jan 2013 16:16:40 +0000 (16:16 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 21 Jan 2013 16:16:40 +0000 (16:16 +0000)
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

lib/Serialization/ASTCommon.cpp
lib/Serialization/ASTCommon.h
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp

index df87165df794f018ab736d7ec019878a8b3dd2e0..6ac4a2688d89f692c95722a95165d011591a1ea3 100644 (file)
@@ -141,5 +141,68 @@ const Decl *serialization::getDefinitiveDeclContext(const DeclContext *DC) {
   }
   
   return 0;
+}
+
+bool serialization::isRedeclarableDeclKind(unsigned Kind) {
+  switch (static_cast<Decl::Kind>(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");
 }
index f9db1f0f94dcff74e7aa5b28823423eb0fa1cea5..d930854231279220cd136b6be1d1671ce4a29adc 100644 (file)
@@ -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
index 146065866b02ca06ba7a8d2761d1ce91477d02f3..4ae67a04e78151a8640122fee289e38853f4beef 100644 (file)
@@ -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<T> *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<T *>(D)->getKind());
 }
 
 /// \brief Attempts to merge the given declaration (D) with another declaration
index 7a57bad7360f8aa49ae7ab12560ca0231651d24d..dca93f7fda0b7c232117368c8d6a161f9a79e1a2 100644 (file)
@@ -1277,7 +1277,10 @@ template <typename T>
 void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *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<T *>(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);