summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--clang/lib/Serialization/ASTReader.cpp257
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);
}
OpenPOWER on IntegriCloud