Availability: only diagnose exposing SPI_AVAILABLE symbols in modules with library-level=API

For executable targets or private libraries, using SPI_AVAILABLE symbols should be allowed.

rdar://91088241
This commit is contained in:
Xi Ge
2022-04-04 14:55:47 -07:00
parent 89176021f3
commit 6b1f736f16
7 changed files with 58 additions and 15 deletions

View File

@@ -1546,13 +1546,21 @@ swift::getDisallowedOriginKind(const Decl *decl,
// Implementation-only imported, cannot be reexported.
return DisallowedOriginKind::ImplementationOnly;
} else if ((decl->isSPI() || decl->isAvailableAsSPI()) && !where.isSPI()) {
if (decl->isAvailableAsSPI() && !decl->isSPI()) {
// Allowing unavailable context to use @_spi_available decls.
// Decls with @_spi_available aren't hidden entirely from public interfaces,
// thus public interfaces may still refer them. Be forgiving here so public
// interfaces can compile.
if (where.getUnavailablePlatformKind().hasValue() &&
decl->isAvailableAsSPI() && !decl->isSPI()) {
if (where.getUnavailablePlatformKind().hasValue())
return DisallowedOriginKind::None;
// We should only diagnose SPI_AVAILABLE usage when the library level is API.
// Using SPI_AVAILABLE symbols in private frameworks or executable targets
// should be allowed.
if (auto *mod = where.getDeclContext()->getParentModule()) {
if (mod->getLibraryLevel() != LibraryLevel::API) {
return DisallowedOriginKind::None;
}
}
}
// SPI can only be exported in SPI.
return where.getDeclContext()->getParentModule() == M ?

View File

@@ -1,6 +1,6 @@
// REQUIRES: OS=macosx
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -verify -DNOT_UNDERLYING
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -module-name SPIContainer -import-underlying-module -verify
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -verify -DNOT_UNDERLYING -library-level api
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -module-name SPIContainer -import-underlying-module -verify -library-level api
#if NOT_UNDERLYING
import SPIContainer

View File

@@ -1,5 +1,5 @@
// REQUIRES: OS=macosx
// RUN: %target-swift-frontend -typecheck %s -import-objc-header %S/Inputs/frameworks/SPIContainer.framework/Headers/SPIContainer.h -verify
// RUN: %target-swift-frontend -typecheck %s -import-objc-header %S/Inputs/frameworks/SPIContainer.framework/Headers/SPIContainer.h -verify -library-level api
@_spi(a) public let a: SPIInterface1

View File

@@ -0,0 +1,35 @@
// REQUIRES: OS=macosx
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -verify -DNOT_UNDERLYING
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -verify -DNOT_UNDERLYING -library-level spi
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -module-name SPIContainer -import-underlying-module -verify
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -module-name SPIContainer -import-underlying-module -verify -library-level spi
#if NOT_UNDERLYING
import SPIContainer
#endif
@_spi(a) public let a: SPIInterface1
@_spi(a) public let b: SPIInterface2
public let c: SPIInterface1
public let d: SPIInterface2
@inlinable
public func inlinableUsingSPI() {
SharedInterface.foo()
}
@available(macOS, unavailable)
public let e: SPIInterface2
@available(iOS, unavailable)
public let f: SPIInterface2
@inlinable
@available(macOS, unavailable)
public func inlinableUnavailableUsingSPI() {
SharedInterface.foo()
}

View File

@@ -1,5 +1,5 @@
// REQUIRES: OS=macosx
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -verify
// RUN: %target-swift-frontend -typecheck %s -F %S/Inputs/frameworks -verify -library-level api
import SPIContainerImporter

View File

@@ -1,10 +1,10 @@
// REQUIRES: OS=macosx
// RUN: %empty-directory(%t/inputs)
// RUN: %target-swift-frontend -typecheck %s -F %S/../ClangImporter/Inputs/frameworks -DFoo -emit-module-interface-path %t/inputs/Foo.swiftinterface -module-name Foo -enable-library-evolution -disable-clang-spi
// RUN: %target-swift-frontend -typecheck %s -F %S/../ClangImporter/Inputs/frameworks -DFoo -emit-module-interface-path %t/inputs/Foo.swiftinterface -module-name Foo -enable-library-evolution -disable-clang-spi -library-level api
// RUN: %target-swift-frontend -typecheck %s -F %S/../ClangImporter/Inputs/frameworks -enable-library-evolution -I %t/inputs -disable-clang-spi
// RUN: %target-swift-frontend -typecheck %s -F %S/../ClangImporter/Inputs/frameworks -enable-library-evolution -I %t/inputs -disable-clang-spi -library-level api
// RUN: %target-swift-frontend -typecheck-module-from-interface %t/inputs/Foo.swiftinterface -F %S/../ClangImporter/Inputs/frameworks -disable-clang-spi
// RUN: %target-swift-frontend -typecheck-module-from-interface %t/inputs/Foo.swiftinterface -F %S/../ClangImporter/Inputs/frameworks -disable-clang-spi -library-level api
#if Foo

View File

@@ -1,6 +1,6 @@
// REQUIRES: VENDOR=apple
// REQUIRES: OS=macosx
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx11.9
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx11.9 -library-level api
@_spi_available(macOS 10.4, *)
public class MacOSSPIClass { public init() {} }