From 0619a83380703bac86eb8a762ab0931762e30759 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Fri, 13 Dec 2024 16:41:17 -0800 Subject: [PATCH] SIL: Always give @_silgen_name forward declarations public linkage. When `@_silgen_name` is applied to a function with no body, it is a forward declaration. It therefore must be treated as an external (public) declaration regardless of the access level it was given in source. Resolves rdar://141436934. --- lib/SIL/IR/SILDeclRef.cpp | 8 +++++ test/IRGen/silgen_name_linkage.swift | 49 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 test/IRGen/silgen_name_linkage.swift diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index ae96bd37a6cdf..3180203db0b99 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -651,6 +651,14 @@ SILLinkage SILDeclRef::getDefinitionLinkage() const { effectiveAccess = std::max(effectiveAccess, AccessLevel::Internal); } + // Declarations with a @_silgen_name attribute and no body may be forward + // declarations of functions defined in another module. Therefore they must + // always have external (public) linkage, regardless of declared access level. + if (auto afd = getAbstractFunctionDecl()) { + if (!afd->hasBody() && afd->getAttrs().hasAttribute()) + effectiveAccess = AccessLevel::Public; + } + switch (effectiveAccess) { case AccessLevel::Private: case AccessLevel::FilePrivate: diff --git a/test/IRGen/silgen_name_linkage.swift b/test/IRGen/silgen_name_linkage.swift new file mode 100644 index 0000000000000..9993727edd0e0 --- /dev/null +++ b/test/IRGen/silgen_name_linkage.swift @@ -0,0 +1,49 @@ +// RUN: %target-swift-frontend -parse-as-library -emit-ir %s | %FileCheck %s + +// Since this test depends on weak linking based on availability, it only +// applies to Apple platforms. +// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=visionos + +@available(SwiftStdlib 9999, *) +@_silgen_name("privateForwardDecl") +private func privateForwardDecl() + +@available(SwiftStdlib 9999, *) +@_silgen_name("internalForwardDecl") +internal func internalForwardDecl() + +@available(SwiftStdlib 9999, *) +@_silgen_name("publicForwardDecl") +public func publicForwardDecl() + +@available(SwiftStdlib 9999, *) +@_silgen_name("privateDefined") +private func privateDefined() {} + +// CHECK: define internal swiftcc void @privateDefined() + +@available(SwiftStdlib 9999, *) +@_silgen_name("internalDefined") +internal func internalDefined() {} + +// CHECK: define hidden swiftcc void @internalDefined() + +@available(SwiftStdlib 9999, *) +@_silgen_name("publicDefined") +public func publicDefined() {} + +// CHECK: define swiftcc void @publicDefined() + +public func test() { + guard #available(SwiftStdlib 9999, *) else { return } + privateForwardDecl() + internalForwardDecl() + publicForwardDecl() + privateDefined() + internalDefined() + publicDefined() +} + +// CHECK: declare extern_weak swiftcc void @privateForwardDecl() +// CHECK: declare extern_weak swiftcc void @internalForwardDecl() +// CHECK: declare extern_weak swiftcc void @publicForwardDecl()