[Explicit Modules] Fix detection of a type-checking action in 'ExplicitModuleInterfaceBuilder'

When we run an interface verification tasks with Explicit module builds, we directly invoke a '-explicit-interface-module-build' instance with a '-typecheck-module-from-interface' action. So the builder needs to recognize this as a typechecking invocation. In implicit builds, this gets lowered into a separate compiler sub-instance with a '-typecheck' action, for some reason.

resolves rdar://115565571
This commit is contained in:
Artem Chikin
2023-09-18 13:58:43 -07:00
parent 9f61777eb0
commit 373d49134a
7 changed files with 48 additions and 16 deletions

View File

@@ -641,6 +641,10 @@ public:
/// Whether this compiler instance supports caching.
bool supportCaching() const;
/// Whether errors during interface verification can be downgrated
/// to warnings.
bool downgradeInterfaceVerificationErrors() const;
/// Gets the SourceFile which is the primary input for this CompilerInstance.
/// \returns the primary SourceFile, or nullptr if there is no primary input;
/// if there are _multiple_ primary inputs, fails with an assertion.

View File

@@ -507,6 +507,9 @@ public:
/// Whether we're configured to track system intermodule dependencies.
bool shouldTrackSystemDependencies() const;
/// Whether we are configured with -typecheck or -typecheck-module-from-interface actuin
bool isTypeCheckAction() const;
/// Whether to emit symbol graphs for the output module.
bool EmitSymbolGraph = false;

View File

@@ -1130,6 +1130,18 @@ bool CompilerInstance::supportCaching() const {
Invocation.getFrontendOptions().RequestedAction);
}
bool CompilerInstance::downgradeInterfaceVerificationErrors() const {
auto &FrontendOpts = Invocation.getFrontendOptions();
if (Context->blockListConfig.hasBlockListAction(FrontendOpts.ModuleName,
BlockListKeyKind::ModuleName,
BlockListAction::DowngradeInterfaceVerificationFailure)) {
Context->Diags.diagnose(SourceLoc(), diag::interface_block_listed_broken,
FrontendOpts.ModuleName);
return true;
}
return FrontendOpts.DowngradeInterfaceVerificationError;
}
ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const {
auto &frontendOpts = Invocation.getFrontendOptions();

View File

@@ -928,3 +928,8 @@ bool FrontendOptions::shouldTrackSystemDependencies() const {
return IntermoduleDependencyTracking ==
IntermoduleDepTrackingMode::IncludeSystem;
}
bool FrontendOptions::isTypeCheckAction() const {
return RequestedAction == FrontendOptions::ActionType::Typecheck ||
RequestedAction == FrontendOptions::ActionType::TypecheckModuleFromInterface;
}

View File

@@ -187,18 +187,6 @@ bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization(
return false;
}
static bool shouldDowngradeInterfaceVerificationError(const FrontendOptions &opts,
ASTContext &ctx) {
if (ctx.blockListConfig.hasBlockListAction(opts.ModuleName,
BlockListKeyKind::ModuleName,
BlockListAction::DowngradeInterfaceVerificationFailure)) {
ctx.Diags.diagnose(SourceLoc(), diag::interface_block_listed_broken,
opts.ModuleName);
return true;
}
return opts.DowngradeInterfaceVerificationError;
}
std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
@@ -214,8 +202,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
return std::error_code();
}
FrontendOptions &FEOpts = Invocation.getFrontendOptions();
bool isTypeChecking =
(FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck);
bool isTypeChecking = FEOpts.isTypeCheckAction();
const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput();
StringRef InPath = InputInfo.getFileName();
@@ -227,7 +214,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
if (isTypeChecking &&
shouldDowngradeInterfaceVerificationError(FEOpts, Instance.getASTContext())) {
Instance.downgradeInterfaceVerificationErrors()) {
ErrorDowngradeConsumerRAII R(Instance.getDiags());
Instance.performSema();
return std::error_code();

View File

@@ -1464,13 +1464,17 @@ static bool performCompile(CompilerInstance &Instance,
}() && "Only supports parsing .swift files");
bool hadError = performAction(Instance, ReturnValue, observer);
auto canIgnoreErrorForExit = [&Instance, &opts]() {
return opts.AllowModuleWithCompilerErrors ||
(opts.isTypeCheckAction() && Instance.downgradeInterfaceVerificationErrors());
};
// We might have freed the ASTContext already, but in that case we would
// have already performed these actions.
if (Instance.hasASTContext() &&
FrontendOptions::doesActionPerformEndOfPipelineActions(Action)) {
performEndOfPipelineActions(Instance);
if (!opts.AllowModuleWithCompilerErrors)
if (!canIgnoreErrorForExit())
hadError |= Instance.getASTContext().hadError();
}
return hadError;

View File

@@ -0,0 +1,17 @@
// RUN: %empty-directory(%t)
// RUN: echo "// swift-interface-format-version: 1.0" > %t/Main.swiftinterface
// RUN: echo "// swift-module-flags: -module-name Foo" >> %t/Main.swiftinterface
// RUN: echo "malfunctioned" >> %t/Main.swiftinterface
// Verify with '-downgrade-typecheck-interface-error'
// RUN: %target-swift-frontend -typecheck-module-from-interface %t/Main.swiftinterface -module-name Foo -downgrade-typecheck-interface-error -explicit-interface-module-build 2>&1 | %FileCheck %s
// Verify with a blocklist
// RUN: echo "---" > %t/blocklist.yml
// RUN: echo "DowngradeInterfaceVerificationFailure:" >> %t/blocklist.yml
// RUN: echo " ModuleName:" >> %t/blocklist.yml
// RUN: echo " - Foo" >> %t/blocklist.yml
// RUN: %target-swift-frontend -typecheck-module-from-interface %t/Main.swiftinterface -module-name Foo -blocklist-file %t/blocklist.yml -explicit-interface-module-build 2>&1 | %FileCheck %s
// CHECK: warning:
// CHECK-NOT: error: