diff options
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 257 |
1 files changed, 76 insertions, 181 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b41bfa1255e..f4044624d07 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -20,6 +20,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/Frontend/PCHContainerOperations.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" @@ -903,6 +904,13 @@ unsigned DeclarationNameKey::getHash() const { return ID.ComputeHash(); } +ModuleFile * +ASTDeclContextNameLookupTrait::ReadFileRef(const unsigned char *&d) { + using namespace llvm::support; + uint32_t ModuleFileID = endian::readNext<uint32_t, little, unaligned>(d); + return Reader.getLocalModuleFile(F, ModuleFileID); +} + std::pair<unsigned, unsigned> ASTDeclContextNameLookupTrait::ReadKeyDataLength(const unsigned char *&d) { using namespace llvm::support; @@ -948,15 +956,15 @@ ASTDeclContextNameLookupTrait::ReadKey(const unsigned char *d, unsigned) { return DeclarationNameKey(Kind, Data); } -ASTDeclContextNameLookupTrait::data_type -ASTDeclContextNameLookupTrait::ReadData(internal_key_type, - const unsigned char *d, - unsigned DataLen) { +void ASTDeclContextNameLookupTrait::ReadDataInto(internal_key_type, + const unsigned char *d, + unsigned DataLen, + data_type_builder &Val) { using namespace llvm::support; - unsigned NumDecls = DataLen / 4; - LE32DeclID *Start = reinterpret_cast<LE32DeclID *>( - const_cast<unsigned char *>(d)); - return std::make_pair(Start, Start + NumDecls); + for (unsigned NumDecls = DataLen / 4; NumDecls; --NumDecls) { + uint32_t LocalID = endian::readNext<uint32_t, little, unaligned>(d); + Val.insert(Reader.getGlobalDeclID(F, LocalID)); + } } bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, @@ -1015,9 +1023,8 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, // We can't safely determine the primary context yet, so delay attaching the // lookup table until we're done with recursive deserialization. - unsigned BucketOffset = Record[0]; - PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{ - &M, (const unsigned char *)Blob.data(), BucketOffset}); + auto *Data = (const unsigned char*)Blob.data(); + PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&M, Data}); return false; } @@ -2552,9 +2559,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { unsigned Idx = 0; serialization::DeclID ID = ReadDeclID(F, Record, Idx); auto *Data = (const unsigned char*)Blob.data(); - unsigned BucketOffset = Record[Idx++]; - PendingVisibleUpdates[ID].push_back( - PendingVisibleUpdate{&F, Data, BucketOffset}); + PendingVisibleUpdates[ID].push_back(PendingVisibleUpdate{&F, Data}); // If we've already loaded the decl, perform the updates when we finish // loading this block. if (Decl *D = GetExistingDecl(ID)) @@ -6355,196 +6360,48 @@ void ASTReader::FindFileRegionDecls(FileID File, Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt))); } -/// \brief Retrieve the "definitive" module file for the definition of the -/// given declaration context, if there is one. -/// -/// The "definitive" module file is the only place where we need to look to -/// find information about the declarations within the given declaration -/// context. For example, C++ and Objective-C classes, C structs/unions, and -/// Objective-C protocols, categories, and extensions are all defined in a -/// single place in the source code, so they have definitive module files -/// associated with them. C++ namespaces, on the other hand, can have -/// definitions in multiple different module files. -/// -/// Note: this needs to be kept in sync with ASTWriter::AddedVisibleDecl's -/// NDEBUG checking. -static ModuleFile *getDefinitiveModuleFileFor(const DeclContext *DC, - ASTReader &Reader) { - if (const DeclContext *DefDC = getDefinitiveDeclContext(DC)) - return Reader.getOwningModuleFile(cast<Decl>(DefDC)); - - return nullptr; -} - -namespace { - /// \brief ModuleFile visitor used to perform name lookup into a - /// declaration context. - class DeclContextNameLookupVisitor { - ASTReader &Reader; - const DeclContext *Context; - DeclarationName Name; - DeclarationNameKey NameKey; - unsigned NameHash; - SmallVectorImpl<NamedDecl *> &Decls; - llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet; - - public: - DeclContextNameLookupVisitor(ASTReader &Reader, const DeclContext *Context, - DeclarationName Name, - SmallVectorImpl<NamedDecl *> &Decls, - llvm::SmallPtrSetImpl<NamedDecl *> &DeclSet) - : Reader(Reader), Context(Context), Name(Name), NameKey(Name), - NameHash(NameKey.getHash()), Decls(Decls), DeclSet(DeclSet) {} - - bool operator()(ModuleFile &M) { - // Check whether we have any visible declaration information for - // this context in this module. - auto Info = M.DeclContextInfos.find(Context); - if (Info == M.DeclContextInfos.end() || !Info->second.NameLookupTableData) - return false; - - // Look for this name within this module. - ASTDeclContextNameLookupTable *LookupTable = - Info->second.NameLookupTableData; - ASTDeclContextNameLookupTable::iterator Pos = - LookupTable->find_hashed(NameKey, NameHash); - if (Pos == LookupTable->end()) - return false; - - bool FoundAnything = false; - ASTDeclContextNameLookupTrait::data_type Data = *Pos; - for (; Data.first != Data.second; ++Data.first) { - NamedDecl *ND = Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first); - if (!ND) - continue; - - if (ND->getDeclName() != Name) { - // Not all names map to a unique DeclarationNameKey. - assert(DeclarationNameKey(ND->getDeclName()) == NameKey && - "mismatched name for decl in decl context lookup table?"); - continue; - } - - // Record this declaration. - FoundAnything = true; - if (DeclSet.insert(ND).second) - Decls.push_back(ND); - } - - return FoundAnything; - } - }; -} - bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { - assert(DC->hasExternalVisibleStorage() && + assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() && "DeclContext has no visible decls in storage"); if (!Name) return false; + auto It = Lookups.find(DC); + if (It == Lookups.end()) + return false; + Deserializing LookupResults(this); + // Load the list of declarations. SmallVector<NamedDecl *, 64> Decls; - llvm::SmallPtrSet<NamedDecl*, 64> DeclSet; - - DeclContextNameLookupVisitor Visitor(*this, DC, Name, Decls, DeclSet); - - // If we can definitively determine which module file to look into, - // only look there. Otherwise, look in all module files. - if (ModuleFile *Definitive = getDefinitiveModuleFileFor(DC, *this)) - Visitor(*Definitive); - else - ModuleMgr.visit(Visitor); + for (DeclID ID : It->second.Table.find(Name)) { + NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); + if (ND->getDeclName() == Name) + Decls.push_back(ND); + } ++NumVisibleDeclContextsRead; SetExternalVisibleDeclsForName(DC, Name, Decls); return !Decls.empty(); } -namespace { - /// \brief ModuleFile visitor used to retrieve all visible names in a - /// declaration context. - class DeclContextAllNamesVisitor { - ASTReader &Reader; - SmallVectorImpl<const DeclContext *> &Contexts; - DeclsMap &Decls; - llvm::SmallPtrSet<NamedDecl *, 256> DeclSet; - bool VisitAll; - - public: - DeclContextAllNamesVisitor(ASTReader &Reader, - SmallVectorImpl<const DeclContext *> &Contexts, - DeclsMap &Decls, bool VisitAll) - : Reader(Reader), Contexts(Contexts), Decls(Decls), VisitAll(VisitAll) { } - - bool operator()(ModuleFile &M) { - // Check whether we have any visible declaration information for - // this context in this module. - ModuleFile::DeclContextInfosMap::iterator Info; - bool FoundInfo = false; - for (unsigned I = 0, N = Contexts.size(); I != N; ++I) { - Info = M.DeclContextInfos.find(Contexts[I]); - if (Info != M.DeclContextInfos.end() && - Info->second.NameLookupTableData) { - FoundInfo = true; - break; - } - } - - if (!FoundInfo) - return false; - - ASTDeclContextNameLookupTable *LookupTable = - Info->second.NameLookupTableData; - bool FoundAnything = false; - for (ASTDeclContextNameLookupTable::data_iterator - I = LookupTable->data_begin(), E = LookupTable->data_end(); - I != E; - ++I) { - ASTDeclContextNameLookupTrait::data_type Data = *I; - for (; Data.first != Data.second; ++Data.first) { - NamedDecl *ND = Reader.GetLocalDeclAs<NamedDecl>(M, *Data.first); - if (!ND) - continue; - - // Record this declaration. - FoundAnything = true; - if (DeclSet.insert(ND).second) - Decls[ND->getDeclName()].push_back(ND); - } - } - - return FoundAnything && !VisitAll; - } - }; -} - void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { if (!DC->hasExternalVisibleStorage()) return; - DeclsMap Decls; - // Compute the declaration contexts we need to look into. Multiple such - // declaration contexts occur when two declaration contexts from disjoint - // modules get merged, e.g., when two namespaces with the same name are - // independently defined in separate modules. - SmallVector<const DeclContext *, 2> Contexts; - Contexts.push_back(DC); + auto It = Lookups.find(DC); + assert(It != Lookups.end() && + "have external visible storage but no lookup tables"); - if (DC->isNamespace()) { - KeyDeclsMap::iterator Key = - KeyDecls.find(const_cast<Decl *>(cast<Decl>(DC))); - if (Key != KeyDecls.end()) { - for (unsigned I = 0, N = Key->second.size(); I != N; ++I) - Contexts.push_back(cast<DeclContext>(GetDecl(Key->second[I]))); - } + DeclsMap Decls; + + for (DeclID ID : It->second.Table.findAll()) { + NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); + Decls[ND->getDeclName()].push_back(ND); } - DeclContextAllNamesVisitor Visitor(*this, Contexts, Decls, - /*VisitAll=*/DC->isFileContext()); - ModuleMgr.visit(Visitor); ++NumVisibleDeclContextsRead; for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { @@ -6553,6 +6410,12 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false); } +const serialization::reader::DeclContextLookupTable * +ASTReader::getLoadedLookupTables(DeclContext *Primary) const { + auto I = Lookups.find(Primary); + return I == Lookups.end() ? nullptr : &I->second; +} + /// \brief Under non-PCH compilation the consumer receives the objc methods /// before receiving the implementation, and codegen depends on this. /// We simulate this by deserializing and passing to consumer the methods of the @@ -7384,6 +7247,36 @@ Module *ASTReader::getModule(unsigned ID) { return getSubmodule(ID); } +ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) { + if (ID & 1) { + // It's a module, look it up by submodule ID. + auto I = GlobalSubmoduleMap.find(getGlobalSubmoduleID(F, ID >> 1)); + return I == GlobalSubmoduleMap.end() ? nullptr : I->second; + } else { + // It's a prefix (preamble, PCH, ...). Look it up by index. + unsigned IndexFromEnd = ID >> 1; + assert(IndexFromEnd && "got reference to unknown module file"); + return getModuleManager().pch_modules().end()[-IndexFromEnd]; + } +} + +unsigned ASTReader::getModuleFileID(ModuleFile *F) { + if (!F) + return 1; + + // For a file representing a module, use the submodule ID of the top-level + // module as the file ID. For any other kind of file, the number of such + // files loaded beforehand will be the same on reload. + // FIXME: Is this true even if we have an explicit module file and a PCH? + if (F->isModule()) + return ((F->BaseSubmoduleID + NUM_PREDEF_SUBMODULE_IDS) << 1) | 1; + + auto PCHModules = getModuleManager().pch_modules(); + auto I = std::find(PCHModules.begin(), PCHModules.end(), F); + assert(I != PCHModules.end() && "emitting reference to unknown file"); + return (I - PCHModules.end()) << 1; +} + ExternalASTSource::ASTSourceDescriptor ASTReader::getSourceDescriptor(const Module &M) { StringRef Dir, Filename; @@ -8432,6 +8325,8 @@ void ASTReader::FinishedDeserializing() { for (auto Update : Updates) { auto *FPT = Update.second->getType()->castAs<FunctionProtoType>(); auto ESI = FPT->getExtProtoInfo().ExceptionSpec; + if (auto *Listener = Context.getASTMutationListener()) + Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second)); for (auto *Redecl : Update.second->redecls()) Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); } |