Improve diagnostic for broken module interfaces

Currently, when a swiftinterface file fails to load, we emit the specific diagnostics for the failures, followed by a generic “failed to load module ‘Foo’” message. This PR improves that final diagnostic, particularly when the cause may be that the interface was emitted by a newer compiler using backwards-incompatible syntax.
This commit is contained in:
Brent Royal-Gordon
2020-03-13 16:56:18 -07:00
parent 000572d56c
commit a7a5e340aa
8 changed files with 80 additions and 15 deletions

View File

@@ -135,8 +135,8 @@ void ModuleInterfaceBuilder::configureSubInvocation(
}
bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
swift::version::Version &Vers, llvm::StringSaver &SubArgSaver,
SmallVectorImpl<const char *> &SubArgs) {
swift::version::Version &Vers, StringRef &CompilerVersion,
llvm::StringSaver &SubArgSaver, SmallVectorImpl<const char *> &SubArgs) {
auto FileOrError = swift::vfs::getFileOrSTDIN(fs, interfacePath);
if (!FileOrError) {
diags.diagnose(diagnosticLoc, diag::error_open_input_file,
@@ -145,8 +145,9 @@ bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
}
auto SB = FileOrError.get()->getBuffer();
auto VersRe = getSwiftInterfaceFormatVersionRegex();
auto CompRe = getSwiftInterfaceCompilerVersionRegex();
auto FlagRe = getSwiftInterfaceModuleFlagsRegex();
SmallVector<StringRef, 1> VersMatches, FlagMatches;
SmallVector<StringRef, 1> VersMatches, FlagMatches, CompMatches;
if (!VersRe.match(SB, &VersMatches)) {
diags.diagnose(diagnosticLoc,
diag::error_extracting_version_from_module_interface);
@@ -161,6 +162,16 @@ bool ModuleInterfaceBuilder::extractSwiftInterfaceVersionAndArgs(
assert(FlagMatches.size() == 2);
Vers = swift::version::Version(VersMatches[1], SourceLoc(), &diags);
llvm::cl::TokenizeGNUCommandLine(FlagMatches[1], SubArgSaver, SubArgs);
if (CompRe.match(SB, &CompMatches)) {
assert(CompMatches.size() == 2);
CompilerVersion = SubArgSaver.save(CompMatches[1]);
}
else {
// Don't diagnose; handwritten module interfaces don't include this field.
CompilerVersion = "(unspecified, file possibly handwritten)";
}
return false;
}
@@ -274,7 +285,9 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
llvm::StringSaver SubArgSaver(SubArgsAlloc);
SmallVector<const char *, 16> SubArgs;
swift::version::Version Vers;
if (extractSwiftInterfaceVersionAndArgs(Vers, SubArgSaver, SubArgs)) {
StringRef emittedByCompiler;
if (extractSwiftInterfaceVersionAndArgs(Vers, emittedByCompiler,
SubArgSaver, SubArgs)) {
SubError = true;
return;
}
@@ -325,8 +338,12 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
// emitted an error in the parent diagnostic engine, which is what
// determines whether the process exits with a proper failure status.
if (SubInstance.getASTContext().hadError()) {
diags.diagnose(diagnosticLoc, diag::serialization_load_failed,
moduleName);
auto builtByCompiler =
getSwiftInterfaceCompilerVersionForCurrentCompiler(
SubInstance.getASTContext());
diags.diagnose(diagnosticLoc, diag::module_interface_build_failed,
moduleName, emittedByCompiler == builtByCompiler,
emittedByCompiler, builtByCompiler);
}
};