Skip to content

Commit 69f8a6f

Browse files
authored
Merge pull request #81313 from artemcm/DepScanVariantError
[Dependency Scanning] Emit a detailed error diagnostic on Clang module variant discovery
2 parents c2a1081 + 4b26a3d commit 69f8a6f

File tree

5 files changed

+74
-12
lines changed

5 files changed

+74
-12
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/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)