mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Frontend: add a flag to downgrade all module interface verification errors to warnings
Ideally, module interface verification should fail the build when fatal error occurs when type checking emitted module interfaces. However, we found it's hard to stage this phase in because the ideal case requires all Swift adopters to have valid interfaces. This new front-end flag allows driver to downgrade all interface verification errors to warnings as an intermediate step.
This commit is contained in:
@@ -333,6 +333,11 @@ public:
|
||||
/// skip nodes entirely, depending on the errors involved.
|
||||
bool AllowModuleWithCompilerErrors = false;
|
||||
|
||||
/// Downgrade all errors emitted in the module interface verification phase
|
||||
/// to warnings.
|
||||
/// TODO: remove this after we fix all project-side warnings in the interface.
|
||||
bool DowngradeInterfaceVerificationError = false;
|
||||
|
||||
/// True if the "-static" option is set.
|
||||
bool Static = false;
|
||||
|
||||
|
||||
@@ -299,12 +299,14 @@ struct ModuleInterfaceLoaderOptions {
|
||||
bool disableInterfaceLock = false;
|
||||
bool disableImplicitSwiftModule = false;
|
||||
bool disableBuildingInterface = false;
|
||||
bool downgradeInterfaceVerificationError = false;
|
||||
std::string mainExecutablePath;
|
||||
ModuleInterfaceLoaderOptions(const FrontendOptions &Opts):
|
||||
remarkOnRebuildFromInterface(Opts.RemarkOnRebuildFromModuleInterface),
|
||||
disableInterfaceLock(Opts.DisableInterfaceFileLock),
|
||||
disableImplicitSwiftModule(Opts.DisableImplicitModules),
|
||||
disableBuildingInterface(Opts.DisableBuildingInterface),
|
||||
downgradeInterfaceVerificationError(Opts.DowngradeInterfaceVerificationError),
|
||||
mainExecutablePath(Opts.MainExecutablePath)
|
||||
{
|
||||
switch (Opts.RequestedAction) {
|
||||
|
||||
@@ -562,6 +562,9 @@ def warn_long_expression_type_checking_EQ : Joined<["-"], "warn-long-expression-
|
||||
def Rmodule_interface_rebuild : Flag<["-"], "Rmodule-interface-rebuild">,
|
||||
HelpText<"Emits a remark if an imported module needs to be re-compiled from its module interface">;
|
||||
|
||||
def downgrade_typecheck_interface_error : Flag<["-"], "downgrade-typecheck-interface-error">,
|
||||
HelpText<"Downgrade error to warning when typechecking emitted module interfaces">;
|
||||
|
||||
def enable_volatile_modules : Flag<["-"], "enable-volatile-modules">,
|
||||
HelpText<"Load Swift modules in memory">;
|
||||
|
||||
|
||||
@@ -141,6 +141,8 @@ bool ArgsToFrontendOptionsConverter::convert(
|
||||
Opts.RemarkOnRebuildFromModuleInterface |=
|
||||
Args.hasArg(OPT_Rmodule_interface_rebuild);
|
||||
|
||||
Opts.DowngradeInterfaceVerificationError |=
|
||||
Args.hasArg(OPT_downgrade_typecheck_interface_error);
|
||||
computePrintStatsOptions();
|
||||
computeDebugTimeOptions();
|
||||
computeTBDOptions();
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include "llvm/Support/LockFileManager.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
using namespace swift;
|
||||
using FileDependency = SerializationOptions::FileDependency;
|
||||
@@ -152,6 +153,32 @@ bool ModuleInterfaceBuilder::collectDepsForSerialization(
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ErrorDowngradeConsumerRAII: DiagnosticConsumer {
|
||||
DiagnosticEngine &Diag;
|
||||
std::vector<DiagnosticConsumer *> allConsumers;
|
||||
bool SeenError;
|
||||
ErrorDowngradeConsumerRAII(DiagnosticEngine &Diag): Diag(Diag),
|
||||
allConsumers(Diag.takeConsumers()), SeenError(false) {
|
||||
Diag.addConsumer(*this);
|
||||
}
|
||||
~ErrorDowngradeConsumerRAII() {
|
||||
for (auto *consumer: allConsumers) {
|
||||
Diag.addConsumer(*consumer);
|
||||
}
|
||||
Diag.removeConsumer(*this);
|
||||
}
|
||||
void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override {
|
||||
DiagnosticInfo localInfo(Info);
|
||||
if (localInfo.Kind == DiagnosticKind::Error) {
|
||||
localInfo.Kind = DiagnosticKind::Warning;
|
||||
SeenError = true;
|
||||
for (auto *consumer: allConsumers) {
|
||||
consumer->handleDiagnostic(SM, localInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
|
||||
StringRef OutPath, bool ShouldSerializeDeps,
|
||||
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
|
||||
@@ -204,6 +231,12 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
|
||||
LLVM_DEBUG(llvm::dbgs() << "Setting up instance to compile "
|
||||
<< InPath << " to " << OutPath << "\n");
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
|
||||
if (isTypeChecking && FEOpts.DowngradeInterfaceVerificationError) {
|
||||
ErrorDowngradeConsumerRAII R(SubInstance.getDiags());
|
||||
SubInstance.performSema();
|
||||
return std::error_code();
|
||||
}
|
||||
SWIFT_DEFER {
|
||||
// Make sure to emit a generic top-level error if a module fails to
|
||||
// load. This is not only good for users; it also makes sure that we've
|
||||
@@ -225,12 +258,14 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
|
||||
}
|
||||
};
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Performing sema\n");
|
||||
SubInstance.performSema();
|
||||
if (SubInstance.getASTContext().hadError()) {
|
||||
LLVM_DEBUG(llvm::dbgs() << "encountered errors\n");
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
}
|
||||
// If we are just type-checking the interface, we are done.
|
||||
if (isTypeChecking)
|
||||
return std::error_code();
|
||||
|
||||
SILOptions &SILOpts = subInvocation.getSILOptions();
|
||||
auto Mod = SubInstance.getMainModule();
|
||||
@@ -268,9 +303,6 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
|
||||
SerializationOpts.IsOSSA = SILOpts.EnableOSSAModules;
|
||||
|
||||
SILMod->setSerializeSILAction([&]() {
|
||||
if (isTypeChecking)
|
||||
return;
|
||||
|
||||
// We don't want to serialize module docs in the cache -- they
|
||||
// will be serialized beside the interface file.
|
||||
serializeToBuffers(Mod, SerializationOpts, ModuleBuffer,
|
||||
|
||||
@@ -1497,7 +1497,9 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
|
||||
if (LoaderOpts.remarkOnRebuildFromInterface) {
|
||||
GenericArgs.push_back("-Rmodule-interface-rebuild");
|
||||
}
|
||||
|
||||
// This flag only matters when we are verifying an textual interface.
|
||||
frontendOpts.DowngradeInterfaceVerificationError =
|
||||
LoaderOpts.downgradeInterfaceVerificationError;
|
||||
// Note that we don't assume cachePath is the same as the Clang
|
||||
// module cache path at this point.
|
||||
if (buildModuleCacheDirIfAbsent && !moduleCachePath.empty())
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// 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
|
||||
// RUN: %target-swift-frontend -typecheck-module-from-interface %t/Main.swiftinterface -module-name Foo -downgrade-typecheck-interface-error &> %t/results.txt
|
||||
// RUN: %FileCheck --input-file %t/results.txt %s
|
||||
|
||||
// CHECK: warning:
|
||||
// CHECK-NOT: error:
|
||||
Reference in New Issue
Block a user