Skip to content

Commit 1533f54

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 cfb9eda commit 1533f54

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
@@ -2330,22 +2330,27 @@ ObjCCategoryNameMap ClassDecl::getObjCCategoryNameMap() {
23302330
ObjCCategoryNameMap());
23312331
}
23322332

2333-
static bool missingImportForMemberDecl(const DeclContext *dc, ValueDecl *decl) {
2334-
// Only require explicit imports for members when MemberImportVisibility is
2335-
// enabled.
2336-
auto &ctx = dc->getASTContext();
2333+
/// Determines whether MemberImportVisiblity should be enforced for lookups in
2334+
/// the given context.
2335+
static bool shouldRequireImportsInContext(const DeclContext *lookupContext) {
2336+
auto &ctx = lookupContext->getASTContext();
23372337
if (!ctx.LangOpts.hasFeature(Feature::MemberImportVisibility))
23382338
return false;
23392339

2340-
return !dc->isDeclImported(decl);
2340+
// Code outside of the main module (which is often synthesized) isn't subject
2341+
// to MemberImportVisibility rules.
2342+
if (lookupContext->getParentModule() != ctx.MainModule)
2343+
return false;
2344+
2345+
return true;
23412346
}
23422347

23432348
/// Determine whether the given declaration is an acceptable lookup
23442349
/// result when searching from the given DeclContext.
2345-
static bool isAcceptableLookupResult(const DeclContext *dc,
2346-
NLOptions options,
2350+
static bool isAcceptableLookupResult(const DeclContext *dc, NLOptions options,
23472351
ValueDecl *decl,
2348-
bool onlyCompleteObjectInits) {
2352+
bool onlyCompleteObjectInits,
2353+
bool requireImport) {
23492354
// Filter out designated initializers, if requested.
23502355
if (onlyCompleteObjectInits) {
23512356
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
@@ -2373,10 +2378,9 @@ static bool isAcceptableLookupResult(const DeclContext *dc,
23732378

23742379
// Check that there is some import in the originating context that makes this
23752380
// decl visible.
2376-
if (!(options & NL_IgnoreMissingImports)) {
2377-
if (missingImportForMemberDecl(dc, decl))
2381+
if (requireImport && !(options & NL_IgnoreMissingImports))
2382+
if (!dc->isDeclImported(decl))
23782383
return false;
2379-
}
23802384

23812385
return true;
23822386
}
@@ -2593,6 +2597,9 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
25932597
// Whether we only want to return complete object initializers.
25942598
bool onlyCompleteObjectInits = false;
25952599

2600+
// Whether to enforce MemberImportVisibility import restrictions.
2601+
bool requireImport = shouldRequireImportsInContext(DC);
2602+
25962603
// Visit all of the nominal types we know about, discovering any others
25972604
// we need along the way.
25982605
bool wantProtocolMembers = (options & NL_ProtocolMembers);
@@ -2625,7 +2632,8 @@ QualifiedLookupRequest::evaluate(Evaluator &eval, const DeclContext *DC,
26252632
if ((options & NL_OnlyMacros) && !isa<MacroDecl>(decl))
26262633
continue;
26272634

2628-
if (isAcceptableLookupResult(DC, options, decl, onlyCompleteObjectInits))
2635+
if (isAcceptableLookupResult(DC, options, decl, onlyCompleteObjectInits,
2636+
requireImport))
26292637
decls.push_back(decl);
26302638
}
26312639

@@ -2762,6 +2770,9 @@ AnyObjectLookupRequest::evaluate(Evaluator &evaluator, const DeclContext *dc,
27622770
member.getFullName(), allDecls);
27632771
}
27642772

2773+
/// Whether to enforce MemberImportVisibility import restrictions.
2774+
bool requireImport = shouldRequireImportsInContext(dc);
2775+
27652776
// For each declaration whose context is not something we've
27662777
// already visited above, add it to the list of declarations.
27672778
llvm::SmallPtrSet<ValueDecl *, 4> knownDecls;
@@ -2794,7 +2805,8 @@ AnyObjectLookupRequest::evaluate(Evaluator &evaluator, const DeclContext *dc,
27942805
// result, add it to the list.
27952806
if (knownDecls.insert(decl).second &&
27962807
isAcceptableLookupResult(dc, options, decl,
2797-
/*onlyCompleteObjectInits=*/false))
2808+
/*onlyCompleteObjectInits=*/false,
2809+
requireImport))
27982810
decls.push_back(decl);
27992811
}
28002812

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)