mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Frontend] Allow -emit-interface with -typecheck (#19676)
Textual module interfaces don't actually depend on SILGen, so we shouldn't need to run SILGen (or serialize an entire binary module) if we're just trying to emit a textual interface. On the other hand, if we /are/ going to run SILGen and then SIL diagnostics, we shouldn't delay those diagnostics by spending time emitting a textual interface, or for that matter a TBD file. Using this, update all the ModuleInterface tests that use `-emit-module -o /dev/null` to use `-typecheck` instead, except for those using `-merge-modules`.
This commit is contained in:
@@ -337,6 +337,11 @@ public:
|
||||
/// so return the TBDPath when in that mode and fail an assert
|
||||
/// if not in that mode.
|
||||
std::string getTBDPathForWholeModule() const;
|
||||
|
||||
/// ModuleInterfaceOutputPath only makes sense in whole module compilation
|
||||
/// mode, so return the ModuleInterfaceOutputPath when in that mode and fail
|
||||
/// an assert if not in that mode.
|
||||
std::string getModuleInterfaceOutputPathForWholeModule() const;
|
||||
};
|
||||
|
||||
/// A class which manages the state and execution of the compiler.
|
||||
|
||||
@@ -109,6 +109,15 @@ std::string CompilerInvocation::getTBDPathForWholeModule() const {
|
||||
.SupplementaryOutputs.TBDPath;
|
||||
}
|
||||
|
||||
std::string
|
||||
CompilerInvocation::getModuleInterfaceOutputPathForWholeModule() const {
|
||||
assert(getFrontendOptions().InputsAndOutputs.isWholeModule() &&
|
||||
"ModuleInterfaceOutputPath only makes sense when the whole module can "
|
||||
"be seen");
|
||||
return getPrimarySpecificPathsForAtMostOnePrimary()
|
||||
.SupplementaryOutputs.ModuleInterfaceOutputPath;
|
||||
}
|
||||
|
||||
void CompilerInstance::createSILModule() {
|
||||
assert(MainModule && "main module not created yet");
|
||||
// Assume WMO if a -primary-file option was not provided.
|
||||
|
||||
@@ -374,7 +374,6 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) {
|
||||
case ActionType::NoneAction:
|
||||
case ActionType::Parse:
|
||||
case ActionType::ResolveImports:
|
||||
case ActionType::Typecheck:
|
||||
case ActionType::DumpParse:
|
||||
case ActionType::DumpInterfaceHash:
|
||||
case ActionType::DumpAST:
|
||||
@@ -390,6 +389,7 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) {
|
||||
case ActionType::REPL:
|
||||
case ActionType::EmitImportedModules:
|
||||
return false;
|
||||
case ActionType::Typecheck:
|
||||
case ActionType::MergeModules:
|
||||
case ActionType::EmitModuleOnly:
|
||||
case ActionType::EmitSIL:
|
||||
|
||||
@@ -867,6 +867,40 @@ emitIndexData(CompilerInvocation &Invocation, CompilerInstance &Instance) {
|
||||
return hadEmitIndexDataError;
|
||||
}
|
||||
|
||||
/// Emits all "one-per-module" supplementary outputs that don't depend on
|
||||
/// anything past type-checking.
|
||||
///
|
||||
/// These are extracted out so that they can be invoked early when using
|
||||
/// `-typecheck`, but skipped for any mode that runs SIL diagnostics if there's
|
||||
/// an error found there (to get those diagnostics back to the user faster).
|
||||
static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
|
||||
CompilerInstance &Instance, CompilerInvocation &Invocation,
|
||||
bool moduleIsPublic) {
|
||||
const FrontendOptions &opts = Invocation.getFrontendOptions();
|
||||
|
||||
// Record whether we failed to emit any of these outputs, but keep going; one
|
||||
// failure does not mean skipping the rest.
|
||||
bool hadAnyError = false;
|
||||
|
||||
if (opts.InputsAndOutputs.hasObjCHeaderOutputPath()) {
|
||||
hadAnyError |= printAsObjCIfNeeded(
|
||||
Invocation.getObjCHeaderOutputPathForAtMostOnePrimary(),
|
||||
Instance.getMainModule(), opts.ImplicitObjCHeaderPath, moduleIsPublic);
|
||||
}
|
||||
|
||||
if (opts.InputsAndOutputs.hasModuleInterfaceOutputPath()) {
|
||||
hadAnyError |= printModuleInterfaceIfNeeded(
|
||||
Invocation.getModuleInterfaceOutputPathForWholeModule(),
|
||||
Instance.getMainModule());
|
||||
}
|
||||
|
||||
{
|
||||
hadAnyError |= writeTBDIfNeeded(Invocation, Instance);
|
||||
}
|
||||
|
||||
return hadAnyError;
|
||||
}
|
||||
|
||||
static bool performCompileStepsPostSILGen(
|
||||
CompilerInstance &Instance, CompilerInvocation &Invocation,
|
||||
std::unique_ptr<SILModule> SM, bool astGuaranteedToCorrespondToSIL,
|
||||
@@ -965,9 +999,6 @@ static bool performCompile(CompilerInstance &Instance,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (writeTBDIfNeeded(Invocation, Instance))
|
||||
return true;
|
||||
|
||||
// FIXME: This is still a lousy approximation of whether the module file will
|
||||
// be externally consumed.
|
||||
bool moduleIsPublic =
|
||||
@@ -977,17 +1008,14 @@ static bool performCompile(CompilerInstance &Instance,
|
||||
|
||||
// We've just been told to perform a typecheck, so we can return now.
|
||||
if (Action == FrontendOptions::ActionType::Typecheck) {
|
||||
const bool hadPrintAsObjCError =
|
||||
Invocation.getFrontendOptions()
|
||||
.InputsAndOutputs.hasObjCHeaderOutputPath() &&
|
||||
printAsObjCIfNeeded(
|
||||
Invocation.getObjCHeaderOutputPathForAtMostOnePrimary(),
|
||||
Instance.getMainModule(), opts.ImplicitObjCHeaderPath,
|
||||
moduleIsPublic);
|
||||
|
||||
const bool hadEmitIndexDataError = emitIndexData(Invocation, Instance);
|
||||
|
||||
return hadPrintAsObjCError || hadEmitIndexDataError || Context.hadError();
|
||||
if (emitIndexData(Invocation, Instance))
|
||||
return true;
|
||||
if (emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance,
|
||||
Invocation,
|
||||
moduleIsPublic)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(FrontendOptions::doesActionGenerateSIL(Action) &&
|
||||
@@ -1272,6 +1300,9 @@ static bool performCompileStepsPostSILGen(
|
||||
SM->verify();
|
||||
}
|
||||
|
||||
emitAnyWholeModulePostTypeCheckSupplementaryOutputs(Instance, Invocation,
|
||||
moduleIsPublic);
|
||||
|
||||
// This is the action to be used to serialize SILModule.
|
||||
// It may be invoked multiple times, but it will perform
|
||||
// serialization only once. The serialization may either happen
|
||||
@@ -1309,14 +1340,6 @@ static bool performCompileStepsPostSILGen(
|
||||
|
||||
setPrivateDiscriminatorIfNeeded(IRGenOpts, MSF);
|
||||
|
||||
(void)printAsObjCIfNeeded(PSPs.SupplementaryOutputs.ObjCHeaderOutputPath,
|
||||
Instance.getMainModule(),
|
||||
opts.ImplicitObjCHeaderPath, moduleIsPublic);
|
||||
|
||||
(void)printModuleInterfaceIfNeeded(
|
||||
PSPs.SupplementaryOutputs.ModuleInterfaceOutputPath,
|
||||
Instance.getMainModule());
|
||||
|
||||
if (Action == FrontendOptions::ActionType::EmitSIB)
|
||||
return serializeSIB(SM.get(), PSPs, Instance.getASTContext(), MSF);
|
||||
|
||||
|
||||
@@ -26,7 +26,5 @@
|
||||
|
||||
// RUN: not %target-swift-frontend -parse -emit-interface-path %t %s 2>&1 | %FileCheck -check-prefix=PARSE_NO_INTERFACE %s
|
||||
// PARSE_NO_INTERFACE: error: this mode does not support emitting textual interface files{{$}}
|
||||
// RUN: not %target-swift-frontend -typecheck -emit-interface-path %t %s 2>&1 | %FileCheck -check-prefix=TYPECHECK_NO_INTERFACE %s
|
||||
// TYPECHECK_NO_INTERFACE: error: this mode does not support emitting textual interface files{{$}}
|
||||
// RUN: not %target-swift-frontend -emit-silgen -emit-interface-path %t %s 2>&1 | %FileCheck -check-prefix=SILGEN_NO_INTERFACE %s
|
||||
// SILGEN_NO_INTERFACE: error: this mode does not support emitting textual interface files{{$}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path %t.swiftinterface %s
|
||||
// RUN: %FileCheck %s < %t.swiftinterface
|
||||
// RUN: %FileCheck -check-prefix NEGATIVE %s < %t.swiftinterface
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -enable-resilience -emit-module -o /dev/null %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path %t.swiftinterface -enable-resilience %s
|
||||
// RUN: %FileCheck %s < %t.swiftinterface
|
||||
|
||||
// CHECK: @_transparent public func glass() -> Int { return 0 }{{$}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
|
||||
// RUN: %target-swift-frontend-typecheck -emit-interface-path %t.swiftinterface %s
|
||||
// RUN: %FileCheck %s < %t.swiftinterface
|
||||
// RUN: %FileCheck -check-prefix NEGATIVE %s < %t.swiftinterface
|
||||
|
||||
|
||||
12
test/ModuleInterface/dataflow-errors.swift
Normal file
12
test/ModuleInterface/dataflow-errors.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
// RUN: rm -f %t
|
||||
// RUN: not %target-swift-frontend -emit-interface-path %t -emit-module -o /dev/null %s
|
||||
// RUN: test ! -f %t
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t -typecheck %s
|
||||
// RUN: test -f %t
|
||||
|
||||
public struct BadInit {
|
||||
public var x: Int
|
||||
public init() {
|
||||
return // without initializing 'x'
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/Test.swiftmodule %t/Test~partial.swiftmodule
|
||||
// RUN: %target-swift-ide-test -print-module -module-to-print=Test -source-filename=x -I %t | %FileCheck %s
|
||||
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -enable-resilience -emit-module -o /dev/null %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path %t.swiftinterface -enable-resilience %s
|
||||
// RUN: %FileCheck %s < %t.swiftinterface
|
||||
|
||||
// CHECK: func hasClosureDefaultArg(_ x: () -> Void = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s -I %S/Inputs/imports-submodule-order/ | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s -I %S/Inputs/imports-submodule-order/ -D XY | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path - %s -I %S/Inputs/imports-submodule-order/ | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path - %s -I %S/Inputs/imports-submodule-order/ -D XY | %FileCheck %s
|
||||
|
||||
#if XY
|
||||
@_exported import X.Submodule
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -o %t/empty.swiftmodule %S/../Inputs/empty.swift
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s %S/Inputs/imports-other.swift -I %S/Inputs/imports-clang-modules/ -I %t -verify | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path - %s %S/Inputs/imports-other.swift -I %S/Inputs/imports-clang-modules/ -I %t -verify | %FileCheck %s
|
||||
|
||||
|
||||
@_exported import empty
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -emit-module -o /dev/null %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path %t.swiftinterface %s
|
||||
// RUN: %FileCheck %s < %t.swiftinterface --check-prefix CHECK --check-prefix COMMON
|
||||
|
||||
// RUN: %target-swift-frontend -emit-interface-path %t-resilient.swiftinterface -enable-resilience -emit-module -o /dev/null %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path %t-resilient.swiftinterface -enable-resilience %s
|
||||
// RUN: %FileCheck %s --check-prefix RESILIENT --check-prefix COMMON < %t-resilient.swiftinterface
|
||||
|
||||
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule %t.swiftinterface -disable-objc-attr-requires-foundation-module
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null %s %S/Inputs/other.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-MULTI-FILE %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path - %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path - %s %S/Inputs/other.swift | %FileCheck -check-prefix CHECK -check-prefix CHECK-MULTI-FILE %s
|
||||
|
||||
// CHECK: public func verySimpleFunction(){{$}}
|
||||
public func verySimpleFunction() {}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// RUN: %target-swift-frontend -typecheck -emit-interface-path - -parse-stdlib %s | %FileCheck %s
|
||||
// RUN: %target-swift-frontend -emit-interface-path - -emit-module -o /dev/null -parse-stdlib %s | %FileCheck %s
|
||||
|
||||
// CHECK-NOT: import Builtin
|
||||
|
||||
Reference in New Issue
Block a user