Skip to content

Commit 4b26a3d

Browse files
committed
[Dependency Scanning] Emit a detailed error diagnostic on Clang module variant discovery
In expectation, this should never happen. Such a situation means that within the same scanning action, Clang Dependency Scanner has produced two different variants of the same module. This is not supposed to happen, but we are currently hunting down the rare cases where it does, seemingly due to differences in Clang Scanner direct by-name queries and transitive header lookup queries.
1 parent 3a788a4 commit 4b26a3d

File tree

6 files changed

+74
-19
lines changed

6 files changed

+74
-19
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,5 +624,15 @@ ERROR(ast_format_requires_dump_ast,none,
624624
ERROR(unknown_dump_ast_format,none,
625625
"unknown format '%0' requested with '-dump-ast-format'", (StringRef))
626626

627+
ERROR(dependency_scan_unexpected_variant, none,
628+
"unexpected variant during dependency scanning on module '%0'", (StringRef))
629+
NOTE(dependency_scan_unexpected_variant_context_hash_note, none,
630+
"first module context hash: '%0', second module context hash: '%1'", (StringRef, StringRef))
631+
NOTE(dependency_scan_unexpected_variant_module_map_note, none,
632+
"first module module map: '%0', second module module map: '%1'", (StringRef, StringRef))
633+
NOTE(dependency_scan_unexpected_variant_extra_arg_note, none,
634+
"%select{first|second}0 module command-line has extra argument: '%1'", (bool, StringRef))
635+
636+
627637
#define UNDEFINE_DIAGNOSTIC_MACROS
628638
#include "DefineDiagnosticMacros.h"

include/swift/AST/ModuleDependencies.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class Identifier;
5555
class CompilerInstance;
5656
class IRGenOptions;
5757
class CompilerInvocation;
58+
class DiagnosticEngine;
5859

5960
/// Which kind of module dependencies we are looking for.
6061
enum class ModuleDependencyKind : int8_t {
@@ -1254,7 +1255,8 @@ class ModuleDependenciesCache {
12541255
ModuleDependencyInfo dependencies);
12551256

12561257
/// Record dependencies for the given module collection.
1257-
void recordDependencies(ModuleDependencyVector moduleDependencies);
1258+
void recordDependencies(ModuleDependencyVector moduleDependencies,
1259+
DiagnosticEngine &diags);
12581260

12591261
/// Update stored dependencies for the given module.
12601262
void updateDependency(ModuleDependencyID moduleID,

lib/AST/ASTContext.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,13 +2201,6 @@ Identifier ASTContext::getRealModuleName(Identifier key, ModuleAliasLookupOption
22012201
return value.first;
22022202
}
22032203

2204-
namespace {
2205-
static StringRef pathStringFromSearchPath(
2206-
const SearchPathOptions::SearchPath &next) {
2207-
return next.Path;
2208-
}
2209-
}
2210-
22112204
std::vector<std::string> ASTContext::getDarwinImplicitFrameworkSearchPaths()
22122205
const {
22132206
assert(LangOpts.Target.isOSDarwin());

lib/AST/ModuleDependencies.cpp

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -888,11 +888,61 @@ void ModuleDependenciesCache::recordDependency(
888888
}
889889

890890
void ModuleDependenciesCache::recordDependencies(
891-
ModuleDependencyVector dependencies) {
891+
ModuleDependencyVector dependencies, DiagnosticEngine &diags) {
892892
for (const auto &dep : dependencies) {
893-
if (!hasDependency(dep.first))
893+
if (hasDependency(dep.first)) {
894+
if (dep.first.Kind == ModuleDependencyKind::Clang) {
895+
auto priorClangModuleDetails =
896+
findKnownDependency(dep.first).getAsClangModule();
897+
auto newClangModuleDetails = dep.second.getAsClangModule();
898+
auto priorContextHash = priorClangModuleDetails->contextHash;
899+
auto newContextHash = newClangModuleDetails->contextHash;
900+
if (priorContextHash != newContextHash) {
901+
// This situation means that within the same scanning action, Clang
902+
// Dependency Scanner has produced two different variants of the same
903+
// module. This is not supposed to happen, but we are currently
904+
// hunting down the rare cases where it does, seemingly due to
905+
// differences in Clang Scanner direct by-name queries and transitive
906+
// header lookup queries.
907+
//
908+
// Emit a failure diagnostic here that is hopefully more actionable
909+
// for the time being.
910+
diags.diagnose(SourceLoc(), diag::dependency_scan_unexpected_variant,
911+
dep.first.ModuleName);
912+
diags.diagnose(
913+
SourceLoc(),
914+
diag::dependency_scan_unexpected_variant_context_hash_note,
915+
priorContextHash, newContextHash);
916+
diags.diagnose(
917+
SourceLoc(),
918+
diag::dependency_scan_unexpected_variant_module_map_note,
919+
priorClangModuleDetails->moduleMapFile,
920+
newClangModuleDetails->moduleMapFile);
921+
922+
auto diagnoseExtraCommandLineFlags =
923+
[&diags](const ClangModuleDependencyStorage *checkModuleDetails,
924+
const ClangModuleDependencyStorage *baseModuleDetails,
925+
bool isNewlyDiscovered) -> void {
926+
std::unordered_set<std::string> baseCommandLineSet(
927+
baseModuleDetails->buildCommandLine.begin(),
928+
baseModuleDetails->buildCommandLine.end());
929+
for (const auto &checkArg : checkModuleDetails->buildCommandLine)
930+
if (baseCommandLineSet.find(checkArg) == baseCommandLineSet.end())
931+
diags.diagnose(
932+
SourceLoc(),
933+
diag::dependency_scan_unexpected_variant_extra_arg_note,
934+
isNewlyDiscovered, checkArg);
935+
};
936+
diagnoseExtraCommandLineFlags(priorClangModuleDetails,
937+
newClangModuleDetails, true);
938+
diagnoseExtraCommandLineFlags(newClangModuleDetails,
939+
priorClangModuleDetails, false);
940+
}
941+
}
942+
} else
894943
recordDependency(dep.first.ModuleName, dep.second);
895-
if (dep.second.getKind() == ModuleDependencyKind::Clang) {
944+
945+
if (dep.first.Kind == ModuleDependencyKind::Clang) {
896946
auto clangModuleDetails = dep.second.getAsClangModule();
897947
addSeenClangModule(clang::tooling::dependencies::ModuleID{
898948
dep.first.ModuleName, clangModuleDetails->contextHash});

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ bool ClangImporter::getHeaderDependencies(
516516
[&cache](StringRef path) {
517517
return cache.getScanService().remapPath(path);
518518
});
519-
cache.recordDependencies(bridgedDeps);
519+
cache.recordDependencies(bridgedDeps, Impl.SwiftContext.Diags);
520520

521521
llvm::copy(dependencies->FileDeps, std::back_inserter(headerFileInputs));
522522
auto bridgedDependencyIDs =

lib/DependencyScan/ModuleDependencyScanner.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ ModuleDependencyScanner::getNamedClangModuleDependencyInfo(
532532
for (const auto &dep : moduleDependencies)
533533
discoveredClangModules.insert(dep.first);
534534

535-
cache.recordDependencies(moduleDependencies);
535+
cache.recordDependencies(moduleDependencies, Diagnostics);
536536
return cache.findDependency(moduleID);
537537
}
538538

@@ -566,7 +566,7 @@ ModuleDependencyScanner::getNamedSwiftModuleDependencyInfo(
566566
if (moduleDependencies.empty())
567567
return std::nullopt;
568568

569-
cache.recordDependencies(moduleDependencies);
569+
cache.recordDependencies(moduleDependencies, Diagnostics);
570570
return cache.findDependency(moduleName);
571571
}
572572

@@ -927,7 +927,7 @@ ModuleDependencyScanner::resolveAllClangModuleDependencies(
927927
std::lock_guard<std::mutex> guard(cacheAccessLock);
928928
moduleLookupResult.insert_or_assign(moduleName, moduleDependencies);
929929
if (!moduleDependencies.empty())
930-
cache.recordDependencies(moduleDependencies);
930+
cache.recordDependencies(moduleDependencies, Diagnostics);
931931
}
932932
};
933933

@@ -1138,7 +1138,7 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
11381138
ScanningThreadPool.wait();
11391139

11401140
auto recordResolvedModuleImport =
1141-
[&cache, &moduleLookupResult, &importedSwiftDependencies,
1141+
[this, &cache, &moduleLookupResult, &importedSwiftDependencies,
11421142
moduleID](const ScannerImportStatementInfo &moduleImport) {
11431143
if (moduleID.ModuleName == moduleImport.importIdentifier)
11441144
return;
@@ -1152,7 +1152,7 @@ void ModuleDependencyScanner::resolveSwiftImportsForModule(
11521152
} else {
11531153
// Cache discovered module dependencies.
11541154
if (!lookupResult.value().empty()) {
1155-
cache.recordDependencies(lookupResult.value());
1155+
cache.recordDependencies(lookupResult.value(), Diagnostics);
11561156
importedSwiftDependencies.insert({moduleImport.importIdentifier,
11571157
lookupResult.value()[0].first.Kind});
11581158
}
@@ -1306,7 +1306,7 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
13061306
ScanningThreadPool.wait();
13071307

13081308
// Aggregate both previously-cached and freshly-scanned module results
1309-
auto recordResult = [&cache, &swiftOverlayLookupResult,
1309+
auto recordResult = [this, &cache, &swiftOverlayLookupResult,
13101310
&swiftOverlayDependencies,
13111311
moduleID](const std::string &moduleName) {
13121312
auto lookupResult = swiftOverlayLookupResult[moduleName];
@@ -1318,7 +1318,7 @@ void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule(
13181318
{moduleName, cachedInfo.value()->getKind()});
13191319
} else {
13201320
// Cache discovered module dependencies.
1321-
cache.recordDependencies(lookupResult.value());
1321+
cache.recordDependencies(lookupResult.value(), Diagnostics);
13221322
if (!lookupResult.value().empty())
13231323
swiftOverlayDependencies.insert({moduleName, lookupResult.value()[0].first.Kind});
13241324
}

0 commit comments

Comments
 (0)