Skip to content

Commit 3970364

Browse files
authored
Merge pull request swiftlang#36147 from bnbarham/allow-invalid-target
[Serialization] Import incompatible targets when allowing errors
2 parents e2ed3ea + f410958 commit 3970364

File tree

6 files changed

+67
-31
lines changed

6 files changed

+67
-31
lines changed

lib/Serialization/ModuleFile.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,14 @@ ModuleFile::ModuleFile(std::shared_ptr<const ModuleFileSharedCore> core)
118118
allocateBuffer(Identifiers, core->Identifiers);
119119
}
120120

121-
Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc) {
121+
Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
122+
bool recoverFromIncompatibility) {
122123
PrettyStackTraceModuleFile stackEntry(*this);
123124

124125
assert(!hasError() && "error already detected; should not call this");
125126
assert(!FileContext && "already associated with an AST module");
126127
FileContext = file;
128+
Status status = Status::Valid;
127129

128130
ModuleDecl *M = file->getParentModule();
129131
if (M->getName().str() != Core->Name)
@@ -134,12 +136,14 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc) {
134136
llvm::Triple moduleTarget(llvm::Triple::normalize(Core->TargetTriple));
135137
if (!areCompatibleArchitectures(moduleTarget, ctx.LangOpts.Target) ||
136138
!areCompatibleOSs(moduleTarget, ctx.LangOpts.Target)) {
137-
return error(Status::TargetIncompatible);
138-
}
139-
if (ctx.LangOpts.EnableTargetOSChecking &&
140-
!M->isResilient() &&
141-
isTargetTooNew(moduleTarget, ctx.LangOpts.Target)) {
142-
return error(Status::TargetTooNew);
139+
status = Status::TargetIncompatible;
140+
if (!recoverFromIncompatibility)
141+
return error(status);
142+
} else if (ctx.LangOpts.EnableTargetOSChecking && !M->isResilient() &&
143+
isTargetTooNew(moduleTarget, ctx.LangOpts.Target)) {
144+
status = Status::TargetTooNew;
145+
if (!recoverFromIncompatibility)
146+
return error(status);
143147
}
144148

145149
for (const auto &searchPath : Core->SearchPaths)
@@ -240,7 +244,7 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc) {
240244
None);
241245
}
242246

243-
return Status::Valid;
247+
return status;
244248
}
245249

246250
bool ModuleFile::mayHaveDiagnosticsPointingAtBuffer() const {

lib/Serialization/ModuleFile.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,14 @@ class ModuleFile
486486
/// This does not include diagnostics about \e this file failing to load,
487487
/// but rather other things that might be imported as part of bringing the
488488
/// file into the AST.
489+
/// \param recoverFromIncompatibility Whether to associate the file
490+
/// regardless of the compatibility with the AST module. Still returns the
491+
/// underlying error for diagnostic purposes but does not set the error bit.
489492
///
490493
/// \returns any error that occurred during association, such as being
491494
/// compiled for a different OS.
492-
Status associateWithFileContext(FileUnit *file, SourceLoc diagLoc);
495+
Status associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
496+
bool recoverFromIncompatibility);
493497

494498
/// Returns `true` if there is a buffer that might contain source code where
495499
/// other parts of the compiler could have emitted diagnostics, to indicate

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -706,13 +706,15 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
706706
std::move(moduleDocInputBuffer),
707707
std::move(moduleSourceInfoInputBuffer),
708708
isFramework, loadedModuleFileCore);
709+
SerializedASTFile *fileUnit = nullptr;
710+
709711
if (loadInfo.status == serialization::Status::Valid) {
710712
loadedModuleFile =
711713
std::make_unique<ModuleFile>(std::move(loadedModuleFileCore));
712714
M.setResilienceStrategy(loadedModuleFile->getResilienceStrategy());
713715

714716
// We've loaded the file. Now try to bring it into the AST.
715-
auto fileUnit = new (Ctx) SerializedASTFile(M, *loadedModuleFile);
717+
fileUnit = new (Ctx) SerializedASTFile(M, *loadedModuleFile);
716718
if (loadedModuleFile->isTestable())
717719
M.setTestingEnabled();
718720
if (loadedModuleFile->arePrivateImportsEnabled())
@@ -723,8 +725,8 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
723725
M.setHasIncrementalInfo();
724726

725727
auto diagLocOrInvalid = diagLoc.getValueOr(SourceLoc());
726-
loadInfo.status =
727-
loadedModuleFile->associateWithFileContext(fileUnit, diagLocOrInvalid);
728+
loadInfo.status = loadedModuleFile->associateWithFileContext(
729+
fileUnit, diagLocOrInvalid, Ctx.LangOpts.AllowModuleWithCompilerErrors);
728730

729731
// FIXME: This seems wrong. Overlay for system Clang module doesn't
730732
// necessarily mean it's "system" module. User can make their own overlay
@@ -734,31 +736,36 @@ LoadedFile *SerializedModuleLoaderBase::loadAST(
734736
if (shadowed->isSystemModule())
735737
M.setIsSystemModule(true);
736738

737-
if (loadInfo.status == serialization::Status::Valid) {
739+
if (loadInfo.status == serialization::Status::Valid ||
740+
(Ctx.LangOpts.AllowModuleWithCompilerErrors &&
741+
(loadInfo.status == serialization::Status::TargetTooNew ||
742+
loadInfo.status == serialization::Status::TargetIncompatible))) {
738743
Ctx.bumpGeneration();
739744
LoadedModuleFiles.emplace_back(std::move(loadedModuleFile),
740745
Ctx.getCurrentGeneration());
741746
findOverlayFiles(diagLoc.getValueOr(SourceLoc()), &M, fileUnit);
742-
return fileUnit;
747+
} else {
748+
fileUnit = nullptr;
743749
}
744750
}
745751

746-
// From here on is the failure path.
747-
748-
if (diagLoc)
749-
serialization::diagnoseSerializedASTLoadFailure(
750-
Ctx, *diagLoc, loadInfo, moduleBufferID,
751-
moduleDocBufferID, loadedModuleFile.get(), M.getName());
752-
753-
// Even though the module failed to load, it's possible its contents include
754-
// a source buffer that need to survive because it's already been used for
755-
// diagnostics.
756-
// Note this is only necessary in case a bridging header failed to load
757-
// during the `associateWithFileContext()` call.
758-
if (loadedModuleFile && loadedModuleFile->mayHaveDiagnosticsPointingAtBuffer())
759-
OrphanedModuleFiles.push_back(std::move(loadedModuleFile));
752+
if (loadInfo.status != serialization::Status::Valid) {
753+
if (diagLoc)
754+
serialization::diagnoseSerializedASTLoadFailure(
755+
Ctx, *diagLoc, loadInfo, moduleBufferID, moduleDocBufferID,
756+
loadedModuleFile.get(), M.getName());
757+
758+
// Even though the module failed to load, it's possible its contents
759+
// include a source buffer that need to survive because it's already been
760+
// used for diagnostics.
761+
// Note this is only necessary in case a bridging header failed to load
762+
// during the `associateWithFileContext()` call.
763+
if (loadedModuleFile &&
764+
loadedModuleFile->mayHaveDiagnosticsPointingAtBuffer())
765+
OrphanedModuleFiles.push_back(std::move(loadedModuleFile));
766+
}
760767

761-
return nullptr;
768+
return fileUnit;
762769
}
763770

764771
void swift::serialization::diagnoseSerializedASTLoadFailure(
@@ -908,7 +915,8 @@ void swift::serialization::diagnoseSerializedASTLoadFailure(
908915
// FIXME: This doesn't handle a non-debugger REPL, which should also treat
909916
// this as a non-fatal error.
910917
auto diagKind = diag::serialization_target_incompatible;
911-
if (Ctx.LangOpts.DebuggerSupport)
918+
if (Ctx.LangOpts.DebuggerSupport ||
919+
Ctx.LangOpts.AllowModuleWithCompilerErrors)
912920
diagKind = diag::serialization_target_incompatible_repl;
913921
Ctx.Diags.diagnose(diagLoc, diagKind, ModuleName, loadInfo.targetTriple,
914922
moduleBufferID);
@@ -926,7 +934,8 @@ void swift::serialization::diagnoseSerializedASTLoadFailure(
926934
// FIXME: This doesn't handle a non-debugger REPL, which should also treat
927935
// this as a non-fatal error.
928936
auto diagKind = diag::serialization_target_too_new;
929-
if (Ctx.LangOpts.DebuggerSupport)
937+
if (Ctx.LangOpts.DebuggerSupport ||
938+
Ctx.LangOpts.AllowModuleWithCompilerErrors)
930939
diagKind = diag::serialization_target_too_new_repl;
931940
Ctx.Diags.diagnose(diagLoc, diagKind, compilationOSInfo.first,
932941
compilationOSInfo.second, ModuleName,

test/Serialization/target-incompatible.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
// RUN: %{python} -u %S/Inputs/binary_sub.py x86_64-unknown-darwin14 x86_64-unknown-solaris8 < %t/solaris-template.swiftmodule > %t/solaris.swiftmodule
99
// RUN: not %target-swift-frontend -I %t -typecheck -parse-stdlib %s -DSOLARIS 2>&1 | %FileCheck -check-prefix=CHECK-SOLARIS %s
1010

11+
// Check that we still get the diagnostic but the module is output anyway when
12+
// allowing errors
13+
// RUN: %target-swift-frontend -I %t -parse-stdlib -experimental-allow-module-with-compiler-errors -emit-module -module-name incompatmips -o %t %s -DMIPS 2>&1 | %FileCheck -check-prefix=CHECK-MIPS %s
14+
// RUN: ls %t/incompatmips.swiftmodule
15+
// RUN: %target-swift-frontend -I %t -parse-stdlib -experimental-allow-module-with-compiler-errors -emit-module -module-name incompatsol -o %t %s -DSOLARIS 2>&1 | %FileCheck -check-prefix=CHECK-SOLARIS %s
16+
// RUN: ls %t/incompatsol.swiftmodule
17+
1118
// These checks should still hold with -enable-library-evolution.
1219

1320
// RUN: %swift -target x86_64-unknown-darwin14 -o %t/mips-template.swiftmodule -parse-stdlib -emit-module -module-name mips %S/../Inputs/empty.swift -enable-library-evolution

test/Serialization/target-too-new-ios.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
// RUN: %target-swift-frontend -parse-stdlib -target x86_64-apple-ios50.50.1 -I %t -typecheck %s
66
// RUN: %target-swift-frontend -parse-stdlib -target x86_64-apple-ios50.51 -I %t -typecheck %s
77

8+
// Check that we still get the diagnostic but the module is output anyway when
9+
// allowing errors
10+
// RUN: %target-swift-frontend -I %t -target x86_64-apple-ios12 -parse-stdlib -experimental-allow-module-with-compiler-errors -emit-module -module-name toonewios -o %t %s 2>&1 | %FileCheck %s
11+
// RUN: ls %t/toonewios.swiftmodule
12+
813
// REQUIRES: OS=ios
914

1015
// CHECK: :[[@LINE+1]]:8: error: compiling for iOS 12.0, but module 'empty' has a minimum deployment target of iOS 50.50.1: {{.*}}empty.swiftmodule{{$}}

test/Serialization/target-too-new.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.50 -I %t -typecheck %s
77
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.50.1 -I %t -typecheck %s
88

9+
// Check that we still get the diagnostic but the module is output anyway when
10+
// allowing errors
11+
// RUN: %target-swift-frontend -I %t -target %target-cpu-apple-macosx10.9 -parse-stdlib -experimental-allow-module-with-compiler-errors -emit-module -module-name toonew -o %t %s 2>&1 | %FileCheck %s
12+
// RUN: ls %t/toonew.swiftmodule
13+
// RUN: %target-swift-frontend -I %t -target %target-cpu-apple-darwin13 -parse-stdlib -experimental-allow-module-with-compiler-errors -emit-module -module-name toonewother -o %t %s 2>&1 | %FileCheck %s
14+
// RUN: ls %t/toonewother.swiftmodule
15+
916
// Allow any version when built with resilience. (Really we should encode a
1017
// "minimum supported OS", but we don't have that information today.)
1118
// RUN: %target-swift-frontend -target %target-cpu-apple-macosx10.50 -emit-module -parse-stdlib %S/../Inputs/empty.swift -enable-library-evolution -o %t

0 commit comments

Comments
 (0)