[Sema] Allow the use of SPI in API for SPI modules

When the whole module has an SPI distribution, SPI declarations can be
used in API.

rdar://75335462
This commit is contained in:
Alexis Laferrière
2021-03-24 15:55:39 -07:00
parent 091e5affe8
commit 758351110a
6 changed files with 48 additions and 5 deletions

View File

@@ -331,6 +331,13 @@ static void ParseModuleInterfaceArgs(ModuleInterfaceOptions &Opts,
Args.hasArg(OPT_experimental_spi_imports);
Opts.DebugPrintInvalidSyntax |=
Args.hasArg(OPT_debug_emit_invalid_swiftinterface_syntax);
if (const Arg *A = Args.getLastArg(OPT_library_level)) {
StringRef contents = A->getValue();
if (contents == "spi") {
Opts.PrintSPIs = true;
}
}
}
/// Save a copy of any flags marked as ModuleInterfaceOption, if running

View File

@@ -862,7 +862,7 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
}
if (opts.InputsAndOutputs.hasPrivateModuleInterfaceOutputPath()) {
// Copy the settings from the module interface
// Copy the settings from the module interface to add SPI printing.
ModuleInterfaceOptions privOpts = Invocation.getModuleInterfaceOptions();
privOpts.PrintSPIs = true;

View File

@@ -179,7 +179,7 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
(Ctx.LangOpts.DisableAvailabilityChecking
? AvailabilityContext::alwaysAvailable()
: TypeChecker::overApproximateAvailabilityAtLocation(D->getEndLoc(), DC));
bool spi = false;
bool spi = Ctx.LangOpts.LibraryLevel == LibraryLevel::SPI;
bool implicit = false;
bool deprecated = false;
Optional<PlatformKind> unavailablePlatformKind;
@@ -208,7 +208,7 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC, SourceLoc loc) {
? AvailabilityContext::alwaysAvailable()
: TypeChecker::overApproximateAvailabilityAtLocation(loc, DC));
bool spi = false;
bool spi = Ctx.LangOpts.LibraryLevel == LibraryLevel::SPI;
bool implicit = false;
bool deprecated = false;
Optional<PlatformKind> unavailablePlatformKind;

View File

@@ -0,0 +1,27 @@
/// Check that SPI declarations can be exported from an SPI module.
// RUN: %empty-directory(%t)
// RUN: %target-typecheck-verify-swift -I %t -verify-ignore-unknown -enable-library-evolution -swift-version 5 -library-level spi
@_spi(S) public func spiFunc() {}
@_spi(S) public class SPIClass {
public init() {}
}
@_spi(S) public class SPIStruct {
public init() {}
}
@_spi(S) public protocol SPIProtocol {}
public func useOfSPITypeOk(_ p0: SPIProtocol, p1: SPIClass) -> SPIClass { fatalError() }
@inlinable
func inlinable() -> SPIClass {
spiFunc()
_ = SPIClass()
}
@frozen public struct FrozenStruct {
public var spiInFrozen = SPIStruct()
var spiTypeInFrozen = SPIStruct()
private var spiTypeInFrozen1: SPIClass
}

View File

@@ -42,6 +42,14 @@
// RUN: %target-swift-frontend -typecheck-module-from-interface -I %t %t/Merged.swiftinterface
// RUN: %target-swift-frontend -typecheck-module-from-interface -I %t %t/Merged.private.swiftinterface -module-name Merged
/// Both the public and private textual interfaces should have
/// SPI information with `-library-level spi`.
// RUN: %target-swift-frontend -typecheck %s -emit-module-interface-path %t/SPIModule.swiftinterface -emit-private-module-interface-path %t/SPIModule.private.swiftinterface -enable-library-evolution -swift-version 5 -I %t -module-name SPIModule -library-level spi
// RUN: %FileCheck -check-prefix=CHECK-PRIVATE %s < %t/SPIModule.swiftinterface
// RUN: %FileCheck -check-prefix=CHECK-PRIVATE %s < %t/SPIModule.private.swiftinterface
// RUN: %target-swift-frontend -typecheck-module-from-interface -I %t %t/SPIModule.swiftinterface
// RUN: %target-swift-frontend -typecheck-module-from-interface -I %t %t/SPIModule.private.swiftinterface -module-name SPIModule
@_spi(HelperSPI) @_spi(OtherSPI) @_spi(OtherSPI) import SPIHelper
// CHECK-PUBLIC: import SPIHelper
// CHECK-PRIVATE: @_spi(OtherSPI) @_spi(HelperSPI) import SPIHelper

View File

@@ -12,9 +12,10 @@
// RUN: rm %t/SPIHelper.swiftmodule
// RUN: %target-typecheck-verify-swift -I %t -verify-ignore-unknown
/// Reading from .swiftinterface should still produce the same failures
/// Reading from the public .swiftinterface should raise errors on missing
/// declarations.
// RUN: rm %t/SPIHelper.private.swiftinterface
// RUN: not %target-swift-frontend -typecheck -I %t
// RUN: not %target-swift-frontend -typecheck -I %t %s
import SPIHelper