diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b07b9544dc3d3..e060a8dd6261e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -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", diff --git a/include/swift/SIL/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h index 3966fb5302168..6841a7161fd63 100644 --- a/include/swift/SIL/SILDeclRef.h +++ b/include/swift/SIL/SILDeclRef.h @@ -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); diff --git a/lib/AST/UnqualifiedLookup.cpp b/lib/AST/UnqualifiedLookup.cpp index 51820b41a9ca8..45f6ed4b3fcb1 100644 --- a/lib/AST/UnqualifiedLookup.cpp +++ b/lib/AST/UnqualifiedLookup.cpp @@ -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); diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 8f5648145d350..9d0bed0087c8d 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -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()); + } } } diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index b615b98c9e51a..592f05e988b25 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -1153,6 +1153,29 @@ bool SILDeclRef::hasNonUniqueDefinition() const { return false; } +bool SILDeclRef::declExposedToForeignLanguage(const ValueDecl *decl) { + // @c / @_cdecl / @objc. + if (decl->getAttrs().hasAttribute() || + (decl->getAttrs().hasAttribute() && + decl->getDeclContext()->isModuleScopeContext())) { + return true; + } + + // @_expose that isn't negated. + for (auto *expose : decl->getAttrs().getAttributes()) { + 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)) @@ -1167,6 +1190,28 @@ bool SILDeclRef::declHasNonUniqueDefinition(const ValueDecl *decl) { if (decl->getAttrs().hasAttribute()) 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() || + decl->getAttrs().hasAttribute()) { + return false; + } + auto module = decl->getModuleContext(); auto &ctx = module->getASTContext(); diff --git a/lib/SIL/IR/SILFunction.cpp b/lib/SIL/IR/SILFunction.cpp index 7713ae57f345b..69e1d4793c999 100644 --- a/lib/SIL/IR/SILFunction.cpp +++ b/lib/SIL/IR/SILFunction.cpp @@ -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; diff --git a/lib/SIL/IR/SILGlobalVariable.cpp b/lib/SIL/IR/SILGlobalVariable.cpp index c32ccfbb9ded2..241a39eb4126e 100644 --- a/lib/SIL/IR/SILGlobalVariable.cpp +++ b/lib/SIL/IR/SILGlobalVariable.cpp @@ -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()); } diff --git a/test/NameLookup/Inputs/accessibility_other.swift b/test/NameLookup/Inputs/accessibility_other.swift index 8fcfbd44739b2..4c001873d1ea0 100644 --- a/test/NameLookup/Inputs/accessibility_other.swift +++ b/test/NameLookup/Inputs/accessibility_other.swift @@ -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() {} diff --git a/test/NameLookup/accessibility.swift b/test/NameLookup/accessibility.swift index eac3b6b186d0b..4c3524ed5860a 100644 --- a/test/NameLookup/accessibility.swift +++ b/test/NameLookup/accessibility.swift @@ -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}} @@ -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 { diff --git a/test/decl/ext/Inputs/c_decls.h b/test/decl/ext/Inputs/c_decls.h new file mode 100644 index 0000000000000..9f9526fec249c --- /dev/null +++ b/test/decl/ext/Inputs/c_decls.h @@ -0,0 +1 @@ +double c_function_returns_double(void); diff --git a/test/decl/ext/Inputs/module.modulemap b/test/decl/ext/Inputs/module.modulemap new file mode 100644 index 0000000000000..796a273ec3dd7 --- /dev/null +++ b/test/decl/ext/Inputs/module.modulemap @@ -0,0 +1,3 @@ +module ToBeImplemented { + header "c_decls.h" +} diff --git a/test/decl/ext/cdecl_official_implementation.swift b/test/decl/ext/cdecl_official_implementation.swift index d0d596d87bc19..87ddea64ccd72 100644 --- a/test/decl/ext/cdecl_official_implementation.swift +++ b/test/decl/ext/cdecl_official_implementation.swift @@ -1,5 +1,6 @@ // 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 @@ -7,6 +8,11 @@ // 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 @@ -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 @@ -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. } @@ -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) } } @@ -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}} } } diff --git a/test/decl/ext/objc_implementation.swift b/test/decl/ext/objc_implementation.swift index 73382ad12f3b6..1b7f852347815 100644 --- a/test/decl/ext/objc_implementation.swift +++ b/test/decl/ext/objc_implementation.swift @@ -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 {} @@ -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") @@ -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. } @@ -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) } } @@ -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}} } } diff --git a/test/decl/ext/objc_implementation_early_adopter.swift b/test/decl/ext/objc_implementation_early_adopter.swift index f8b2f5461c710..3170083a269c1 100644 --- a/test/decl/ext/objc_implementation_early_adopter.swift +++ b/test/decl/ext/objc_implementation_early_adopter.swift @@ -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 {} @@ -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") @@ -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. } @@ -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) } } @@ -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}} } } diff --git a/test/embedded/linkage/Inputs/MyModuleExports.h b/test/embedded/linkage/Inputs/MyModuleExports.h new file mode 100644 index 0000000000000..ab74ed6f4f450 --- /dev/null +++ b/test/embedded/linkage/Inputs/MyModuleExports.h @@ -0,0 +1,4 @@ +double clib_func1(void); +double clib_func2(void); +double clib_func3(void); +double clib_func4(void); diff --git a/test/embedded/linkage/Inputs/module.modulemap b/test/embedded/linkage/Inputs/module.modulemap index 5445080fa9516..a1f15125ed19d 100644 --- a/test/embedded/linkage/Inputs/module.modulemap +++ b/test/embedded/linkage/Inputs/module.modulemap @@ -1,3 +1,7 @@ module CDependency { header "CHeader.h" } + +module MyModuleExports { + header "MyModuleExports.h" +} diff --git a/test/embedded/linkage/c.swift b/test/embedded/linkage/c.swift new file mode 100644 index 0000000000000..2edc76eac5618 --- /dev/null +++ b/test/embedded/linkage/c.swift @@ -0,0 +1,81 @@ +// Check that C functions are exported as needed. + +// REQUIRES: swift_in_compiler +// REQUIRES: executable_test +// REQUIRES: swift_feature_Embedded +// REQUIRES: swift_feature_DeferredCodeGen +// REQUIRES: swift_feature_CDecl +// REQUIRES: swift_feature_CImplementation +// REQUIRES: swift_feature_SymbolLinkageMarkers + +// RUN: %target-swift-frontend -emit-ir -o - %s -I %S/Inputs -package-name MyPackage -enable-experimental-feature Embedded -enable-experimental-feature DeferredCodeGen -enable-experimental-feature CDecl -enable-experimental-feature CImplementation -enable-experimental-feature SymbolLinkageMarkers -parse-as-library | %FileCheck %s + +import MyModuleExports + +// --------------------------------------------------------------------------- +// @c / @_cdecl on > internal declarations cause symbol emission +// --------------------------------------------------------------------------- + +// CHECK: define {{(protected |dllexport )?}}void @lib_publicCDeclFunc() +@_cdecl("lib_publicCDeclFunc") +public func f1() { } + +// CHECK: define {{(protected |dllexport )?}}void @lib_publicCFunc() +@c(lib_publicCFunc) +package func f2() { } + +// CHECK: define hidden void @lib_publicCDeclFunc3 +@_cdecl("lib_publicCDeclFunc3") +internal func f3() { } + +// CHECK: define hidden void @lib_publicCDeclFunc4 +@c("lib_publicCDeclFunc4") +internal func f4() { } + +// CHECK-NOT: lib_publicCDeclFunc5 +@_cdecl("lib_publicCDeclFunc5") +private func f5() { } + +// CHECK-NOT: lib_publicCDeclFunc6 +@c("lib_publicCDeclFunc6") +private func f6() { } + +// --------------------------------------------------------------------------- +// @implementation @c / @_cdecl cause symbol emission +// --------------------------------------------------------------------------- + +// CHECK: define {{(protected |dllexport )?}}double @clib_func1 +@_cdecl("clib_func1") @implementation +public func clib_func1() -> Double { 0 } + +// CHECK: define {{(protected |dllexport )?}}double @clib_func2 +@c @implementation +package func clib_func2() -> Double { 0 } + +// CHECK: define hidden double @clib_func3 +@_cdecl("clib_func3") @implementation +internal func clib_func3() -> Double { 0 } + +// CHECK: define hidden double @clib_func4 +@c @implementation +internal func clib_func4() -> Double { 0 } + +// --------------------------------------------------------------------------- +// @_section causes symbol emission +// --------------------------------------------------------------------------- + +// CHECK: define {{(protected |dllexport )?}}swiftcc void @"$e1c15symbolInSectionyyF" +@_section("__TEXT,__mysection") +public func symbolInSection() { } + +// CHECK: define hidden swiftcc void @"$e1c23internalSymbolInSectionyyF" +@_section("__TEXT,__mysection") +func internalSymbolInSection() { } + +// --------------------------------------------------------------------------- +// @_used causes symbol emission +// --------------------------------------------------------------------------- + +// CHECK: define hidden swiftcc void @"$e1c10usedSymbolyyF" +@_used +func usedSymbol() { } diff --git a/test/embedded/linkage/cxx.swift b/test/embedded/linkage/cxx.swift new file mode 100644 index 0000000000000..7390e8d123de4 --- /dev/null +++ b/test/embedded/linkage/cxx.swift @@ -0,0 +1,16 @@ +// Check that C++ functions are exported as needed. + +// REQUIRES: swift_in_compiler +// REQUIRES: executable_test +// REQUIRES: swift_feature_Embedded +// REQUIRES: swift_feature_DeferredCodeGen + +// RUN: %target-swift-frontend -emit-ir -o - %s -I %S/Inputs -package-name MyPackage -enable-experimental-feature Embedded -enable-experimental-feature DeferredCodeGen -parse-as-library -cxx-interoperability-mode=default | %FileCheck %s + +// CHECK: define hidden swiftcc void @"$e3cxx2f1yyF"() +@_expose(Cxx) +func f1() { } + +// CHECK-NOT: 2f2 +@_expose(!Cxx) +public func f2() { }