Skip to content

Commit d9d7c99

Browse files
committed
AST: Only apply MemberImportVisibility to lookups from the main module.
MemberImportVisibility rules should only apply to source code in the main module. The rules were being applied when resolving witnesses for synthesized Hashable conformances on CF types imported by ClangImporter, which caused the lookups to fail and bad conformances to be generated. Resolves #78870 and rdar://142433039.
1 parent 95dca81 commit d9d7c99

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

lib/AST/NameLookup.cpp

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,22 +2340,27 @@ ObjCCategoryNameMap ClassDecl::getObjCCategoryNameMap() {
23402340
ObjCCategoryNameMap());
23412341
}
23422342

2343-
static bool missingImportForMemberDecl(const DeclContext *dc, ValueDecl *decl) {
2344-
// Only require explicit imports for members when MemberImportVisibility is
2345-
// enabled.
2346-
auto &ctx = dc->getASTContext();
2343+
/// Determines whether MemberImportVisiblity should be enforced for lookups in
2344+
/// the given context.
2345+
static bool shouldRequireImportsInContext(const DeclContext *lookupContext) {
2346+
auto &ctx = lookupContext->getASTContext();
23472347
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility))
23482348
return false;
23492349

2350-
return !dc->isDeclImported(decl);
2350+
// Code outside of the main module (which is often synthesized) isn't subject
2351+
// to MemberImportVisibility rules.
2352+
if (lookupContext->getParentModule() != ctx.MainModule)
2353+
return false;
2354+
2355+
return true;
23512356
}
23522357

23532358
/// Determine whether the given declaration is an acceptable lookup
23542359
/// result when searching from the given DeclContext.
2355-
static bool isAcceptableLookupResult(const DeclContext *dc,
2356-
NLOptions options,
2360+
static bool isAcceptableLookupResult(const DeclContext *dc, NLOptions options,
23572361
ValueDecl *decl,
2358-
bool onlyCompleteObjectInits) {
2362+
bool onlyCompleteObjectInits,
2363+
bool requireImport) {
23592364
// Filter out designated initializers, if requested.
23602365
if (onlyCompleteObjectInits) {
23612366
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
@@ -2383,10 +2388,9 @@ static bool isAcceptableLookupResult(const DeclContext *dc,
23832388

23842389
// Check that there is some import in the originating context that makes this
23852390
// decl visible.
2386-
if (!(options & NL_IgnoreMissingImports)) {
2387-
if (missingImportForMemberDecl(dc, decl))
2391+
if (requireImport && !(options & NL_IgnoreMissingImports))
2392+
if (!dc->isDeclImported(decl))
23882393
return false;
2389-
}
23902394

23912395
// Check that it has the appropriate ABI role.
23922396
if (!ABIRoleInfo(decl).matchesOptions(options))
@@ -2620,6 +2624,9 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
26202624
// Whether we only want to return complete object initializers.
26212625
bool onlyCompleteObjectInits = false;
26222626

2627+
// Whether to enforce MemberImportVisibility import restrictions.
2628+
bool requireImport = shouldRequireImportsInContext(DC);
2629+
26232630
// Visit all of the nominal types we know about, discovering any others
26242631
// we need along the way.
26252632
bool wantProtocolMembers = (options & NL_ProtocolMembers);
@@ -2654,7 +2661,8 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
26542661
if ((options & NL_OnlyMacros) && !isa<MacroDecl>(decl))
26552662
continue;
26562663

2657-
if (isAcceptableLookupResult(DC, options, decl, onlyCompleteObjectInits))
2664+
if (isAcceptableLookupResult(DC, options, decl, onlyCompleteObjectInits,
2665+
requireImport))
26582666
decls.push_back(decl);
26592667
}
26602668

@@ -2792,6 +2800,9 @@ AnyObjectLookupRequest::evaluate(Evaluator &evaluator, const DeclContext *dc,
27922800
member.getFullName(), allDecls);
27932801
}
27942802

2803+
/// Whether to enforce MemberImportVisibility import restrictions.
2804+
bool requireImport = shouldRequireImportsInContext(dc);
2805+
27952806
// For each declaration whose context is not something we've
27962807
// already visited above, add it to the list of declarations.
27972808
llvm::SmallPtrSet<ValueDecl *, 4> knownDecls;
@@ -2824,7 +2835,8 @@ AnyObjectLookupRequest::evaluate(Evaluator &evaluator, const DeclContext *dc,
28242835
// result, add it to the list.
28252836
if (knownDecls.insert(decl).second &&
28262837
isAcceptableLookupResult(dc, options, decl,
2827-
/*onlyCompleteObjectInits=*/false))
2838+
/*onlyCompleteObjectInits=*/false,
2839+
requireImport))
28282840
decls.push_back(decl);
28292841
}
28302842

test/ClangImporter/Security_test.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -verify
2+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -enable-upcoming-feature MemberImportVisibility -verify
23

34
// REQUIRES: objc_interop
45

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-frontend -emit-sil %s -verify
2+
// RUN: %target-swift-frontend -emit-sil %s -enable-upcoming-feature MemberImportVisibility -verify
3+
4+
// REQUIRES: VENDOR=apple
5+
// REQUIRES: swift_feature_MemberImportVisibility
6+
7+
import CoreFoundation
8+
9+
public func takesHashable<T: Hashable>(_ t: T) {}
10+
11+
public func takesCFObjects(
12+
_ string: CFString,
13+
_ number: CFNumber,
14+
_ date: CFDate,
15+
_ data: CFData,
16+
_ set: CFSet,
17+
) {
18+
takesHashable(string)
19+
takesHashable(number)
20+
takesHashable(date)
21+
takesHashable(data)
22+
takesHashable(set)
23+
}

0 commit comments

Comments
 (0)