Skip to content
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
8 changes: 4 additions & 4 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1879,12 +1879,12 @@ ERROR(objc_implementation_cannot_have_generics,none,
"'@objc @implementation' cannot be used to implement %kind0",
(ValueDecl *))
ERROR(attr_objc_implementation_category_not_found,none,
"could not find category %0 on Objective-C class %1; make sure your "
"umbrella or bridging header imports the header that declares it",
"could not find category %0 on Objective-C class %1; make sure you "
"import the module or header that declares it",
(Identifier, ValueDecl*))
ERROR(attr_objc_implementation_func_not_found,none,
"could not find imported function '%0' matching %kind1; make sure your "
"umbrella or bridging header imports the header that declares it",
"could not find imported function '%0' matching %kind1; make sure you "
"import the module or header that declares it",
(StringRef, ValueDecl*))
NOTE(attr_objc_implementation_fixit_remove_category_name,none,
"remove arguments to implement the main '@interface' for this class",
Expand Down
4 changes: 4 additions & 0 deletions include/swift/SIL/SILDeclRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ struct SILDeclRef {
/// embedded linkage model.
bool hasNonUniqueDefinition() const;

/// True if the declaration is explicitly marked as being exposed to a
/// foreign language or environment,
static bool declExposedToForeignLanguage(const ValueDecl *decl);

/// True if the declaration should have a non-unique definition based on the
/// embedded linkage model.
static bool declHasNonUniqueDefinition(const ValueDecl *decl);
Expand Down
3 changes: 3 additions & 0 deletions lib/AST/UnqualifiedLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,9 @@ void UnqualifiedLookupFactory::addImportedResults(const DeclContext *const dc) {
nlOptions |= NL_ExcludeMacroExpansions;
if (options.contains(Flags::ABIProviding))
nlOptions |= NL_ABIProviding;
if (options.contains(Flags::IgnoreAccessControl))
nlOptions |= NL_IgnoreAccessControl;

lookupInModule(dc, Name.getFullName(), CurModuleResults,
NLKind::UnqualifiedLookup, resolutionKind, dc,
Loc, nlOptions);
Expand Down
16 changes: 12 additions & 4 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6689,15 +6689,23 @@ static void lookupRelatedFuncs(AbstractFunctionDecl *func,
else
swiftName = func->getName();

NLOptions options = NL_IgnoreAccessControl | NL_IgnoreMissingImports;
if (auto ty = func->getDeclContext()->getSelfNominalTypeDecl()) {
NLOptions options = NL_IgnoreAccessControl | NL_IgnoreMissingImports;
ty->lookupQualified({ ty }, DeclNameRef(swiftName), func->getLoc(),
NL_QualifiedDefault | options, results);
}
else {
auto mod = func->getDeclContext()->getParentModule();
mod->lookupQualified(mod, DeclNameRef(swiftName), func->getLoc(),
NL_RemoveOverridden | options, results);
ASTContext &ctx = func->getASTContext();
UnqualifiedLookupOptions options =
UnqualifiedLookupFlags::IgnoreAccessControl;
UnqualifiedLookupDescriptor descriptor(
DeclNameRef(ctx, Identifier(), swiftName), func->getDeclContext(),
func->getLoc(), options);
auto lookup = evaluateOrDefault(func->getASTContext().evaluator,
UnqualifiedLookupRequest{descriptor}, {});
for (const auto &result : lookup) {
results.push_back(result.getValueDecl());
}
}
}

Expand Down
45 changes: 45 additions & 0 deletions lib/SIL/IR/SILDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,29 @@ bool SILDeclRef::hasNonUniqueDefinition() const {
return false;
}

bool SILDeclRef::declExposedToForeignLanguage(const ValueDecl *decl) {
// @c / @_cdecl / @objc.
if (decl->getAttrs().hasAttribute<CDeclAttr>() ||
(decl->getAttrs().hasAttribute<ObjCAttr>() &&
decl->getDeclContext()->isModuleScopeContext())) {
return true;
}

// @_expose that isn't negated.
for (auto *expose : decl->getAttrs().getAttributes<ExposeAttr>()) {
switch (expose->getExposureKind()) {
case ExposureKind::Cxx:
case ExposureKind::Wasm:
return true;

case ExposureKind::NotCxx:
continue;
}
}

return false;
}

bool SILDeclRef::declHasNonUniqueDefinition(const ValueDecl *decl) {
// This function only forces the issue in embedded.
if (!decl->getASTContext().LangOpts.hasFeature(Feature::Embedded))
Expand All @@ -1167,6 +1190,28 @@ bool SILDeclRef::declHasNonUniqueDefinition(const ValueDecl *decl) {
if (decl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
return true;

// If the declaration is marked in a manner that indicates that other
// systems will expect it to have a symbol, then it has a unique definition.
// There are a few cases here.

// - @implementation explicitly says that we are implementing something to
// be called from another language, so call it non-unique.
if (decl->isObjCImplementation())
return false;

// - @c / @_cdecl / @objc / @_expose expect to be called from another
// language if the symbol itself would be visible.
if (declExposedToForeignLanguage(decl) &&
decl->getFormalAccess() >= AccessLevel::Internal) {
return false;
}

// - @_section and @_used imply that external tools will look for this symbol.
if (decl->getAttrs().hasAttribute<SectionAttr>() ||
decl->getAttrs().hasAttribute<UsedAttr>()) {
return false;
}

auto module = decl->getModuleContext();
auto &ctx = module->getASTContext();

Expand Down
12 changes: 12 additions & 0 deletions lib/SIL/IR/SILFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,18 @@ SILFunction::isPossiblyUsedExternally() const {
if (markedAsUsed())
return true;

// If this function is exposed to a foreign language, it can be used
// externally (by that language).
if (auto decl = getDeclRef().getDecl()) {
if (SILDeclRef::declExposedToForeignLanguage(decl))
return true;
}

// If this function was explicitly placed in a section or given a WebAssembly
// export, it can be used externally.
if (!Section.empty() || !WasmExportName.empty())
return true;

if (shouldBePreservedForDebugger())
return true;

Expand Down
3 changes: 3 additions & 0 deletions lib/SIL/IR/SILGlobalVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ bool SILGlobalVariable::isPossiblyUsedExternally() const {
if (markedAsUsed())
return true;

if (getSectionAttr())
return true;

SILLinkage linkage = getLinkage();
return swift::isPossiblyUsedExternally(linkage, getModule().isWholeModule());
}
Expand Down
2 changes: 1 addition & 1 deletion test/NameLookup/Inputs/accessibility_other.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import has_accessibility

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

extension Foo {
public static func a() {}
Expand Down
4 changes: 2 additions & 2 deletions test/NameLookup/accessibility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ markUsed(z) // expected-error {{cannot find 'z' in scope}}

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

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

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

class Sub : Base {
Expand Down
1 change: 1 addition & 0 deletions test/decl/ext/Inputs/c_decls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
double c_function_returns_double(void);
3 changes: 3 additions & 0 deletions test/decl/ext/Inputs/module.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module ToBeImplemented {
header "c_decls.h"
}
18 changes: 12 additions & 6 deletions test/decl/ext/cdecl_official_implementation.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
// RUN: %target-typecheck-verify-swift -target %target-stable-abi-triple \
// RUN: -import-bridging-header %S/Inputs/objc_implementation.h \
// RUN: -I %S/Inputs \
// RUN: -disable-objc-interop \
// RUN: -enable-experimental-feature CImplementation \
// RUN: -enable-experimental-feature CDecl

// REQUIRES: swift_feature_CImplementation
// REQUIRES: swift_feature_CDecl

import ToBeImplemented

@implementation @c
func c_function_returns_double() -> Double { 0 }

@implementation @c
func CImplFunc1(_: Int32) {
// OK
Expand All @@ -24,7 +30,7 @@ func CImplFunc2(_: Int32) {

@implementation @c
func CImplFuncMissing(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure you import the module or header that declares it}}
}

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

@implementation @c(CImplFuncNameMismatch1)
func mismatchedName1(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure you import the module or header that declares it}}
// FIXME: Improve diagnostic for a partial match.
}

@implementation @c(mismatchedName2)
func CImplFuncNameMismatch2(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure you import the module or header that declares it}}
// FIXME: Improve diagnostic for a partial match.
}

Expand All @@ -56,14 +62,14 @@ var cImplComputedGlobal1: Int32 {
@implementation @c(CImplGetComputedGlobal1)
get {
// FIXME: Lookup for vars isn't working yet
// 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}}
// 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}}
return 0
}

@implementation @c(CImplSetComputedGlobal1)
set {
// FIXME: Lookup for vars isn't working yet
// 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}}
// 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}}
print(newValue)
}
}
Expand All @@ -77,6 +83,6 @@ extension CImplStruct {
// FIXME: Add underlying support for this
// expected-error@-3 {{@c can only be applied to global functions}}
// FIXME: Lookup in an enclosing type is not working yet
// 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}}
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure you import the module or header that declares it}}
}
}
14 changes: 7 additions & 7 deletions test/decl/ext/objc_implementation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ protocol EmptySwiftProto {}
// 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}}

@objc(MissingAdditions) @implementation extension ObjCClass {}
// 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}}
// expected-error@-1 {{could not find category 'MissingAdditions' on Objective-C class 'ObjCClass'; make sure you import the module or header that declares it}}
// expected-note@-2 {{remove arguments to implement the main '@interface' for this class}} {{6-24=}}

@objc @implementation extension ObjCStruct {}
Expand Down Expand Up @@ -558,7 +558,7 @@ func CImplFunc2(_: Int32) {

@implementation @_cdecl("CImplFuncMissing")
func CImplFuncMissing(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure you import the module or header that declares it}}
}

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

@implementation @_cdecl("CImplFuncNameMismatch1")
func mismatchedName1(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure you import the module or header that declares it}}
// FIXME: Improve diagnostic for a partial match.
}

@implementation @_cdecl("mismatchedName2")
func CImplFuncNameMismatch2(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure you import the module or header that declares it}}
// FIXME: Improve diagnostic for a partial match.
}

Expand All @@ -631,14 +631,14 @@ var cImplComputedGlobal1: Int32 {
@implementation @_cdecl("CImplGetComputedGlobal1")
get {
// FIXME: Lookup for vars isn't working yet
// 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}}
// 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}}
return 0
}

@implementation @_cdecl("CImplSetComputedGlobal1")
set {
// FIXME: Lookup for vars isn't working yet
// 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}}
// 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}}
print(newValue)
}
}
Expand All @@ -652,7 +652,7 @@ extension CImplStruct {
// FIXME: Add underlying support for this
// expected-error@-3 {{@_cdecl can only be applied to global functions}}
// FIXME: Lookup in an enclosing type is not working yet
// 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}}
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure you import the module or header that declares it}}
}
}

Expand Down
14 changes: 7 additions & 7 deletions test/decl/ext/objc_implementation_early_adopter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ protocol EmptySwiftProto {}
// 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}}

@_objcImplementation(MissingAdditions) extension ObjCClass {}
// 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}}
// expected-error@-1 {{could not find category 'MissingAdditions' on Objective-C class 'ObjCClass'; make sure you import the module or header that declares it}}
// expected-note@-2 {{remove arguments to implement the main '@interface' for this class}} {{21-39=}}

@_objcImplementation extension ObjCStruct {}
Expand Down Expand Up @@ -549,7 +549,7 @@ func CImplFunc2(_: Int32) {

@_objcImplementation @_cdecl("CImplFuncMissing")
func CImplFuncMissing(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'CImplFuncMissing' matching global function 'CImplFuncMissing'; make sure you import the module or header that declares it}}
}

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

@_objcImplementation @_cdecl("CImplFuncNameMismatch1")
func mismatchedName1(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'CImplFuncNameMismatch1' matching global function 'mismatchedName1'; make sure you import the module or header that declares it}}
// FIXME: Improve diagnostic for a partial match.
}

@_objcImplementation @_cdecl("mismatchedName2")
func CImplFuncNameMismatch2(_: Int32) {
// 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}}
// expected-error@-2 {{could not find imported function 'mismatchedName2' matching global function 'CImplFuncNameMismatch2'; make sure you import the module or header that declares it}}
// FIXME: Improve diagnostic for a partial match.
}

Expand All @@ -622,14 +622,14 @@ var cImplComputedGlobal1: Int32 {
@_objcImplementation @_cdecl("CImplGetComputedGlobal1")
get {
// FIXME: Lookup for vars isn't working yet
// 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}}
// 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}}
return 0
}

@_objcImplementation @_cdecl("CImplSetComputedGlobal1")
set {
// FIXME: Lookup for vars isn't working yet
// 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}}
// 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}}
print(newValue)
}
}
Expand All @@ -643,7 +643,7 @@ extension CImplStruct {
// FIXME: Add underlying support for this
// expected-error@-3 {{@_cdecl can only be applied to global functions}}
// FIXME: Lookup in an enclosing type is not working yet
// 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}}
// expected-error@-5 {{could not find imported function 'CImplStructStaticFunc1' matching static method 'staticFunc1'; make sure you import the module or header that declares it}}
}
}

Expand Down
4 changes: 4 additions & 0 deletions test/embedded/linkage/Inputs/MyModuleExports.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
double clib_func1(void);
double clib_func2(void);
double clib_func3(void);
double clib_func4(void);
4 changes: 4 additions & 0 deletions test/embedded/linkage/Inputs/module.modulemap
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
module CDependency {
header "CHeader.h"
}

module MyModuleExports {
header "MyModuleExports.h"
}
Loading