Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 47 additions & 11 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,25 @@ namespace {

using MacroDefinitionsMap =
llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/>>;
using DeclsMap = llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8>>;

class DeclsSet {
SmallVector<NamedDecl *, 64> Decls;
llvm::SmallPtrSet<NamedDecl *, 8> Found;

public:
operator ArrayRef<NamedDecl *>() const { return Decls; }

bool empty() const { return Decls.empty(); }

bool insert(NamedDecl *ND) {
auto [_, Inserted] = Found.insert(ND);
if (Inserted)
Decls.push_back(ND);
return Inserted;
}
};

using DeclsMap = llvm::DenseMap<DeclarationName, DeclsSet>;

} // namespace

Expand Down Expand Up @@ -8702,14 +8720,23 @@ bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
return false;

// Load the list of declarations.
SmallVector<NamedDecl *, 64> Decls;
llvm::SmallPtrSet<NamedDecl *, 8> Found;
DeclsSet DS;

auto Find = [&, this](auto &&Table, auto &&Key) {
for (GlobalDeclID ID : Table.find(Key)) {
NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));
if (ND->getDeclName() == Name && Found.insert(ND).second)
Decls.push_back(ND);
if (ND->getDeclName() != Name)
continue;
// Special case for namespaces: There can be a lot of redeclarations of
// some namespaces, and we import a "key declaration" per imported module.
// Since all declarations of a namespace are essentially interchangeable,
// we can optimize namespace look-up by only storing the key declaration
// of the current TU, rather than storing N key declarations where N is
// the # of imported modules that declare that namespace.
// TODO: Try to generalize this optimization to other redeclarable decls.
if (isa<NamespaceDecl>(ND))
ND = cast<NamedDecl>(getKeyDeclaration(ND));
DS.insert(ND);
}
};

Expand Down Expand Up @@ -8744,8 +8771,8 @@ bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
Find(It->second.Table, Name);
}

SetExternalVisibleDeclsForName(DC, Name, Decls);
return !Decls.empty();
SetExternalVisibleDeclsForName(DC, Name, DS);
return !DS.empty();
}

void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
Expand All @@ -8763,7 +8790,16 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {

for (GlobalDeclID ID : It->second.Table.findAll()) {
NamedDecl *ND = cast<NamedDecl>(GetDecl(ID));
Decls[ND->getDeclName()].push_back(ND);
// Special case for namespaces: There can be a lot of redeclarations of
// some namespaces, and we import a "key declaration" per imported module.
// Since all declarations of a namespace are essentially interchangeable,
// we can optimize namespace look-up by only storing the key declaration
// of the current TU, rather than storing N key declarations where N is
// the # of imported modules that declare that namespace.
// TODO: Try to generalize this optimization to other redeclarable decls.
if (isa<NamespaceDecl>(ND))
ND = cast<NamedDecl>(getKeyDeclaration(ND));
Decls[ND->getDeclName()].insert(ND);
}

// FIXME: Why a PCH test is failing if we remove the iterator after findAll?
Expand All @@ -8773,9 +8809,9 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
findAll(ModuleLocalLookups, NumModuleLocalVisibleDeclContexts);
findAll(TULocalLookups, NumTULocalVisibleDeclContexts);

for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) {
SetExternalVisibleDeclsForName(DC, I->first, I->second);
}
for (auto &[Name, DS] : Decls)
SetExternalVisibleDeclsForName(DC, Name, DS);

const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false);
}

Expand Down
28 changes: 23 additions & 5 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4396,20 +4396,20 @@ class ASTDeclContextNameLookupTrait

template <typename Coll> data_type getData(const Coll &Decls) {
unsigned Start = DeclIDs.size();
for (NamedDecl *D : Decls) {
auto AddDecl = [this](NamedDecl *D) {
NamedDecl *DeclForLocalLookup =
getDeclForLocalLookup(Writer.getLangOpts(), D);

if (Writer.getDoneWritingDeclsAndTypes() &&
!Writer.wasDeclEmitted(DeclForLocalLookup))
continue;
return;

// Try to avoid writing internal decls to reduced BMI.
// See comments in ASTWriter::WriteDeclContextLexicalBlock for details.
if (Writer.isGeneratingReducedBMI() &&
!DeclForLocalLookup->isFromExplicitGlobalModule() &&
IsInternalDeclFromFileContext(DeclForLocalLookup))
continue;
return;

auto ID = Writer.GetDeclRef(DeclForLocalLookup);

Expand All @@ -4423,7 +4423,7 @@ class ASTDeclContextNameLookupTrait
ModuleLocalDeclsMap.insert({Key, DeclIDsTy{ID}});
else
Iter->second.push_back(ID);
continue;
return;
}
break;
case LookupVisibility::TULocal: {
Expand All @@ -4432,14 +4432,32 @@ class ASTDeclContextNameLookupTrait
TULocalDeclsMap.insert({D->getDeclName(), DeclIDsTy{ID}});
else
Iter->second.push_back(ID);
continue;
return;
}
case LookupVisibility::GenerallyVisibile:
// Generally visible decls go into the general lookup table.
break;
}

DeclIDs.push_back(ID);
};
for (NamedDecl *D : Decls) {
if (ASTReader *Chain = Writer.getChain();
Chain && isa<NamespaceDecl>(D) && D->isFromASTFile() &&
D == Chain->getKeyDeclaration(D)) {
// In ASTReader, we stored only the key declaration of a namespace decl
// for this TU rather than storing all of the key declarations from each
// imported module. If we have an external namespace decl, this is that
// key declaration and we need to re-expand it to write out all of the
// key declarations from each imported module again.
//
// See comment 'ASTReader::FindExternalVisibleDeclsByName' for details.
Chain->forEachImportedKeyDecl(D, [&AddDecl](const Decl *D) {
AddDecl(cast<NamedDecl>(const_cast<Decl *>(D)));
});
} else {
AddDecl(D);
}
}
return std::make_pair(Start, DeclIDs.size());
}
Expand Down
1 change: 1 addition & 0 deletions clang/unittests/Serialization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ add_clang_unittest(SerializationTests
ForceCheckFileInputTest.cpp
InMemoryModuleCacheTest.cpp
ModuleCacheTest.cpp
NamespaceLookupTest.cpp
NoCommentsTest.cpp
PreambleInNamedModulesTest.cpp
LoadSpecLazilyTest.cpp
Expand Down
Loading