[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. /// Whether this compiler instance supports caching.
bool supportCaching() const; 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. /// Gets the SourceFile which is the primary input for this CompilerInstance.
/// \returns the primary SourceFile, or nullptr if there is no primary input; /// \returns the primary SourceFile, or nullptr if there is no primary input;
/// if there are _multiple_ primary inputs, fails with an assertion. /// 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. /// Whether we're configured to track system intermodule dependencies.
bool shouldTrackSystemDependencies() const; 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. /// Whether to emit symbol graphs for the output module.
bool EmitSymbolGraph = false; bool EmitSymbolGraph = false;

View File

@@ -1130,6 +1130,18 @@ bool CompilerInstance::supportCaching() const {
Invocation.getFrontendOptions().RequestedAction); 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 { ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const {
auto &frontendOpts = Invocation.getFrontendOptions(); auto &frontendOpts = Invocation.getFrontendOptions();

View File

@@ -928,3 +928,8 @@ bool FrontendOptions::shouldTrackSystemDependencies() const {
return IntermoduleDependencyTracking == return IntermoduleDependencyTracking ==
IntermoduleDepTrackingMode::IncludeSystem; 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; 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( std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps, StringRef InterfacePath, StringRef OutputPath, bool ShouldSerializeDeps,
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer, std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
@@ -214,8 +202,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
return std::error_code(); return std::error_code();
} }
FrontendOptions &FEOpts = Invocation.getFrontendOptions(); FrontendOptions &FEOpts = Invocation.getFrontendOptions();
bool isTypeChecking = bool isTypeChecking = FEOpts.isTypeCheckAction();
(FEOpts.RequestedAction == FrontendOptions::ActionType::Typecheck);
const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput(); const auto &InputInfo = FEOpts.InputsAndOutputs.firstInput();
StringRef InPath = InputInfo.getFileName(); StringRef InPath = InputInfo.getFileName();
@@ -227,7 +214,7 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n"); LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
if (isTypeChecking && if (isTypeChecking &&
shouldDowngradeInterfaceVerificationError(FEOpts, Instance.getASTContext())) { Instance.downgradeInterfaceVerificationErrors()) {
ErrorDowngradeConsumerRAII R(Instance.getDiags()); ErrorDowngradeConsumerRAII R(Instance.getDiags());
Instance.performSema(); Instance.performSema();
return std::error_code(); return std::error_code();

View File

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