Skip to content

[Experiment] Redo Globals As Member Tables #29007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
111 changes: 64 additions & 47 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2746,36 +2746,41 @@ void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {
// FIXME: Since we don't represent Clang submodules as Swift
// modules, we're getting everything.
llvm::SmallPtrSet<ExtensionDecl *, 8> knownExtensions;
for (auto entry : lookupTable->allGlobalsAsMembers()) {
auto decl = entry.get<clang::NamedDecl *>();
auto importedDecl = owner.importDecl(decl, owner.CurrentVersion);
if (!importedDecl) continue;

// Find the enclosing extension, if there is one.
ExtensionDecl *ext = findEnclosingExtension(importedDecl);
if (ext && knownExtensions.insert(ext).second)
results.push_back(ext);

// If this is a compatibility typealias, the canonical type declaration
// may exist in another extension.
auto alias = dyn_cast<TypeAliasDecl>(importedDecl);
if (!alias || !alias->isCompatibilityAlias()) continue;

auto aliasedTy = alias->getUnderlyingType();
ext = nullptr;
importedDecl = nullptr;

// Note: We can't use getAnyGeneric() here because `aliasedTy`
// might be typealias.
if (auto Ty = dyn_cast<TypeAliasType>(aliasedTy.getPointer()))
importedDecl = Ty->getDecl();
else if (auto Ty = dyn_cast<AnyGenericType>(aliasedTy.getPointer()))
importedDecl = Ty->getDecl();
if (!importedDecl) continue;

ext = findEnclosingExtension(importedDecl);
if (ext && knownExtensions.insert(ext).second)
results.push_back(ext);
auto globalsAsMemberBaseNames = lookupTable->allGlobalsAsMembersBaseNames();
llvm::array_pod_sort(globalsAsMemberBaseNames.begin(),
globalsAsMemberBaseNames.end());
for (auto baseName : globalsAsMemberBaseNames) {
for (auto entry : lookupTable->lookupGlobalsAsMembers(baseName, None)) {
auto decl = entry.get<clang::NamedDecl *>();
auto importedDecl = owner.importDecl(decl, owner.CurrentVersion);
if (!importedDecl) continue;

// Find the enclosing extension, if there is one.
ExtensionDecl *ext = findEnclosingExtension(importedDecl);
if (ext && knownExtensions.insert(ext).second)
results.push_back(ext);

// If this is a compatibility typealias, the canonical type declaration
// may exist in another extension.
auto alias = dyn_cast<TypeAliasDecl>(importedDecl);
if (!alias || !alias->isCompatibilityAlias()) continue;

auto aliasedTy = alias->getUnderlyingType();
ext = nullptr;
importedDecl = nullptr;

// Note: We can't use getAnyGeneric() here because `aliasedTy`
// might be typealias.
if (auto Ty = dyn_cast<TypeAliasType>(aliasedTy.getPointer()))
importedDecl = Ty->getDecl();
else if (auto Ty = dyn_cast<AnyGenericType>(aliasedTy.getPointer()))
importedDecl = Ty->getDecl();
if (!importedDecl) continue;

ext = findEnclosingExtension(importedDecl);
if (ext && knownExtensions.insert(ext).second)
results.push_back(ext);
}
}
}
}
Expand Down Expand Up @@ -3007,10 +3012,12 @@ void ClangImporter::loadExtensions(NominalTypeDecl *nominal,
// where needed.
auto &clangCtx = Impl.getClangASTContext();
(void)Impl.forEachLookupTable([&](SwiftLookupTable &table) -> bool {
// FIXME: If we already looked at this for this generation,
// skip.
// FIXME: If we already looked at this for this generation,
// skip.

for (auto entry : table.lookupGlobalsAsMembers(effectiveClangContext)) {
for (auto key : table.allGlobalsAsMembersBaseNames()) {
for (auto entry : table.lookupGlobalsAsMembers(key,
effectiveClangContext)) {
// If the entry is not visible, skip it.
if (!isVisibleClangEntry(clangCtx, entry)) continue;

Expand All @@ -3022,9 +3029,9 @@ void ClangImporter::loadExtensions(NominalTypeDecl *nominal,
llvm_unreachable("Macros cannot be imported as members.");
}
}

return false;
});
}
return false;
});
}

void ClangImporter::loadObjCMethods(
Expand Down Expand Up @@ -3763,17 +3770,6 @@ ClangImporter::Implementation::loadNamedMembers(
return None;
}

// Also bail out if there are any global-as-member mappings for this context;
// we can support some of them lazily but the full set of idioms seems
// prohibitively complex (also they're not stored in by-name lookup, for
// reasons unclear).
if (isa<ExtensionDecl>(D) && !checkedGlobalsAsMembers.insert(IDC).second) {
if (forEachLookupTable([&](SwiftLookupTable &table) -> bool {
return (!table.lookupGlobalsAsMembers(effectiveClangContext).empty());
}))
return None;
}

// There are 3 cases:
//
// - The decl is from a bridging header, CMO is Some(nullptr)
Expand Down Expand Up @@ -3823,6 +3819,27 @@ ClangImporter::Implementation::loadNamedMembers(
}
}

for (auto entry : table->lookupGlobalsAsMembers(SerializedSwiftName(N),
effectiveClangContext)) {
if (!entry.is<clang::NamedDecl *>()) continue;
auto member = entry.get<clang::NamedDecl *>();
if (!isVisibleClangEntry(clangCtx, member)) continue;

// Skip Decls from different clang::DeclContexts
if (member->getDeclContext() != CDC) continue;

SmallVector<Decl*, 4> tmp;
insertMembersAndAlternates(member, tmp);
for (auto *TD : tmp) {
if (auto *V = dyn_cast<ValueDecl>(TD)) {
// Skip ValueDecls if they import under different names.
if (V->getBaseName() == N) {
Members.push_back(V);
}
}
}
}

if (N == DeclBaseName::createConstructor()) {
if (auto *classDecl = dyn_cast<ClassDecl>(D)) {
SmallVector<Decl *, 4> ctors;
Expand Down
31 changes: 19 additions & 12 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8543,17 +8543,23 @@ void ClangImporter::Implementation::loadAllMembersIntoExtension(
startedImportingEntity();

// Load the members.
for (auto entry : table->lookupGlobalsAsMembers(effectiveClangContext)) {
auto decl = entry.get<clang::NamedDecl *>();

// Only include members in the same submodule as this extension.
if (getClangSubmoduleForDecl(decl) != submodule)
continue;
SmallPtrSet<Decl *, 32> addedMembers;
auto globalsAsMemberBaseNames = table->allGlobalsAsMembersBaseNames();
llvm::array_pod_sort(globalsAsMemberBaseNames.begin(),
globalsAsMemberBaseNames.end());
for (auto key : globalsAsMemberBaseNames) {
for (auto entry : table->lookupGlobalsAsMembers(key, effectiveClangContext)) {
auto decl = entry.get<clang::NamedDecl *>();

// Only include members in the same submodule as this extension.
if (getClangSubmoduleForDecl(decl) != submodule)
continue;

forEachDistinctName(
decl, [&](ImportedName newName, ImportNameVersion nameVersion) -> bool {
return addMemberAndAlternatesToExtension(decl, newName, nameVersion, ext);
});
forEachDistinctName(
decl, [&](ImportedName newName, ImportNameVersion nameVersion) -> bool {
return addMemberAndAlternatesToExtension(decl, newName, nameVersion, ext, addedMembers);
});
}
}
}

Expand All @@ -8573,7 +8579,7 @@ static Decl *findMemberThatWillLandInAnExtensionContext(Decl *member) {

bool ClangImporter::Implementation::addMemberAndAlternatesToExtension(
clang::NamedDecl *decl, ImportedName newName, ImportNameVersion nameVersion,
ExtensionDecl *ext) {
ExtensionDecl *ext, SmallPtrSetImpl<Decl *> &addedMembers) {
// Quickly check the context and bail out if it obviously doesn't
// belong here.
if (auto *importDC = newName.getEffectiveContext().getAsDeclContext())
Expand All @@ -8586,7 +8592,8 @@ bool ClangImporter::Implementation::addMemberAndAlternatesToExtension(
return false;

member = findMemberThatWillLandInAnExtensionContext(member);
if (!member || member->getDeclContext() != ext)
if (!member || member->getDeclContext() != ext ||
!addedMembers.insert(member).second)
return true;
if (!isa<AccessorDecl>(member))
ext->addMember(member);
Expand Down
3 changes: 2 additions & 1 deletion lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
/// forEachDistinctName's callback.
bool addMemberAndAlternatesToExtension(
clang::NamedDecl *decl, importer::ImportedName newName,
importer::ImportNameVersion nameVersion, ExtensionDecl *ext);
importer::ImportNameVersion nameVersion, ExtensionDecl *ext,
SmallPtrSetImpl<Decl *> &addedMembers);

public:
void
Expand Down
Loading