Skip to content

ClangImporter: Reconcile Clang declaration hidden-ness between loadAllMembers() and lazy loading #29418

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

Merged
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
48 changes: 21 additions & 27 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,22 +2867,23 @@ void ClangModuleUnit::lookupValue(DeclName name, NLKind lookupKind,
}
}

/// Determine whether the given Clang entry is visible.
///
/// FIXME: this is an elaborate hack to badly reflect Clang's
/// submodule visibility into Swift.
static bool isVisibleClangEntry(clang::ASTContext &ctx,
SwiftLookupTable::SingleEntry entry) {
if (auto clangDecl = entry.dyn_cast<clang::NamedDecl *>()) {
// For a declaration, check whether the declaration is hidden.
if (!clangDecl->isHidden()) return true;
bool ClangImporter::Implementation::isVisibleClangEntry(
const clang::NamedDecl *clangDecl) {
// For a declaration, check whether the declaration is hidden.
if (!clangDecl->isHidden()) return true;

// Is any redeclaration visible?
for (auto redecl : clangDecl->redecls()) {
if (!cast<clang::NamedDecl>(redecl)->isHidden()) return true;
}
// Is any redeclaration visible?
for (auto redecl : clangDecl->redecls()) {
if (!cast<clang::NamedDecl>(redecl)->isHidden()) return true;
}

return false;
return false;
}

bool ClangImporter::Implementation::isVisibleClangEntry(
SwiftLookupTable::SingleEntry entry) {
if (auto clangDecl = entry.dyn_cast<clang::NamedDecl *>()) {
return isVisibleClangEntry(clangDecl);
}

// If it's a macro from a module, check whether the module has been imported.
Expand Down Expand Up @@ -2917,15 +2918,13 @@ ClangModuleUnit::lookupNestedType(Identifier name,
if (!baseTypeContext)
return nullptr;

auto &clangCtx = owner.getClangASTContext();

// FIXME: This is very similar to what's in Implementation::lookupValue and
// Implementation::loadAllMembers.
SmallVector<TypeDecl *, 2> results;
for (auto entry : lookupTable->lookup(SerializedSwiftName(name.str()),
baseTypeContext)) {
// If the entry is not visible, skip it.
if (!isVisibleClangEntry(clangCtx, entry)) continue;
if (!owner.isVisibleClangEntry(entry)) continue;

auto *clangDecl = entry.dyn_cast<clang::NamedDecl *>();
if (!clangDecl)
Expand Down Expand Up @@ -2993,14 +2992,13 @@ void ClangImporter::loadExtensions(NominalTypeDecl *nominal,

// Dig through each of the Swift lookup tables, creating extensions
// where needed.
auto &clangCtx = Impl.getClangASTContext();
(void)Impl.forEachLookupTable([&](SwiftLookupTable &table) -> bool {
// FIXME: If we already looked at this for this generation,
// skip.

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

if (auto decl = entry.dyn_cast<clang::NamedDecl *>()) {
// Import the context of this declaration, which has the
Expand Down Expand Up @@ -3581,7 +3579,7 @@ void ClangImporter::Implementation::lookupValue(

for (auto entry : table.lookup(name.getBaseName(), clangTU)) {
// If the entry is not visible, skip it.
if (!isVisibleClangEntry(clangCtx, entry)) continue;
if (!isVisibleClangEntry(entry)) continue;

ValueDecl *decl;
// If it's a Clang declaration, try to import it.
Expand Down Expand Up @@ -3685,11 +3683,9 @@ void ClangImporter::Implementation::lookupObjCMembers(
SwiftLookupTable &table,
DeclName name,
VisibleDeclConsumer &consumer) {
auto &clangCtx = getClangASTContext();

for (auto clangDecl : table.lookupObjCMembers(name.getBaseName())) {
// If the entry is not visible, skip it.
if (!isVisibleClangEntry(clangCtx, clangDecl)) continue;
if (!isVisibleClangEntry(clangDecl)) continue;

forEachDistinctName(clangDecl,
[&](ImportedName importedName,
Expand Down Expand Up @@ -3801,8 +3797,6 @@ ClangImporter::Implementation::loadNamedMembers(
auto table = findLookupTable(*CMO);
assert(table && "clang module without lookup table");

clang::ASTContext &clangCtx = getClangASTContext();

assert(isa<clang::ObjCContainerDecl>(CD) || isa<clang::NamespaceDecl>(CD));

ensureSuperclassMembersAreLoaded(dyn_cast<ClassDecl>(D));
Expand All @@ -3812,7 +3806,7 @@ ClangImporter::Implementation::loadNamedMembers(
effectiveClangContext)) {
if (!entry.is<clang::NamedDecl *>()) continue;
auto member = entry.get<clang::NamedDecl *>();
if (!isVisibleClangEntry(clangCtx, member)) continue;
if (!isVisibleClangEntry(member)) continue;

// Skip Decls from different clang::DeclContexts
if (member->getDeclContext() != CDC) continue;
Expand All @@ -3833,7 +3827,7 @@ ClangImporter::Implementation::loadNamedMembers(
effectiveClangContext)) {
if (!entry.is<clang::NamedDecl *>()) continue;
auto member = entry.get<clang::NamedDecl *>();
if (!isVisibleClangEntry(clangCtx, member)) continue;
if (!isVisibleClangEntry(member)) continue;

// Skip Decls from different clang::DeclContexts
if (member->getDeclContext() != CDC) continue;
Expand Down
3 changes: 2 additions & 1 deletion lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8670,7 +8670,8 @@ void ClangImporter::Implementation::collectMembersToAdd(
for (const clang::Decl *m : objcContainer->decls()) {
auto nd = dyn_cast<clang::NamedDecl>(m);
if (nd && nd == nd->getCanonicalDecl() &&
nd->getDeclContext() == objcContainer)
nd->getDeclContext() == objcContainer &&
isVisibleClangEntry(nd))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DougGregor This is the relevant part of the change...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, looks totally reasonable!

insertMembersAndAlternates(nd, members);
}

Expand Down
7 changes: 7 additions & 0 deletions lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,13 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
/// false otherwise.
bool forEachLookupTable(llvm::function_ref<bool(SwiftLookupTable &table)> fn);

/// Determine whether the given Clang entry is visible.
///
/// FIXME: this is an elaborate hack to badly reflect Clang's
/// submodule visibility into Swift.
bool isVisibleClangEntry(const clang::NamedDecl *clangDecl);
bool isVisibleClangEntry(SwiftLookupTable::SingleEntry entry);

/// Look for namespace-scope values with the given name in the given
/// Swift lookup table.
void lookupValue(SwiftLookupTable &table, DeclName name,
Expand Down
2 changes: 1 addition & 1 deletion test/ClangImporter/Inputs/SwiftPrivateAttr.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Foundation
@_exported import Foundation

protocol __PrivProto {
}
Expand Down
1 change: 1 addition & 0 deletions test/ClangImporter/Inputs/custom-modules/module.map
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ module SubclassExistentialsExtra {

module SwiftPrivateAttr {
header "SwiftPrivateAttr.h"
export *
}

module TestProtocols { header "Protocols.h" }
Expand Down
2 changes: 2 additions & 0 deletions test/IDE/Inputs/custom-modules/ImportAsMemberC.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@import ObjectiveC;

typedef const void *CFTypeRef __attribute__((objc_bridge(id)));

typedef const struct __attribute__((objc_bridge(id))) CCPowerSupply *CCPowerSupplyRef;
Expand Down
1 change: 1 addition & 0 deletions test/IDE/Inputs/custom-modules/module.map
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module ImportAsMember {
module C {
requires objc
header "ImportAsMemberC.h"
export *
}

module APINotes {
Expand Down
3 changes: 3 additions & 0 deletions test/IDE/import_as_member.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@
// PRINT-APINOTES-4: @available(swift, obsoleted: 3, renamed: "Struct1.NewApiNoteType")
// PRINT-APINOTES-4-NEXT: typealias IAMStruct1APINoteType = Struct1.NewApiNoteType

#if canImport(Foundation)
import Foundation
#endif
import ImportAsMember.A
import ImportAsMember.B
import ImportAsMember.APINotes
Expand Down
8 changes: 8 additions & 0 deletions test/IRGen/Inputs/usr/include/module.map
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@

module gizmo {
header "Gizmo.h"
export *
}

module SRoA {
header "SRoA.h"
export *
}

module ObjectiveC {
header "BridgeTestObjectiveC.h"
export *
}

module CoreCooling {
header "CoreCooling.h"
export *
}

module Foundation {
header "BridgeTestFoundation.h"
export *
}

module CoreFoundation {
header "BridgeTestCoreFoundation.h"
export *
}

module ObjCInterop {
header "ObjCInterop.h"
export *
}

module error_domains {
header "error_domains.h"
export *
}
4 changes: 2 additions & 2 deletions test/SILGen/import_as_member.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// REQUIRES: objc_interop
import ImportAsMember.A
import ImportAsMember.Class
import Foundation

public func returnGlobalVar() -> Double {
return Struct1.globalVar
Expand Down Expand Up @@ -65,7 +66,6 @@ extension SomeClass {
}

public func useSpecialInit() -> Struct1 {
// FIXME: the below triggers an assert, due to number or params mismatch
// return Struct1(specialLabel:())
return Struct1(specialLabel:())
}

2 changes: 1 addition & 1 deletion test/api-digester/Inputs/Foo-new-version/foo.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#import <Foundation.h>
@import ObjectiveC;

@protocol ObjcProt
-(void) someFunctionFromProt;
Expand Down
1 change: 1 addition & 0 deletions test/api-digester/Inputs/Foo-new-version/module.modulemap
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module Foo {
header "foo.h"
export *
}
2 changes: 1 addition & 1 deletion test/api-digester/Inputs/Foo/foo.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#import <Foundation.h>
@import ObjectiveC;

@protocol ObjcProt
-(void) someFunctionFromProt;
Expand Down
1 change: 1 addition & 0 deletions test/api-digester/Inputs/Foo/module.modulemap
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module Foo {
header "foo.h"
export *
}
1 change: 1 addition & 0 deletions validation-test/Reflection/Inputs/ObjCClasses/module.map
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module ObjCClasses {
header "ObjCClasses.h"
export *
}