Skip to content

Commit 67c7fbc

Browse files
committed
[SE-0495] Make sure we can find imported C functions for @c @implementation
@c @implementation relies on matching the original C declaration. The lookup for the original C declaration was doing the wrong kind of lookup, meaning that it could only find the C declaration if it came through a bridging header, and not through a normal module import. Using unqualified lookup here finds the name appropriately. Clarify the diagnostics here as well to not talk about umbrella and bridging headers. Fixes rdar://161909754.
1 parent bc88160 commit 67c7fbc

File tree

10 files changed

+52
-31
lines changed

10 files changed

+52
-31
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,12 +1879,12 @@ ERROR(objc_implementation_cannot_have_generics,none,
18791879
"'@objc @implementation' cannot be used to implement %kind0",
18801880
(ValueDecl *))
18811881
ERROR(attr_objc_implementation_category_not_found,none,
1882-
"could not find category %0 on Objective-C class %1; make sure your "
1883-
"umbrella or bridging header imports the header that declares it",
1882+
"could not find category %0 on Objective-C class %1; make sure you "
1883+
"import the module or header that declares it",
18841884
(Identifier, ValueDecl*))
18851885
ERROR(attr_objc_implementation_func_not_found,none,
1886-
"could not find imported function '%0' matching %kind1; make sure your "
1887-
"umbrella or bridging header imports the header that declares it",
1886+
"could not find imported function '%0' matching %kind1; make sure you "
1887+
"import the module or header that declares it",
18881888
(StringRef, ValueDecl*))
18891889
NOTE(attr_objc_implementation_fixit_remove_category_name,none,
18901890
"remove arguments to implement the main '@interface' for this class",

lib/AST/UnqualifiedLookup.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,9 @@ void UnqualifiedLookupFactory::addImportedResults(const DeclContext *const dc) {
483483
nlOptions |= NL_ExcludeMacroExpansions;
484484
if (options.contains(Flags::ABIProviding))
485485
nlOptions |= NL_ABIProviding;
486+
if (options.contains(Flags::IgnoreAccessControl))
487+
nlOptions |= NL_IgnoreAccessControl;
488+
486489
lookupInModule(dc, Name.getFullName(), CurModuleResults,
487490
NLKind::UnqualifiedLookup, resolutionKind, dc,
488491
Loc, nlOptions);

lib/ClangImporter/ClangImporter.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6689,15 +6689,23 @@ static void lookupRelatedFuncs(AbstractFunctionDecl *func,
66896689
else
66906690
swiftName = func->getName();
66916691

6692-
NLOptions options = NL_IgnoreAccessControl | NL_IgnoreMissingImports;
66936692
if (auto ty = func->getDeclContext()->getSelfNominalTypeDecl()) {
6693+
NLOptions options = NL_IgnoreAccessControl | NL_IgnoreMissingImports;
66946694
ty->lookupQualified({ ty }, DeclNameRef(swiftName), func->getLoc(),
66956695
NL_QualifiedDefault | options, results);
66966696
}
66976697
else {
6698-
auto mod = func->getDeclContext()->getParentModule();
6699-
mod->lookupQualified(mod, DeclNameRef(swiftName), func->getLoc(),
6700-
NL_RemoveOverridden | options, results);
6698+
ASTContext &ctx = func->getASTContext();
6699+
UnqualifiedLookupOptions options =
6700+
UnqualifiedLookupFlags::IgnoreAccessControl;
6701+
UnqualifiedLookupDescriptor descriptor(
6702+
DeclNameRef(ctx, Identifier(), swiftName), func->getDeclContext(),
6703+
func->getLoc(), options);
6704+
auto lookup = evaluateOrDefault(func->getASTContext().evaluator,
6705+
UnqualifiedLookupRequest{descriptor}, {});
6706+
for (const auto &result : lookup) {
6707+
results.push_back(result.getValueDecl());
6708+
}
67016709
}
67026710
}
67036711

test/NameLookup/Inputs/accessibility_other.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import has_accessibility
22

33
public let a = 0 // expected-note * {{did you mean 'a'?}}
44
internal let b = 0 // expected-note * {{did you mean 'b'?}}
5-
private let c = 0 // expected-note {{'c' declared here}}
5+
private let c = 0 // expected-note 2 {{'c' declared here}}
66

77
extension Foo {
88
public static func a() {}

test/NameLookup/accessibility.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ markUsed(z) // expected-error {{cannot find 'z' in scope}}
3737

3838
markUsed(a)
3939
markUsed(b)
40-
markUsed(c) // expected-error {{cannot find 'c' in scope}}
40+
markUsed(c) // expected-error {{'c' is inaccessible due to 'private' protection level}}
4141

4242
Foo.x()
4343
Foo.y() // expected-error {{'y' is inaccessible due to 'internal' protection level}}
@@ -64,7 +64,7 @@ _ = PrivateInit() // expected-error {{'PrivateInit' initializer is inaccessible
6464
// TESTABLE: :[[@LINE-1]]:{{[^:]+}}: error: 'PrivateInit' initializer is inaccessible due to 'private' protection level
6565

6666
var s = StructWithPrivateSetter()
67-
// expected-note@-1 3{{did you mean 's'?}}
67+
// expected-note@-1 2{{did you mean 's'?}}
6868
s.x = 42 // expected-error {{cannot assign to property: 'x' setter is inaccessible}}
6969

7070
class Sub : Base {

test/decl/ext/Inputs/c_decls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
double c_function_returns_double(void);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module ToBeImplemented {
2+
header "c_decls.h"
3+
}

test/decl/ext/cdecl_official_implementation.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
// RUN: %target-typecheck-verify-swift -target %target-stable-abi-triple \
22
// RUN: -import-bridging-header %S/Inputs/objc_implementation.h \
3+
// RUN: -I %S/Inputs \
34
// RUN: -disable-objc-interop \
45
// RUN: -enable-experimental-feature CImplementation \
56
// RUN: -enable-experimental-feature CDecl
67

78
// REQUIRES: swift_feature_CImplementation
89
// REQUIRES: swift_feature_CDecl
910

11+
import ToBeImplemented
12+
13+
@implementation @c
14+
func c_function_returns_double() -> Double { 0 }
15+
1016
@implementation @c
1117
func CImplFunc1(_: Int32) {
1218
// OK
@@ -24,7 +30,7 @@ func CImplFunc2(_: Int32) {
2430

2531
@implementation @c
2632
func CImplFuncMissing(_: Int32) {
27-
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure your umbrella or bridging header imports the header that declares it}}
33+
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure you import the module or header that declares it}}
2834
}
2935

3036
@implementation @c
@@ -39,13 +45,13 @@ func CImplFuncMismatch2(_: Int32) -> Float {
3945

4046
@implementation @c(CImplFuncNameMismatch1)
4147
func mismatchedName1(_: Int32) {
42-
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure your umbrella or bridging header imports the header that declares it}}
48+
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure you import the module or header that declares it}}
4349
// FIXME: Improve diagnostic for a partial match.
4450
}
4551

4652
@implementation @c(mismatchedName2)
4753
func CImplFuncNameMismatch2(_: Int32) {
48-
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure your umbrella or bridging header imports the header that declares it}}
54+
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure you import the module or header that declares it}}
4955
// FIXME: Improve diagnostic for a partial match.
5056
}
5157

@@ -56,14 +62,14 @@ var cImplComputedGlobal1: Int32 {
5662
@implementation @c(CImplGetComputedGlobal1)
5763
get {
5864
// FIXME: Lookup for vars isn't working yet
59-
// expected-error@-3 {{could not find imported function 'CImplGetComputedGlobal1' matching getter for var 'cImplComputedGlobal1'; make sure your umbrella or bridging header imports the header that declares it}}
65+
// expected-error@-3 {{could not find imported function 'CImplGetComputedGlobal1' matching getter for var 'cImplComputedGlobal1'; make sure you import the module or header that declares it}}
6066
return 0
6167
}
6268

6369
@implementation @c(CImplSetComputedGlobal1)
6470
set {
6571
// FIXME: Lookup for vars isn't working yet
66-
// expected-error@-3 {{could not find imported function 'CImplSetComputedGlobal1' matching setter for var 'cImplComputedGlobal1'; make sure your umbrella or bridging header imports the header that declares it}}
72+
// expected-error@-3 {{could not find imported function 'CImplSetComputedGlobal1' matching setter for var 'cImplComputedGlobal1'; make sure you import the module or header that declares it}}
6773
print(newValue)
6874
}
6975
}
@@ -77,6 +83,6 @@ extension CImplStruct {
7783
// FIXME: Add underlying support for this
7884
// expected-error@-3 {{@c can only be applied to global functions}}
7985
// FIXME: Lookup in an enclosing type is not working yet
80-
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure your umbrella or bridging header imports the header that declares it}}
86+
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure you import the module or header that declares it}}
8187
}
8288
}

test/decl/ext/objc_implementation.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ protocol EmptySwiftProto {}
503503
// expected-warning@-1 {{extension with Objective-C category name 'PresentAdditions' conflicts with previous extension with the same category name; this is an error in the Swift 6 language mode}}
504504

505505
@objc(MissingAdditions) @implementation extension ObjCClass {}
506-
// expected-error@-1 {{could not find category 'MissingAdditions' on Objective-C class 'ObjCClass'; make sure your umbrella or bridging header imports the header that declares it}}
506+
// expected-error@-1 {{could not find category 'MissingAdditions' on Objective-C class 'ObjCClass'; make sure you import the module or header that declares it}}
507507
// expected-note@-2 {{remove arguments to implement the main '@interface' for this class}} {{6-24=}}
508508

509509
@objc @implementation extension ObjCStruct {}
@@ -558,7 +558,7 @@ func CImplFunc2(_: Int32) {
558558

559559
@implementation @_cdecl("CImplFuncMissing")
560560
func CImplFuncMissing(_: Int32) {
561-
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure your umbrella or bridging header imports the header that declares it}}
561+
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure you import the module or header that declares it}}
562562
}
563563

564564
@implementation @_cdecl("CImplFuncMismatch1")
@@ -614,13 +614,13 @@ func CImplFuncMismatch6a(_: Int32) -> Any! {
614614

615615
@implementation @_cdecl("CImplFuncNameMismatch1")
616616
func mismatchedName1(_: Int32) {
617-
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure your umbrella or bridging header imports the header that declares it}}
617+
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure you import the module or header that declares it}}
618618
// FIXME: Improve diagnostic for a partial match.
619619
}
620620

621621
@implementation @_cdecl("mismatchedName2")
622622
func CImplFuncNameMismatch2(_: Int32) {
623-
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure your umbrella or bridging header imports the header that declares it}}
623+
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure you import the module or header that declares it}}
624624
// FIXME: Improve diagnostic for a partial match.
625625
}
626626

@@ -631,14 +631,14 @@ var cImplComputedGlobal1: Int32 {
631631
@implementation @_cdecl("CImplGetComputedGlobal1")
632632
get {
633633
// FIXME: Lookup for vars isn't working yet
634-
// expected-error@-3 {{could not find imported function 'CImplGetComputedGlobal1' matching getter for var 'cImplComputedGlobal1'; make sure your umbrella or bridging header imports the header that declares it}}
634+
// expected-error@-3 {{could not find imported function 'CImplGetComputedGlobal1' matching getter for var 'cImplComputedGlobal1'; make sure you import the module or header that declares it}}
635635
return 0
636636
}
637637

638638
@implementation @_cdecl("CImplSetComputedGlobal1")
639639
set {
640640
// FIXME: Lookup for vars isn't working yet
641-
// expected-error@-3 {{could not find imported function 'CImplSetComputedGlobal1' matching setter for var 'cImplComputedGlobal1'; make sure your umbrella or bridging header imports the header that declares it}}
641+
// expected-error@-3 {{could not find imported function 'CImplSetComputedGlobal1' matching setter for var 'cImplComputedGlobal1'; make sure you import the module or header that declares it}}
642642
print(newValue)
643643
}
644644
}
@@ -652,7 +652,7 @@ extension CImplStruct {
652652
// FIXME: Add underlying support for this
653653
// expected-error@-3 {{@_cdecl can only be applied to global functions}}
654654
// FIXME: Lookup in an enclosing type is not working yet
655-
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure your umbrella or bridging header imports the header that declares it}}
655+
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure you import the module or header that declares it}}
656656
}
657657
}
658658

test/decl/ext/objc_implementation_early_adopter.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ protocol EmptySwiftProto {}
507507
// expected-warning@-1 {{extension with Objective-C category name 'PresentAdditions' conflicts with previous extension with the same category name; this is an error in the Swift 6 language mode}}
508508

509509
@_objcImplementation(MissingAdditions) extension ObjCClass {}
510-
// expected-error@-1 {{could not find category 'MissingAdditions' on Objective-C class 'ObjCClass'; make sure your umbrella or bridging header imports the header that declares it}}
510+
// expected-error@-1 {{could not find category 'MissingAdditions' on Objective-C class 'ObjCClass'; make sure you import the module or header that declares it}}
511511
// expected-note@-2 {{remove arguments to implement the main '@interface' for this class}} {{21-39=}}
512512

513513
@_objcImplementation extension ObjCStruct {}
@@ -549,7 +549,7 @@ func CImplFunc2(_: Int32) {
549549

550550
@_objcImplementation @_cdecl("CImplFuncMissing")
551551
func CImplFuncMissing(_: Int32) {
552-
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure your umbrella or bridging header imports the header that declares it}}
552+
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure you import the module or header that declares it}}
553553
}
554554

555555
@_objcImplementation @_cdecl("CImplFuncMismatch1")
@@ -605,13 +605,13 @@ func CImplFuncMismatch6a(_: Int32) -> Any! {
605605

606606
@_objcImplementation @_cdecl("CImplFuncNameMismatch1")
607607
func mismatchedName1(_: Int32) {
608-
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure your umbrella or bridging header imports the header that declares it}}
608+
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure you import the module or header that declares it}}
609609
// FIXME: Improve diagnostic for a partial match.
610610
}
611611

612612
@_objcImplementation @_cdecl("mismatchedName2")
613613
func CImplFuncNameMismatch2(_: Int32) {
614-
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure your umbrella or bridging header imports the header that declares it}}
614+
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure you import the module or header that declares it}}
615615
// FIXME: Improve diagnostic for a partial match.
616616
}
617617

@@ -622,14 +622,14 @@ var cImplComputedGlobal1: Int32 {
622622
@_objcImplementation @_cdecl("CImplGetComputedGlobal1")
623623
get {
624624
// FIXME: Lookup for vars isn't working yet
625-
// expected-error@-3 {{could not find imported function 'CImplGetComputedGlobal1' matching getter for var 'cImplComputedGlobal1'; make sure your umbrella or bridging header imports the header that declares it}}
625+
// expected-error@-3 {{could not find imported function 'CImplGetComputedGlobal1' matching getter for var 'cImplComputedGlobal1'; make sure you import the module or header that declares it}}
626626
return 0
627627
}
628628

629629
@_objcImplementation @_cdecl("CImplSetComputedGlobal1")
630630
set {
631631
// FIXME: Lookup for vars isn't working yet
632-
// expected-error@-3 {{could not find imported function 'CImplSetComputedGlobal1' matching setter for var 'cImplComputedGlobal1'; make sure your umbrella or bridging header imports the header that declares it}}
632+
// expected-error@-3 {{could not find imported function 'CImplSetComputedGlobal1' matching setter for var 'cImplComputedGlobal1'; make sure you import the module or header that declares it}}
633633
print(newValue)
634634
}
635635
}
@@ -643,7 +643,7 @@ extension CImplStruct {
643643
// FIXME: Add underlying support for this
644644
// expected-error@-3 {{@_cdecl can only be applied to global functions}}
645645
// FIXME: Lookup in an enclosing type is not working yet
646-
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure your umbrella or bridging header imports the header that declares it}}
646+
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure you import the module or header that declares it}}
647647
}
648648
}
649649

0 commit comments

Comments
 (0)