From 373d49134ac18387d5f02d914b6d826c53c8b9e2 Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Mon, 18 Sep 2023 13:58:43 -0700 Subject: [PATCH] [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 --- include/swift/Frontend/Frontend.h | 4 ++++ include/swift/Frontend/FrontendOptions.h | 3 +++ lib/Frontend/Frontend.cpp | 12 ++++++++++++ lib/Frontend/FrontendOptions.cpp | 5 +++++ lib/Frontend/ModuleInterfaceBuilder.cpp | 17 ++--------------- lib/FrontendTool/FrontendTool.cpp | 6 +++++- ...ade-module-verification-error-explicit.swift | 17 +++++++++++++++++ 7 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 test/ModuleInterface/downgrade-module-verification-error-explicit.swift diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index ee15c12371e..aba24b77283 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -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. diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 3c0143dac05..055419d3960 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -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; diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 34892ecb6c8..d1a03141117 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -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(); diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index ad6fc9630ed..eb381672154 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -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; +} diff --git a/lib/Frontend/ModuleInterfaceBuilder.cpp b/lib/Frontend/ModuleInterfaceBuilder.cpp index 4a381b15875..6ab4f79bcaf 100644 --- a/lib/Frontend/ModuleInterfaceBuilder.cpp +++ b/lib/Frontend/ModuleInterfaceBuilder.cpp @@ -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 *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(); diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index e3f22948a28..ce25bb94ac1 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -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; diff --git a/test/ModuleInterface/downgrade-module-verification-error-explicit.swift b/test/ModuleInterface/downgrade-module-verification-error-explicit.swift new file mode 100644 index 00000000000..48148b2bb41 --- /dev/null +++ b/test/ModuleInterface/downgrade-module-verification-error-explicit.swift @@ -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: