diff options
-rw-r--r-- | include/clang/AST/DeclBase.h | 2 | ||||
-rw-r--r-- | include/clang/AST/ExternalASTSource.h | 103 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 45 | ||||
-rw-r--r-- | include/clang/Sema/ExternalSemaSource.h | 2 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 107 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 43 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 12 |
8 files changed, 204 insertions, 114 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 453c8597bf..3e2435197d 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -632,6 +632,8 @@ class DeclContext { /// another pointer. mutable Decl *LastDecl; + friend class ExternalASTSource; + protected: DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 79e44511d3..def9ced94c 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -58,67 +58,85 @@ public: virtual ~ExternalASTSource(); - /// \brief Resolve a type ID into a type, potentially building a new - /// type. - virtual QualType GetType(uint32_t ID) = 0; - /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - virtual Decl *GetDecl(uint32_t ID) = 0; + /// + /// This method only needs to be implemented if the AST source ever + /// passes back decl sets as VisibleDeclaration objects. + virtual Decl *GetExternalDecl(uint32_t ID) = 0; /// \brief Resolve a selector ID into a selector. - virtual Selector GetSelector(uint32_t ID) = 0; + /// + /// This operation only needs to be implemented if the AST source + /// returns non-zero for GetNumKnownSelectors(). + virtual Selector GetExternalSelector(uint32_t ID) = 0; /// \brief Returns the number of selectors known to the external AST /// source. - virtual uint32_t GetNumKnownSelectors() = 0; + virtual uint32_t GetNumExternalSelectors() = 0; - /// \brief Resolve the offset of a statement in the decl stream into a - /// statement. + /// \brief Resolve the offset of a statement in the decl stream into + /// a statement. /// - /// This operation will read a new statement from the external - /// source each time it is called, and is meant to be used via a - /// LazyOffsetPtr. - virtual Stmt *GetDeclStmt(uint64_t Offset) = 0; + /// This operation is meant to be used via a LazyOffsetPtr. It only + /// needs to be implemented if the AST source uses methods like + /// FunctionDecl::setLazyBody when building decls. + virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0; - /// \brief Read all of the declarations lexically stored in a - /// declaration context. + /// \brief Finds all declarations with the given name in the + /// given context. /// - /// \param DC The declaration context whose declarations will be - /// read. + /// Generally the final step of this method is either to call + /// SetExternalVisibleDeclsForName or to recursively call lookup on + /// the DeclContext after calling SetExternalVisibleDecls. + virtual DeclContext::lookup_result + FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) = 0; + + /// \brief Finds all declarations lexically contained within the given + /// DeclContext. /// - /// \param Decls Vector that will contain the declarations loaded - /// from the external source. The caller is responsible for merging - /// these declarations with any declarations already stored in the - /// declaration context. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, - llvm::SmallVectorImpl<uint32_t> &Decls) = 0; - - /// \brief Read all of the declarations visible from a declaration - /// context. - /// - /// \param DC The declaration context whose visible declarations - /// will be read. - /// - /// \param Decls A vector of visible declaration structures, - /// providing the mapping from each name visible in the declaration - /// context to the declaration IDs of declarations with that name. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - virtual bool ReadDeclsVisibleInContext(DeclContext *DC, - llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0; + /// \return true if an error occurred + virtual bool FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Result) = 0; /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. + /// + /// The default implementation of this method is a no-op. virtual void StartTranslationUnit(ASTConsumer *Consumer) { } /// \brief Print any statistics that have been gathered regarding /// the external AST source. + /// + /// The default implementation of this method is a no-op. virtual void PrintStats(); + +protected: + /// \brief Initialize the context's lookup map with the given decls. + /// It is assumed that none of the declarations are redeclarations of + /// each other. + static void SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<VisibleDeclaration> &Decls); + + /// \brief Initialize the context's lookup map with the given decls. + /// It is assumed that none of the declarations are redeclarations of + /// each other. + static void SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<NamedDecl*> &Decls); + + static DeclContext::lookup_result + SetExternalVisibleDeclsForName(const DeclContext *DC, + const VisibleDeclaration &VD); + + static DeclContext::lookup_result + SetExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl*> &Decls); + + static DeclContext::lookup_result + SetNoExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name); }; /// \brief A lazy pointer to an AST node (of base type T) that resides @@ -185,7 +203,8 @@ public: }; /// \brief A lazy pointer to a statement. -typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetDeclStmt> LazyDeclStmtPtr; +typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt> + LazyDeclStmtPtr; } // end namespace clang diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index e144738236..b6881edce9 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -570,29 +570,37 @@ public: const RecordData &Record, unsigned &Idx); /// \brief Reads a declarator info from the given record. - virtual TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, - unsigned &Idx); + TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, + unsigned &Idx); /// \brief Resolve a type ID into a type, potentially building a new /// type. - virtual QualType GetType(pch::TypeID ID); + QualType GetType(pch::TypeID ID); /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - virtual Decl *GetDecl(pch::DeclID ID); + Decl *GetDecl(pch::DeclID ID); + virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve the offset of a statement into a statement. /// /// This operation will read a new statement from the external /// source each time it is called, and is meant to be used via a /// LazyOffsetPtr (which is used by Decls for the body of functions, etc). - virtual Stmt *GetDeclStmt(uint64_t Offset); + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block /// and then leave the cursor pointing into the block. bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID); + /// \brief Finds all the visible declarations with a given name. + /// The current implementation of this method just loads the entire + /// lookup table as unmaterialized references. + virtual DeclContext::lookup_result + FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name); + /// \brief Read all of the declarations lexically stored in a /// declaration context. /// @@ -606,27 +614,8 @@ public: /// /// \returns true if there was an error while reading the /// declarations for this declaration context. - virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, - llvm::SmallVectorImpl<pch::DeclID> &Decls); - - /// \brief Read all of the declarations visible from a declaration - /// context. - /// - /// \param DC The declaration context whose visible declarations - /// will be read. - /// - /// \param Decls A vector of visible declaration structures, - /// providing the mapping from each name visible in the declaration - /// context to the declaration IDs of declarations with that name. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - /// - /// FIXME: Using this intermediate data structure results in an - /// extraneous copying of the data. Could we pass in a reference to - /// the StoredDeclsMap instead? - virtual bool ReadDeclsVisibleInContext(DeclContext *DC, - llvm::SmallVectorImpl<VisibleDeclaration> & Decls); + virtual bool FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Decls); /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. @@ -691,8 +680,8 @@ public: Selector DecodeSelector(unsigned Idx); - virtual Selector GetSelector(uint32_t ID); - virtual uint32_t GetNumKnownSelectors(); + virtual Selector GetExternalSelector(uint32_t ID); + uint32_t GetNumExternalSelectors(); Selector GetSelector(const RecordData &Record, unsigned &Idx) { return DecodeSelector(Record[Idx++]); diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index d27e29281b..ad42a847fa 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -29,6 +29,8 @@ public: ExternalASTSource::SemaSource = true; } + ~ExternalSemaSource(); + /// \brief Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 225729ea69..a73d17a5ca 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -638,9 +638,8 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); - llvm::SmallVector<uint32_t, 64> Decls; - if (Source->ReadDeclsLexicallyInContext(const_cast<DeclContext *>(this), - Decls)) + llvm::SmallVector<Decl*, 64> Decls; + if (Source->FindExternalLexicalDecls(this, Decls)) return; // There is no longer any lexical storage in this context @@ -654,7 +653,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { Decl *FirstNewDecl = 0; Decl *PrevDecl = 0; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { - Decl *D = Source->GetDecl(Decls[I]); + Decl *D = Decls[I]; if (PrevDecl) PrevDecl->NextDeclInContext = D; else @@ -671,28 +670,83 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { LastDecl = PrevDecl; } -void -DeclContext::LoadVisibleDeclsFromExternalStorage() const { - DeclContext *This = const_cast<DeclContext *>(this); - ExternalASTSource *Source = getParentASTContext().getExternalSource(); - assert(hasExternalVisibleStorage() && Source && "No external storage?"); +DeclContext::lookup_result +ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name) { + ASTContext &Context = DC->getParentASTContext(); + StoredDeclsMap *Map; + if (!(Map = DC->LookupPtr)) + Map = DC->CreateStoredDeclsMap(Context); + + StoredDeclsList &List = (*Map)[Name]; + assert(List.isNull()); + (void) List; + + return DeclContext::lookup_result(); +} - llvm::SmallVector<VisibleDeclaration, 64> Decls; - if (Source->ReadDeclsVisibleInContext(This, Decls)) - return; +DeclContext::lookup_result +ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, + const VisibleDeclaration &VD) { + ASTContext &Context = DC->getParentASTContext(); + StoredDeclsMap *Map; + if (!(Map = DC->LookupPtr)) + Map = DC->CreateStoredDeclsMap(Context); + + StoredDeclsList &List = (*Map)[VD.Name]; + List.setFromDeclIDs(VD.Declarations); + return List.getLookupResult(Context); +} - // There is no longer any visible storage in this context - ExternalVisibleStorage = false; +DeclContext::lookup_result +ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl*> &Decls) { + ASTContext &Context = DC->getParentASTContext();; + + StoredDeclsMap *Map; + if (!(Map = DC->LookupPtr)) + Map = DC->CreateStoredDeclsMap(Context); - // Load the declaration IDs for all of the names visible in this - // context. - assert(!LookupPtr && "Have a lookup map before de-serialization?"); - StoredDeclsMap *Map = CreateStoredDeclsMap(getParentASTContext()); + StoredDeclsList &List = (*Map)[Name]; + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + if (List.isNull()) + List.setOnlyValue(Decls[I]); + else + List.AddSubsequentDecl(Decls[I]); + } + + return List.getLookupResult(Context); +} + +void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<VisibleDeclaration> &Decls) { + // There is no longer any visible storage in this context. + DC->ExternalVisibleStorage = false; + + assert(!DC->LookupPtr && "Have a lookup map before de-serialization?"); + StoredDeclsMap *Map = DC->CreateStoredDeclsMap(DC->getParentASTContext()); for (unsigned I = 0, N = Decls.size(); I != N; ++I) { (*Map)[Decls[I].Name].setFromDeclIDs(Decls[I].Declarations); } } +void ExternalASTSource::SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<NamedDecl*> &Decls) { + // There is no longer any visible storage in this context. + DC->ExternalVisibleStorage = false; + + assert(!DC->LookupPtr && "Have a lookup map before de-serialization?"); + StoredDeclsMap &Map = *DC->CreateStoredDeclsMap(DC->getParentASTContext()); + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + StoredDeclsList &List = Map[Decls[I]->getDeclName()]; + if (List.isNull()) + List.setOnlyValue(Decls[I]); + else + List.AddSubsequentDecl(Decls[I]); + } +} + DeclContext::decl_iterator DeclContext::decls_begin() const { if (hasExternalLexicalStorage()) LoadLexicalDeclsFromExternalStorage(); @@ -813,8 +867,17 @@ DeclContext::lookup(DeclarationName Name) { if (PrimaryContext != this) return PrimaryContext->lookup(Name); - if (hasExternalVisibleStorage()) - LoadVisibleDeclsFromExternalStorage(); + if (hasExternalVisibleStorage()) { + // Check to see if we've already cached the lookup results. + if (LookupPtr) { + StoredDeclsMap::iterator I = LookupPtr->find(Name); + if (I != LookupPtr->end()) + return I->second.getLookupResult(getParentASTContext()); + } + + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + return Source->FindExternalVisibleDeclsByName(this, Name); + } /// If there is no lookup data structure, build one now by walking /// all of the linked DeclContexts (in declaration order!) and @@ -944,7 +1007,7 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) { ExternalASTSource *Source = Context.getExternalSource(); assert(Source && "No external AST source available!"); - Data = reinterpret_cast<uintptr_t>(Source->GetDecl(DeclID)); + Data = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(DeclID)); break; } @@ -956,7 +1019,7 @@ void StoredDeclsList::materializeDecls(ASTContext &Context) { assert(Source && "No external AST source available!"); for (unsigned I = 0, N = Vector.size(); I != N; ++I) - Vector[I] = reinterpret_cast<uintptr_t>(Source->GetDecl(Vector[I])); + Vector[I] = reinterpret_cast<uintptr_t>(Source->GetExternalDecl(Vector[I])); Data = (Data & ~0x03) | DK_Decl_Vector; break; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 88e9b9db18..2c51180afc 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2476,6 +2476,10 @@ PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, return TemplateArgumentLocInfo(); } +Decl *PCHReader::GetExternalDecl(uint32_t ID) { + return GetDecl(ID); +} + Decl *PCHReader::GetDecl(pch::DeclID ID) { if (ID == 0) return 0; @@ -2497,15 +2501,15 @@ Decl *PCHReader::GetDecl(pch::DeclID ID) { /// This operation will read a new statement from the external /// source each time it is called, and is meant to be used via a /// LazyOffsetPtr (which is used by Decls for the body of functions, etc). -Stmt *PCHReader::GetDeclStmt(uint64_t Offset) { +Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) { // Since we know tha this statement is part of a decl, make sure to use the // decl cursor to read it. DeclsCursor.JumpToBit(Offset); return ReadStmt(DeclsCursor); } -bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, - llvm::SmallVectorImpl<pch::DeclID> &Decls) { +bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Decls) { assert(DC->hasExternalLexicalStorage() && "DeclContext has no lexical decls in storage"); @@ -2531,20 +2535,22 @@ bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC, } // Load all of the declaration IDs - Decls.clear(); - Decls.insert(Decls.end(), Record.begin(), Record.end()); + for (RecordData::iterator I = Record.begin(), E = Record.end(); I != E; ++I) + Decls.push_back(GetDecl(*I)); ++NumLexicalDeclContextsRead; return false; } -bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, - llvm::SmallVectorImpl<VisibleDeclaration> &Decls) { +DeclContext::lookup_result +PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) { assert(DC->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); uint64_t Offset = DeclContextOffsets[DC].second; if (Offset == 0) { Error("DeclContext has no visible decls in storage"); - return true; + return DeclContext::lookup_result(DeclContext::lookup_iterator(), + DeclContext::lookup_iterator()); } // Keep track of where we are in the stream, then jump back there @@ -2559,13 +2565,16 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); if (RecCode != pch::DECL_CONTEXT_VISIBLE) { Error("Expected visible block"); - return true; + return DeclContext::lookup_result(DeclContext::lookup_iterator(), + DeclContext::lookup_iterator()); } - if (Record.size() == 0) - return false; - - Decls.clear(); + llvm::SmallVector<VisibleDeclaration, 64> Decls; + if (Record.empty()) { + SetExternalVisibleDecls(DC, Decls); + return DeclContext::lookup_result(DeclContext::lookup_iterator(), + DeclContext::lookup_iterator()); + } unsigned Idx = 0; while (Idx < Record.size()) { @@ -2580,7 +2589,9 @@ bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC, } ++NumVisibleDeclContextsRead; - return false; + + SetExternalVisibleDecls(DC, Decls); + return const_cast<DeclContext*>(DC)->lookup(Name); } void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { @@ -2853,11 +2864,11 @@ Selector PCHReader::DecodeSelector(unsigned ID) { return SelectorsLoaded[Index]; } -Selector PCHReader::GetSelector(uint32_t ID) { +Selector PCHReader::GetExternalSelector(uint32_t ID) { return DecodeSelector(ID); } -uint32_t PCHReader::GetNumKnownSelectors() { +uint32_t PCHReader::GetNumExternalSelectors() { return TotalNumSelectors + 1; } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 9cc5048572..8bdf971d96 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" +#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -427,3 +428,6 @@ BlockScopeInfo *Sema::getCurBlock() { return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); } + +// Pin this vtable to this file. +ExternalSemaSource::~ExternalSemaSource() {} diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index dda4fc1a80..d40853d724 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3494,9 +3494,9 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, // If we have an external source, load the entire class method // pool from the PCH file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N; - ++I) { - Selector Sel = ExternalSource->GetSelector(I); + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || FactoryMethodPool.count(Sel) || InstanceMethodPool.count(Sel)) continue; @@ -3595,9 +3595,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, // If we have an external source, load the entire class method // pool from the PCH file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N; - ++I) { - Selector Sel = ExternalSource->GetSelector(I); + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || InstanceMethodPool.count(Sel) || FactoryMethodPool.count(Sel)) continue; |