Skip to content

Commit 7f950ff

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 696ba3e commit 7f950ff

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
@@ -618,5 +618,15 @@ ERROR(ast_format_requires_dump_ast,none,
618618
ERROR(unknown_dump_ast_format,none,
619619
"unknown format '%0' requested with '-dump-ast-format'", (StringRef))
620620

621+
ERROR(dependency_scan_unexpected_variant, none,
622+
"unexpected variant during dependency scanning on module '%0'", (StringRef))
623+
NOTE(dependency_scan_unexpected_variant_context_hash_note, none,
624+
"first module context hash: '%0', second module context hash: '%1'", (StringRef, StringRef))
625+
NOTE(dependency_scan_unexpected_variant_module_map_note, none,
626+
"first module module map: '%0', second module module map: '%1'", (StringRef, StringRef))
627+
NOTE(dependency_scan_unexpected_variant_extra_arg_note, none,
628+
"%select{first|second}0 module command-line has extra argument: '%1'", (bool, StringRef))
629+
630+
621631
#define UNDEFINE_DIAGNOSTIC_MACROS
622632
#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
@@ -2199,13 +2199,6 @@ Identifier ASTContext::getRealModuleName(Identifier key, ModuleAliasLookupOption
21992199
return value.first;
22002200
}
22012201

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

lib/AST/ModuleDependencies.cpp

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

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