mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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.
This commit is contained in:
@@ -886,11 +886,61 @@ void ModuleDependenciesCache::recordDependency(
|
||||
}
|
||||
|
||||
void ModuleDependenciesCache::recordDependencies(
|
||||
ModuleDependencyVector dependencies) {
|
||||
ModuleDependencyVector dependencies, DiagnosticEngine &diags) {
|
||||
for (const auto &dep : dependencies) {
|
||||
if (!hasDependency(dep.first))
|
||||
if (hasDependency(dep.first)) {
|
||||
if (dep.first.Kind == ModuleDependencyKind::Clang) {
|
||||
auto priorClangModuleDetails =
|
||||
findKnownDependency(dep.first).getAsClangModule();
|
||||
auto newClangModuleDetails = dep.second.getAsClangModule();
|
||||
auto priorContextHash = priorClangModuleDetails->contextHash;
|
||||
auto newContextHash = newClangModuleDetails->contextHash;
|
||||
if (priorContextHash != newContextHash) {
|
||||
// This 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.
|
||||
//
|
||||
// Emit a failure diagnostic here that is hopefully more actionable
|
||||
// for the time being.
|
||||
diags.diagnose(SourceLoc(), diag::dependency_scan_unexpected_variant,
|
||||
dep.first.ModuleName);
|
||||
diags.diagnose(
|
||||
SourceLoc(),
|
||||
diag::dependency_scan_unexpected_variant_context_hash_note,
|
||||
priorContextHash, newContextHash);
|
||||
diags.diagnose(
|
||||
SourceLoc(),
|
||||
diag::dependency_scan_unexpected_variant_module_map_note,
|
||||
priorClangModuleDetails->moduleMapFile,
|
||||
newClangModuleDetails->moduleMapFile);
|
||||
|
||||
auto diagnoseExtraCommandLineFlags =
|
||||
[&diags](const ClangModuleDependencyStorage *checkModuleDetails,
|
||||
const ClangModuleDependencyStorage *baseModuleDetails,
|
||||
bool isNewlyDiscovered) -> void {
|
||||
std::unordered_set<std::string> baseCommandLineSet(
|
||||
baseModuleDetails->buildCommandLine.begin(),
|
||||
baseModuleDetails->buildCommandLine.end());
|
||||
for (const auto &checkArg : checkModuleDetails->buildCommandLine)
|
||||
if (baseCommandLineSet.find(checkArg) == baseCommandLineSet.end())
|
||||
diags.diagnose(
|
||||
SourceLoc(),
|
||||
diag::dependency_scan_unexpected_variant_extra_arg_note,
|
||||
isNewlyDiscovered, checkArg);
|
||||
};
|
||||
diagnoseExtraCommandLineFlags(priorClangModuleDetails,
|
||||
newClangModuleDetails, true);
|
||||
diagnoseExtraCommandLineFlags(newClangModuleDetails,
|
||||
priorClangModuleDetails, false);
|
||||
}
|
||||
}
|
||||
} else
|
||||
recordDependency(dep.first.ModuleName, dep.second);
|
||||
if (dep.second.getKind() == ModuleDependencyKind::Clang) {
|
||||
|
||||
if (dep.first.Kind == ModuleDependencyKind::Clang) {
|
||||
auto clangModuleDetails = dep.second.getAsClangModule();
|
||||
addSeenClangModule(clang::tooling::dependencies::ModuleID{
|
||||
dep.first.ModuleName, clangModuleDetails->contextHash});
|
||||
|
||||
Reference in New Issue
Block a user