From 5da2f66755a18a176131a7f1ab0ae71ace424c40 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Mon, 21 Apr 2025 12:52:37 -0700 Subject: [PATCH] [CAS] Improve error message when module cache key is missing When a module cache key is missing, emit better diagnostics that * It is clear it is a cache key missing, so a potential dependency missing, not a CAS error * For other compiler consumers, like a swift compiler that uses a different cache key schema than the clang include tree, it is possible that a detailed cache key cannot be printed. Don't emit extra schema mismatch message that can confuse the users rdar://149707188 (cherry picked from commit a6aa93cadca9e26880b33a2a71af741a806e533d) --- .../include/clang/Basic/DiagnosticCASKinds.td | 6 ++- clang/lib/Frontend/CompileJobCacheKey.cpp | 9 +--- clang/lib/Frontend/CompilerInstance.cpp | 47 ++++++++++--------- .../DependencyScanning/ModuleDepCollector.cpp | 5 +- .../test/CAS/fmodule-file-cache-key-errors.c | 8 ++-- clang/test/ClangScanDeps/modules-cas-trees.c | 2 +- 6 files changed, 40 insertions(+), 37 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticCASKinds.td b/clang/include/clang/Basic/DiagnosticCASKinds.td index e8cfead1d1419..0e9217a1bfc9f 100644 --- a/clang/include/clang/Basic/DiagnosticCASKinds.td +++ b/clang/include/clang/Basic/DiagnosticCASKinds.td @@ -23,8 +23,10 @@ def err_cas_depscan_daemon_connection: Error< def err_cas_depscan_failed: Error< "CAS-based dependency scan failed: %0">, DefaultFatal; def err_cas_store: Error<"failed to store to CAS: %0">, DefaultFatal; -def err_cas_cannot_get_module_cache_key : Error< - "CAS cannot load module with key '%0' from %1: %2">, DefaultFatal; +def err_cas_unloadable_module : Error< + "module file '%0' not found: unloadable module cache key %1: %2">, DefaultFatal; +def err_cas_missing_module : Error< + "module file '%0' not found: missing module cache key %1: %2">, DefaultFatal; def err_cas_missing_root_id : Error< "CAS missing expected root-id '%0'">, DefaultFatal; def err_cas_cannot_parse_root_id_for_module : Error< diff --git a/clang/lib/Frontend/CompileJobCacheKey.cpp b/clang/lib/Frontend/CompileJobCacheKey.cpp index 83c056927781a..48a14c3eca26d 100644 --- a/clang/lib/Frontend/CompileJobCacheKey.cpp +++ b/clang/lib/Frontend/CompileJobCacheKey.cpp @@ -304,12 +304,7 @@ Error clang::printCompileJobCacheKey(ObjectStore &CAS, const CASID &Key, if (!H) return H.takeError(); TreeSchema Schema(CAS); - if (!Schema.isNode(*H)) { - std::string ErrStr; - llvm::raw_string_ostream Err(ErrStr); - Err << "expected cache key to be a CAS tree; got "; - H->getID().print(Err); - return createStringError(inconvertibleErrorCode(), Err.str()); - } + if (!Schema.isNode(*H)) + return createStringError("unexpected cache key schema"); return ::printCompileJobCacheKey(CAS, *H, OS); } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index ba23a3e81c932..99e9f907ba47a 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -2543,31 +2543,36 @@ static bool addCachedModuleFileToInMemoryCache( auto ID = CAS.parseID(CacheKey); if (!ID) { - Diags.Report(diag::err_cas_cannot_get_module_cache_key) - << CacheKey << Provider << ID.takeError(); + Diags.Report(diag::err_cas_unloadable_module) + << Path << CacheKey << ID.takeError(); return true; } auto Value = Cache.get(*ID); - if (!Value || !*Value) { - auto Diag = Diags.Report(diag::err_cas_cannot_get_module_cache_key) - << CacheKey << Provider; - if (!Value) { - Diag << Value.takeError(); - } else { - std::string ErrStr("no such entry in action cache; expected compile:\n"); - llvm::raw_string_ostream Err(ErrStr); - if (auto E = printCompileJobCacheKey(CAS, *ID, Err)) - Diag << std::move(E); - else - Diag << Err.str(); - } + if (!Value) { + Diags.Report(diag::err_cas_unloadable_module) + << Path << CacheKey << Value.takeError(); + return true; + } + if (!*Value) { + auto Diag = Diags.Report(diag::err_cas_missing_module) + << Path << CacheKey; + std::string ErrStr("expected to be produced by:\n"); + llvm::raw_string_ostream Err(ErrStr); + if (auto E = printCompileJobCacheKey(CAS, *ID, Err)) { + // Ignore the error and skip printing the cache key. The cache key can + // be setup by a different compiler that is using an unknown schema. + llvm::consumeError(std::move(E)); + Diag << "module file is not available in the CAS"; + } else + Diag << Err.str(); + return true; } auto ValueRef = CAS.getReference(**Value); if (!ValueRef) { - Diags.Report(diag::err_cas_cannot_get_module_cache_key) - << CacheKey << Provider << "result module doesn't exist in CAS"; + Diags.Report(diag::err_cas_unloadable_module) + << Path << CacheKey << "result module cannot be loaded from CAS"; return true; } @@ -2575,8 +2580,8 @@ static bool addCachedModuleFileToInMemoryCache( std::optional Result; cas::CompileJobResultSchema Schema(CAS); if (llvm::Error E = Schema.load(*ValueRef).moveInto(Result)) { - Diags.Report(diag::err_cas_cannot_get_module_cache_key) - << CacheKey << Provider << std::move(E); + Diags.Report(diag::err_cas_unloadable_module) + << Path << CacheKey << std::move(E); return true; } auto Output = @@ -2589,8 +2594,8 @@ static bool addCachedModuleFileToInMemoryCache( // better network utilization. auto OutputProxy = CAS.getProxy(Output->Object); if (!OutputProxy) { - Diags.Report(diag::err_cas_cannot_get_module_cache_key) - << CacheKey << Provider << OutputProxy.takeError(); + Diags.Report(diag::err_cas_unloadable_module) + << Path << CacheKey << OutputProxy.takeError(); return true; } diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp index 0d784865faa73..ad40e2f47d3d2 100644 --- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp +++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp @@ -657,10 +657,11 @@ static void checkCompileCacheKeyMatch(cas::ObjectStore &CAS, llvm::report_fatal_error(OldKey.takeError()); SmallString<256> Err; llvm::raw_svector_ostream OS(Err); - OS << "Compile cache key for module changed; previously:"; + OS << "Compile cache key for module changed; previously: " + << OldKey->toString() << ": "; if (auto E = printCompileJobCacheKey(CAS, *OldKey, OS)) OS << std::move(E); - OS << "\nkey is now:"; + OS << "\nkey is now: " << NewKey.toString() << ": "; if (auto E = printCompileJobCacheKey(CAS, NewKey, OS)) OS << std::move(E); llvm::report_fatal_error(OS.str()); diff --git a/clang/test/CAS/fmodule-file-cache-key-errors.c b/clang/test/CAS/fmodule-file-cache-key-errors.c index bda2fbe4c657b..1879069a1f3cc 100644 --- a/clang/test/CAS/fmodule-file-cache-key-errors.c +++ b/clang/test/CAS/fmodule-file-cache-key-errors.c @@ -26,7 +26,7 @@ // RUN: -fcache-compile-job -Rcompile-job-cache &> %t/invalid2.txt // RUN: FileCheck %s -check-prefix=INVALID2 -input-file=%t/invalid2.txt -// INVALID2: error: CAS cannot load module with key '-fsyntax-only' from -fmodule-file-cache-key +// INVALID2: error: module file 'INVALID' not found: unloadable module cache key -fsyntax-only: invalid cas-id '-fsyntax-only' // RUN: not %clang_cc1 -triple x86_64-apple-macos11 \ // RUN: -fmodules -fno-implicit-modules \ @@ -46,7 +46,7 @@ // RUN: -fcache-compile-job -Rcompile-job-cache &> %t/bad_key.txt // RUN: cat %t/bad_key.txt | FileCheck %s -check-prefix=BAD_KEY -// BAD_KEY: error: CAS cannot load module with key 'KEY' from -fmodule-file-cache-key: invalid cas-id 'KEY' +// BAD_KEY: error: module file 'PATH' not found: unloadable module cache key KEY: invalid cas-id 'KEY' // RUN: echo -n '-fmodule-file-cache-key PATH ' > %t/bad_key2.rsp // RUN: cat %t/casid >> %t/bad_key2.rsp @@ -59,7 +59,7 @@ // RUN: -fcache-compile-job -Rcompile-job-cache &> %t/bad_key2.txt // RUN: cat %t/bad_key2.txt | FileCheck %s -check-prefix=BAD_KEY2 -// BAD_KEY2: error: CAS cannot load module with key '{{.*}}' from -fmodule-file-cache-key: cas object is not a valid cache key +// BAD_KEY2: error: module file 'PATH' not found: missing module cache key {{.*}}: module file is not available in the CAS // == Build A @@ -87,7 +87,7 @@ // RUN: -fcache-compile-job -Rcompile-job-cache &> %t/not_in_cache.txt // RUN: cat %t/not_in_cache.txt | FileCheck %s -check-prefix=NOT_IN_CACHE -DPREFIX=%/t -// NOT_IN_CACHE: error: CAS cannot load module with key '{{.*}}' from -fmodule-file-cache-key: no such entry in action cache; expected compile: +// NOT_IN_CACHE: error: module file 'PATH' not found: missing module cache key {{.*}}: expected to be produced by: // NOT_IN_CACHE: command-line: // NOT_IN_CACHE: -cc1 // NOT_IN_CACHE: filesystem: diff --git a/clang/test/ClangScanDeps/modules-cas-trees.c b/clang/test/ClangScanDeps/modules-cas-trees.c index f1cab97f9ed89..2077b697c6c13 100644 --- a/clang/test/ClangScanDeps/modules-cas-trees.c +++ b/clang/test/ClangScanDeps/modules-cas-trees.c @@ -42,7 +42,7 @@ // Missing pcm in action cache // RUN: not %clang @%t/Left.rsp 2> %t/error.txt // RUN: cat %t/error.txt | FileCheck %s -check-prefix=MISSING -// MISSING: error: CAS cannot load module with key '{{.*}}' from -fmodule-file-cache-key: no such entry in action cache +// MISSING: error: module file '{{.*}}.pcm' not found: missing module cache key {{.*}}: expected to be produced by: // Build everything // RUN: %clang @%t/Top.rsp 2>&1 | FileCheck %s -check-prefix=CACHE-MISS