Author: Cyndy Ishida Date: 2026-01-05T12:06:24-08:00 New Revision: 5089f634609aab7bec747c731ecdb572ac4d9d40
URL: https://github.com/llvm/llvm-project/commit/5089f634609aab7bec747c731ecdb572ac4d9d40 DIFF: https://github.com/llvm/llvm-project/commit/5089f634609aab7bec747c731ecdb572ac4d9d40.diff LOG: [clang][modules] Diagnose config mismatches more generally from precompiled files (#174260) PCHs (but also modules generated from several implicit invocations like swiftc) previously reported a confusing diagnostic about module caches being mismatched by subdir. This is an implementation detail of the module machinery, and not very useful to the end user. Instead, report this case as a configuration mismatch when the compiler can confirm the module cache was passed the same between the current TU & previously compiled products. Ideally, each argument that could result in this error would be uniquely reported (e.g., O3), but as a starting point, providing something more general is strictly better than pointing the user to the module cache. This patch also includes NFCs for renaming variable names from Module to AST and formatting cleanup in related areas. resolves: rdar://167453135 Added: clang/test/Modules/precompiled-config-mismatch-diagnostics.c Modified: clang/include/clang/Basic/DiagnosticFrontendKinds.td clang/include/clang/Basic/DiagnosticSerializationKinds.td clang/include/clang/Serialization/ASTReader.h clang/lib/Frontend/CompilerInstance.cpp clang/lib/Frontend/FrontendAction.cpp clang/lib/Serialization/ASTReader.cpp clang/test/Modules/ignored_macros.m clang/test/Modules/mismatch-diagnostics.cpp clang/test/PCH/module-hash-difference.m Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 66c7f92622d1e..e2b257ceae80d 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -217,11 +217,8 @@ def note_incompatible_analyzer_plugin_api : Note< def err_module_build_requires_fmodules : Error< "module compilation requires '-fmodules'">; -def err_module_interface_requires_cpp_modules : Error< - "module interface compilation requires '-std=c++20'">; -def warn_module_config_mismatch : Warning< - "module file %0 cannot be loaded due to a configuration mismatch with the current " - "compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError; +def err_module_interface_requires_cpp_modules + : Error<"module interface compilation requires '-std=c++20'">; def err_module_map_not_found : Error<"module map file '%0' not found">, DefaultFatal; def err_missing_module_name : Error< diff --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td b/clang/include/clang/Basic/DiagnosticSerializationKinds.td index b80aff385e01f..229f0bacbd796 100644 --- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td @@ -39,6 +39,12 @@ def err_ast_file_targetopt_feature_mismatch : Error< "not">; def err_ast_file_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " "precompiled file '%3' but is currently %select{disabled|enabled}2">; +def warn_ast_file_config_mismatch + : Warning<"precompiled file '%0' cannot be loaded due to a configuration " + "mismatch with the current " + "compilation">, + InGroup<DiagGroup<"module-file-config-mismatch">>, + DefaultError; def err_ast_file_langopt_value_mismatch : Error< "%0 diff ers in precompiled file '%1' vs. current file">; def err_ast_file_codegenopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index a720e5aca444b..2b3fa6d52f163 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -2024,7 +2024,8 @@ class ASTReader StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, const CodeGenOptions &CGOpts, const TargetOptions &TargetOpts, - const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath, + const PreprocessorOptions &PPOpts, const HeaderSearchOptions &HSOpts, + StringRef ExistingModuleCachePath, bool RequireStrictOptionMatches = false); /// Returns the suggested contents of the predefines buffer, diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 783c340e6a282..e0dd64fe50c99 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -41,6 +41,7 @@ #include "clang/Serialization/GlobalModuleIndex.h" #include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/ModuleCache.h" +#include "clang/Serialization/SerializationDiagnostic.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -1674,9 +1675,9 @@ bool CompilerInstance::loadModuleFile( // If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the // ASTReader to diagnose it, since it can produce better errors that we can. bool ConfigMismatchIsRecoverable = - getDiagnostics().getDiagnosticLevel(diag::warn_module_config_mismatch, - SourceLocation()) - <= DiagnosticsEngine::Warning; + getDiagnostics().getDiagnosticLevel(diag::warn_ast_file_config_mismatch, + SourceLocation()) <= + DiagnosticsEngine::Warning; auto Listener = std::make_unique<ReadModuleNames>(*PP); auto &ListenerRef = *Listener; @@ -1696,7 +1697,8 @@ bool CompilerInstance::loadModuleFile( case ASTReader::ConfigurationMismatch: // Ignore unusable module files. - getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch) + getDiagnostics().Report(SourceLocation(), + diag::warn_ast_file_config_mismatch) << FileName; // All modules provided by any files we tried and failed to load are now // unavailable; includes of those modules should now be handled textually. @@ -1848,7 +1850,7 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST( // FIXME: We shouldn't be setting HadFatalFailure below if we only // produce a warning here! getDiagnostics().Report(SourceLocation(), - diag::warn_module_config_mismatch) + diag::warn_ast_file_config_mismatch) << ModuleFilename; // Fall through to error out. [[fallthrough]]; diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 6a1fb2fd46063..5c2ac862b5e75 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -1039,7 +1039,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, Dir->path(), FileMgr, CI.getModuleCache(), CI.getPCHContainerReader(), CI.getLangOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), - CI.getPreprocessorOpts(), SpecificModuleCachePath, + CI.getPreprocessorOpts(), CI.getHeaderSearchOpts(), + SpecificModuleCachePath, /*RequireStrictOptionMatches=*/true)) { PPOpts.ImplicitPCHInclude = std::string(Dir->path()); Found = true; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 540373cebdfc6..c2426e88158b9 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -960,13 +960,12 @@ bool SimpleASTReaderListener::ReadPreprocessorOptions( /// /// \param Diags If non-null, produce diagnostics for any mismatches incurred. /// \returns true when the module cache paths diff er. -static bool checkModuleCachePath(llvm::vfs::FileSystem &VFS, - StringRef SpecificModuleCachePath, - StringRef ExistingModuleCachePath, - StringRef ModuleFilename, - DiagnosticsEngine *Diags, - const LangOptions &LangOpts, - const PreprocessorOptions &PPOpts) { +static bool checkModuleCachePath( + llvm::vfs::FileSystem &VFS, StringRef SpecificModuleCachePath, + StringRef ExistingModuleCachePath, StringRef ASTFilename, + DiagnosticsEngine *Diags, const LangOptions &LangOpts, + const PreprocessorOptions &PPOpts, const HeaderSearchOptions &HSOpts, + const HeaderSearchOptions &ASTFileHSOpts) { if (!LangOpts.Modules || PPOpts.AllowPCHWithDifferentModulesCachePath || SpecificModuleCachePath == ExistingModuleCachePath) return false; @@ -974,21 +973,31 @@ static bool checkModuleCachePath(llvm::vfs::FileSystem &VFS, VFS.equivalent(SpecificModuleCachePath, ExistingModuleCachePath); if (EqualOrErr && *EqualOrErr) return false; - if (Diags) - Diags->Report(diag::err_ast_file_modulecache_mismatch) - << SpecificModuleCachePath << ExistingModuleCachePath << ModuleFilename; + if (Diags) { + // If the module cache arguments provided from the command line are the + // same, the mismatch must come from other arguments of the configuration + // and not directly the cache path. + EqualOrErr = + VFS.equivalent(ASTFileHSOpts.ModuleCachePath, HSOpts.ModuleCachePath); + if (EqualOrErr && *EqualOrErr) + Diags->Report(clang::diag::warn_ast_file_config_mismatch) << ASTFilename; + else + Diags->Report(diag::err_ast_file_modulecache_mismatch) + << SpecificModuleCachePath << ExistingModuleCachePath << ASTFilename; + } return true; } bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ModuleFilename, + StringRef ASTFilename, StringRef SpecificModuleCachePath, bool Complain) { + const HeaderSearch &HeaderSearchInfo = PP.getHeaderSearchInfo(); return checkModuleCachePath( Reader.getFileManager().getVirtualFileSystem(), SpecificModuleCachePath, - PP.getHeaderSearchInfo().getModuleCachePath(), ModuleFilename, + HeaderSearchInfo.getModuleCachePath(), ASTFilename, Complain ? &Reader.Diags : nullptr, PP.getLangOpts(), - PP.getPreprocessorOpts()); + PP.getPreprocessorOpts(), HeaderSearchInfo.getHeaderSearchOpts(), HSOpts); } void PCHValidator::ReadCounter(const ModuleFile &M, uint32_t Value) { @@ -5763,6 +5772,7 @@ namespace { const CodeGenOptions &ExistingCGOpts; const TargetOptions &ExistingTargetOpts; const PreprocessorOptions &ExistingPPOpts; + const HeaderSearchOptions &ExistingHSOpts; std::string ExistingModuleCachePath; FileManager &FileMgr; bool StrictOptionMatches; @@ -5772,11 +5782,12 @@ namespace { const CodeGenOptions &ExistingCGOpts, const TargetOptions &ExistingTargetOpts, const PreprocessorOptions &ExistingPPOpts, + const HeaderSearchOptions &ExistingHSOpts, StringRef ExistingModuleCachePath, FileManager &FileMgr, bool StrictOptionMatches) : ExistingLangOpts(ExistingLangOpts), ExistingCGOpts(ExistingCGOpts), ExistingTargetOpts(ExistingTargetOpts), - ExistingPPOpts(ExistingPPOpts), + ExistingPPOpts(ExistingPPOpts), ExistingHSOpts(ExistingHSOpts), ExistingModuleCachePath(ExistingModuleCachePath), FileMgr(FileMgr), StrictOptionMatches(StrictOptionMatches) {} @@ -5802,13 +5813,13 @@ namespace { } bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef ModuleFilename, + StringRef ASTFilename, StringRef SpecificModuleCachePath, bool Complain) override { - return checkModuleCachePath(FileMgr.getVirtualFileSystem(), - SpecificModuleCachePath, - ExistingModuleCachePath, ModuleFilename, - nullptr, ExistingLangOpts, ExistingPPOpts); + return checkModuleCachePath( + FileMgr.getVirtualFileSystem(), SpecificModuleCachePath, + ExistingModuleCachePath, ASTFilename, nullptr, ExistingLangOpts, + ExistingPPOpts, ExistingHSOpts, HSOpts); } bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, @@ -6150,9 +6161,9 @@ bool ASTReader::isAcceptableASTFile( StringRef Filename, FileManager &FileMgr, const ModuleCache &ModCache, const PCHContainerReader &PCHContainerRdr, const LangOptions &LangOpts, const CodeGenOptions &CGOpts, const TargetOptions &TargetOpts, - const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath, - bool RequireStrictOptionMatches) { - SimplePCHValidator validator(LangOpts, CGOpts, TargetOpts, PPOpts, + const PreprocessorOptions &PPOpts, const HeaderSearchOptions &HSOpts, + StringRef ExistingModuleCachePath, bool RequireStrictOptionMatches) { + SimplePCHValidator validator(LangOpts, CGOpts, TargetOpts, PPOpts, HSOpts, ExistingModuleCachePath, FileMgr, RequireStrictOptionMatches); return !readASTFileControlBlock(Filename, FileMgr, ModCache, PCHContainerRdr, diff --git a/clang/test/Modules/ignored_macros.m b/clang/test/Modules/ignored_macros.m index fe5a6f3206296..13e49dba57af3 100644 --- a/clang/test/Modules/ignored_macros.m +++ b/clang/test/Modules/ignored_macros.m @@ -10,7 +10,7 @@ // RUN: %clang_cc1 -fmodules-cache-path=%t.modules -fmodules -fimplicit-module-maps -I %S/Inputs -emit-pch -o %t.pch -x objective-c-header %s -verify // RUN: not %clang_cc1 -fmodules-cache-path=%t.modules -DIGNORED=1 -fmodules -fimplicit-module-maps -I %S/Inputs -include-pch %t.pch %s > %t.err 2>&1 // RUN: FileCheck -check-prefix=CHECK-CONFLICT %s < %t.err -// CHECK-CONFLICT: precompiled file '{{.*}}' was compiled with module cache path +// CHECK-CONFLICT: precompiled file '{{.*}}' cannot be loaded due to a configuration mismatch // Third trial: pass -DIGNORED=1 only to the second invocation, but // make it ignored. There should be no failure, IGNORED is defined in diff --git a/clang/test/Modules/mismatch-diagnostics.cpp b/clang/test/Modules/mismatch-diagnostics.cpp index be58f638cfa80..31d13fdd783f7 100644 --- a/clang/test/Modules/mismatch-diagnostics.cpp +++ b/clang/test/Modules/mismatch-diagnostics.cpp @@ -30,4 +30,4 @@ export module mismatching_module; //--- use.cpp import mismatching_module; // CHECK: error: POSIX thread support was enabled in precompiled file '{{.*[/|\\\\]}}mismatching_module.pcm' but is currently disabled -// CHECK-NEXT: module file {{.*[/|\\\\]}}mismatching_module.pcm cannot be loaded due to a configuration mismatch with the current compilation +// CHECK-NEXT: precompiled file '{{.*[/|\\\\]}}mismatching_module.pcm' cannot be loaded due to a configuration mismatch with the current compilation diff --git a/clang/test/Modules/precompiled-config-mismatch-diagnostics.c b/clang/test/Modules/precompiled-config-mismatch-diagnostics.c new file mode 100644 index 0000000000000..e5ad120700447 --- /dev/null +++ b/clang/test/Modules/precompiled-config-mismatch-diagnostics.c @@ -0,0 +1,49 @@ +// Validate configuration mismatches from precompiled files are reported. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -I%t/BuildDir -fimplicit-module-maps -fmodules \ +// RUN: -fmodules-cache-path=%t/cache %t/h1.h -emit-pch -o %t/BuildDir/h1.h.pch + +// Check command line diff that is reported uniquely. +// RUN: not %clang_cc1 -I%t/BuildDir -fimplicit-module-maps -fmodules \ +// RUN: -O3 \ +// RUN: -fmodules-cache-path=%t/cache -fsyntax-only -include-pch %t/BuildDir/h1.h.pch \ +// RUN: %t/client.c 2>&1 | FileCheck %s --check-prefixes=OPTMODE,CONFIG + +// Check command line diff erence that end up in the module hash, but is not +// uniquely reported as a mismatch. +// RUN: not %clang_cc1 -I%t/BuildDir -fimplicit-module-maps -fmodules \ +// RUN: -dwarf-ext-refs -fmodule-format=obj \ +// RUN: -debug-info-kind=standalone -dwarf-version=5 \ +// RUN: -fmodules-cache-path=%t/cache -fsyntax-only -include-pch %t/BuildDir/h1.h.pch \ +// RUN: %t/client.c 2>&1 | FileCheck %s --check-prefix=CONFIG + +// Check that module cache path is uniquely reported. +// RUN: not %clang_cc1 -I%t/BuildDir -fimplicit-module-maps -fmodules \ +// RUN: -fmodules-cache-path=%t/wrong/cache -fsyntax-only \ +// RUN: -include-pch %t/BuildDir/h1.h.pch \ +// RUN: %t/client.c 2>&1 | FileCheck %s --check-prefix=CACHEPATH + +// OPTMODE: OptimizationLevel diff ers in precompiled file +// CONFIG: h1.h.pch' cannot be loaded due to a configuration mismatch +// CACHEPATH: h1.h.pch' was compiled with module cache path '{{.*}}', but the path is currently '{{.*}}' + +//--- BuildDir/A/module.modulemap +module A [system] { + umbrella "." +} + +//--- BuildDir/A/A.h +typedef int A_t; + +//--- h1.h +#include <A/A.h> +#if __OPTIMIZE__ +A_t foo(void); +#endif + +//--- client.c +typedef int foo_t; + diff --git a/clang/test/PCH/module-hash- diff erence.m b/clang/test/PCH/module-hash- diff erence.m index a48a15398903c..ff8432d3ba67d 100644 --- a/clang/test/PCH/module-hash- diff erence.m +++ b/clang/test/PCH/module-hash- diff erence.m @@ -4,5 +4,5 @@ // RUN: not %clang_cc1 -fsyntax-only -include-pch %t.pch %s -I %S/Inputs/modules -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash 2> %t.err // RUN: FileCheck -input-file=%t.err %s -// CHECK: error: precompiled file '{{.*}}' was compiled with module cache path {{.*}}, but the path is currently {{.*}} +// CHECK: error: precompiled file '{{.*}}' cannot be loaded due to a configuration mismatch with the current compilation @import Foo; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
