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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user