Skip to content

Commit 48c2a32

Browse files
committed
[Dependency Scanning] Add support for diagnosing invalid architecture swift binary module candidates
Refactor 'maybeDiagnoseTargetMismatch' to separately collect mismatching target variant modules in 'identifyArchitectureVariants' and rename it to 'handlePossibleTargetMismatch'. Prior uses of 'maybeDiagnoseTargetMismatch' will continue diagnosing errors/warnings on only discovering incompatible swift binary module target variants. A new overload of 'handlePossibleTargetMismatch', in 'SwiftModuleScanner', instead collects it as a discovered incompatible candidate, for diagnosis downstream.
1 parent c73869e commit 48c2a32

File tree

5 files changed

+76
-23
lines changed

5 files changed

+76
-23
lines changed

include/swift/Serialization/ScanningLoaders.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase {
7070
ModuleVersionInfo *versionInfo,
7171
bool isTestableImport) override;
7272

73+
bool handlePossibleTargetMismatch(
74+
SourceLoc sourceLocation,
75+
StringRef moduleName,
76+
const SerializedModuleBaseName &BaseName,
77+
bool isCanImportLookup) override;
78+
7379
virtual void collectVisibleTopLevelModuleNames(
7480
SmallVectorImpl<Identifier> &names) const override {
7581
llvm_unreachable("Not used");

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,23 @@ class SerializedModuleLoaderBase : public ModuleLoader {
151151
/// to list the architectures that \e are present.
152152
///
153153
/// \returns true if an error diagnostic was emitted
154-
virtual bool maybeDiagnoseTargetMismatch(
154+
virtual bool handlePossibleTargetMismatch(
155155
SourceLoc sourceLocation,
156156
StringRef moduleName,
157-
const SerializedModuleBaseName &BaseName,
157+
const SerializedModuleBaseName &baseName,
158158
bool isCanImportLookup) {
159159
return false;
160160
}
161161

162+
/// Assuming the \c baseName is a target-specific Swift module path,
163+
/// for a missing target variant, collect all adjacent binary module
164+
/// files to build a list of discovered modules for incompatible
165+
/// architectures.
166+
static void identifyArchitectureVariants(
167+
ASTContext &Ctx,
168+
const SerializedModuleBaseName &baseName,
169+
std::vector<std::string> &incompatibleArchModules);
170+
162171
/// Determines if the provided path is a cached artifact for dependency
163172
/// tracking purposes.
164173
virtual bool isCached(StringRef DepPath) {
@@ -282,7 +291,7 @@ class ImplicitSerializedModuleLoader : public SerializedModuleLoaderBase {
282291
bool IsCanImportLookup, bool IsFramework,
283292
bool IsTestableDependencyLookup = false) override;
284293

285-
bool maybeDiagnoseTargetMismatch(
294+
bool handlePossibleTargetMismatch(
286295
SourceLoc sourceLocation,
287296
StringRef moduleName,
288297
const SerializedModuleBaseName &BaseName,

lib/Serialization/ScanningLoaders.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,21 @@ bool SwiftModuleScanner::canImportModule(
107107
path, loc, versionInfo, isTestableDependencyLookup);
108108
}
109109

110+
bool SwiftModuleScanner::handlePossibleTargetMismatch(
111+
SourceLoc sourceLocation, StringRef moduleName,
112+
const SerializedModuleBaseName &absoluteBaseName,
113+
bool isCanImportLookup) {
114+
std::vector<std::string> foundIncompatibleArchModules;
115+
identifyArchitectureVariants(Ctx, absoluteBaseName,
116+
foundIncompatibleArchModules);
117+
118+
for (const auto &modulePath : foundIncompatibleArchModules)
119+
incompatibleCandidates.push_back({modulePath,
120+
"invalid architecture"});
121+
122+
return false;
123+
}
124+
110125
static std::vector<std::string> getCompiledCandidates(ASTContext &ctx,
111126
StringRef moduleName,
112127
StringRef interfacePath) {

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -577,47 +577,58 @@ std::error_code ImplicitSerializedModuleLoader::findModuleFilesInDirectory(
577577
return std::error_code();
578578
}
579579

580-
bool ImplicitSerializedModuleLoader::maybeDiagnoseTargetMismatch(
581-
SourceLoc sourceLocation, StringRef moduleName,
582-
const SerializedModuleBaseName &absoluteBaseName,
583-
bool isCanImportLookup) {
580+
void SerializedModuleLoaderBase::identifyArchitectureVariants(
581+
ASTContext &Ctx, const SerializedModuleBaseName &absoluteBaseName,
582+
std::vector<std::string> &incompatibleArchModules) {
584583
llvm::vfs::FileSystem &fs = *Ctx.SourceMgr.getFileSystem();
585584

586-
// Get the last component of the base name, which is the target-specific one.
587-
auto target = llvm::sys::path::filename(absoluteBaseName.baseName);
588-
589585
// Strip off the last component to get the .swiftmodule folder.
590586
auto dir = absoluteBaseName.baseName;
591587
llvm::sys::path::remove_filename(dir);
592588

593589
std::error_code errorCode;
594-
std::string foundArchs;
595590
for (llvm::vfs::directory_iterator directoryIterator =
596591
fs.dir_begin(dir, errorCode), endIterator;
597592
directoryIterator != endIterator;
598593
directoryIterator.increment(errorCode)) {
599594
if (errorCode)
600-
return false;
595+
continue;
601596
StringRef filePath = directoryIterator->path();
602597
StringRef extension = llvm::sys::path::extension(filePath);
603598
if (file_types::lookupTypeForExtension(extension) ==
604599
file_types::TY_SwiftModuleFile) {
605-
if (!foundArchs.empty())
606-
foundArchs += ", ";
607-
foundArchs += llvm::sys::path::stem(filePath).str();
600+
incompatibleArchModules.push_back(filePath.str());
608601
}
609602
}
603+
}
610604

611-
if (foundArchs.empty()) {
612-
// Maybe this swiftmodule directory only contains swiftinterfaces, or
613-
// maybe something else is going on. Regardless, we shouldn't emit a
614-
// possibly incorrect diagnostic.
605+
bool ImplicitSerializedModuleLoader::handlePossibleTargetMismatch(
606+
SourceLoc sourceLocation, StringRef moduleName,
607+
const SerializedModuleBaseName &absoluteBaseName,
608+
bool isCanImportLookup) {
609+
std::string foundArchs;
610+
std::vector<std::string> foundIncompatibleArchModules;
611+
identifyArchitectureVariants(Ctx, absoluteBaseName,
612+
foundIncompatibleArchModules);
613+
614+
// Maybe this swiftmodule directory only contains swiftinterfaces, or
615+
// maybe something else is going on. Regardless, we shouldn't emit a
616+
// possibly incorrect diagnostic.
617+
if (foundIncompatibleArchModules.empty())
615618
return false;
619+
620+
// Generate combined list of discovered architectures
621+
// for the diagnostic
622+
for (const auto &modulePath : foundIncompatibleArchModules) {
623+
if (!foundArchs.empty())
624+
foundArchs += ", ";
625+
foundArchs += llvm::sys::path::stem(modulePath).str();
616626
}
617627

618628
Ctx.Diags
619-
.diagnose(sourceLocation, diag::sema_no_import_target, moduleName, target,
620-
foundArchs, dir)
629+
.diagnose(sourceLocation, diag::sema_no_import_target, moduleName,
630+
llvm::sys::path::filename(absoluteBaseName.baseName),
631+
foundArchs, absoluteBaseName.baseName)
621632
.limitBehaviorIf(isCanImportLookup, DiagnosticBehavior::Warning);
622633
return !isCanImportLookup;
623634
}
@@ -782,8 +793,8 @@ bool SerializedModuleLoaderBase::findModule(
782793
// We can only get here if all targetFileNamePairs failed with
783794
// 'std::errc::no_such_file_or_directory'.
784795
if (firstAbsoluteBaseName &&
785-
maybeDiagnoseTargetMismatch(moduleID.Loc, moduleName,
786-
*firstAbsoluteBaseName, isCanImportLookup))
796+
handlePossibleTargetMismatch(moduleID.Loc, moduleName,
797+
*firstAbsoluteBaseName, isCanImportLookup))
787798
return SearchResult::Error;
788799

789800
return SearchResult::NotFound;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/module-cache)
3+
// RUN: %empty-directory(%t/inputs/Foo.swiftmodule)
4+
// RUN: touch %t/inputs/Foo.swiftmodule/i387.swiftmodule
5+
// RUN: touch %t/inputs/Foo.swiftmodule/ppc65.swiftmodule
6+
7+
// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/module-cache %s -o %t/deps.json -I %t/inputs -diagnostic-style llvm -scanner-module-validation 2>&1 | %FileCheck %s
8+
9+
// CHECK: error: unable to resolve Swift module dependency to a compatible module: 'Foo'
10+
// CHECK-DAG: note: found incompatible module '{{.*}}Foo.swiftmodule{{/|\\}}ppc65.swiftmodule': invalid architecture
11+
// CHECK-DAG: note: found incompatible module '{{.*}}Foo.swiftmodule{{/|\\}}i387.swiftmodule': invalid architecture
12+
import Foo

0 commit comments

Comments
 (0)