https://github.com/qiongsiwu updated https://github.com/llvm/llvm-project/pull/174034
>From 8d00ccc86f1d9c0354ce15514da9cbb3c6dafc0d Mon Sep 17 00:00:00 2001 From: Qiongsi Wu <[email protected]> Date: Tue, 30 Dec 2025 15:10:04 -0800 Subject: [PATCH] Fixing unexpected config macro diagnostics when a PCH is included. --- clang/include/clang/Lex/Preprocessor.h | 11 +++++ clang/lib/Frontend/CompilerInstance.cpp | 4 +- clang/lib/Lex/PPMacroExpansion.cpp | 32 +++++++++++++ .../Inputs/pch-config-macros/include/Mod1.h | 5 ++ .../include/module.modulemap | 4 ++ clang/test/Modules/pch-config-macros.c | 48 +++++++++++++++++++ 6 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 clang/test/Modules/Inputs/pch-config-macros/include/Mod1.h create mode 100644 clang/test/Modules/Inputs/pch-config-macros/include/module.modulemap create mode 100644 clang/test/Modules/pch-config-macros.c diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index b1c648e647f41..4bff1b395b5fc 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1119,6 +1119,10 @@ class Preprocessor { /// The file ID for the PCH through header. FileID PCHThroughHeaderFileID; + /// The file ID for the predefines that come from the PCH. + /// This is only set when modules are in effect. + FileID PCHPredefinesFileID; + /// Whether tokens are being skipped until a #pragma hdrstop is seen. bool SkippingUntilPragmaHdrStop = false; @@ -1315,6 +1319,13 @@ class Preprocessor { /// Returns the FileID for the preprocessor predefines. FileID getPredefinesFileID() const { return PredefinesFileID; } + /// Returns the FileID for the predefines loaded from the PCH. + FileID getPCHPredefinesFileID() const { + assert(getLangOpts().Modules && + "PCHPredefinedFileID is only set when modules is in effect!"); + return PCHPredefinesFileID; + } + /// \{ /// Accessors for preprocessor callbacks. /// diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index f7f0ea3317932..ac27ae692b2a2 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1548,7 +1548,9 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, for (auto *MD = LatestLocalMD; MD; MD = MD->getPrevious()) { // We only care about the predefines buffer. FileID FID = SourceMgr.getFileID(MD->getLocation()); - if (FID.isInvalid() || FID != PP.getPredefinesFileID()) + if (FID.isInvalid()) + continue; + if (FID != PP.getPredefinesFileID() && FID != PP.getPCHPredefinesFileID()) continue; if (auto *DMD = dyn_cast<DefMacroDirective>(MD)) CmdLineDefinition = DMD->getMacroInfo(); diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 5efa4b5b3f872..6b6ef9fe9f3ed 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -125,6 +125,38 @@ void Preprocessor::setLoadedMacroDirective(IdentifierInfo *II, II->setHasMacroDefinition(true); if (!MD->isDefined() && !LeafModuleMacros.contains(II)) II->setHasMacroDefinition(false); + + if (getLangOpts().Modules) { + // When both modules and a PCH are used, we may run into the following + // situation: + // - the PCH is compiled with macro definitions on the command line. + // - the modules are compiled with the same set of macros on the command + // line. + // In this case, clang needs to know that some predefined macros exist + // over the command line transitively through the PCH and some are passed + // directly over the command line. The preprocessor stores + // PCHPredefinesFileID so later it is aware of macros defined transitively + // through the PCH's compilation. + auto MDLoc = MD->getLocation(); + + // The PCH loads the command line macros into the <built-in> buffer. + // This is not the same as SourceMgr.isWrittenInBuiltinFile(MDLoc), + // since we are not looking at the Presumed location. + if (SourceMgr.getBufferName(MDLoc) == "<built-in>") { + auto MDFileID = SourceMgr.getFileID(MDLoc); + if (PCHPredefinesFileID.isInvalid()) + PCHPredefinesFileID = MDFileID; + else { + // The PCH and all the chain of headers it includes must be + // compiled with the exact same set of macros defined over the + // command line. No different macros should be defined over + // different command line invocations. This means that all the macros' + // source locations should have the same MDFileID. + assert(MDFileID == PCHPredefinesFileID && + "PCHBuiltinFileID must be consistent!"); + } + } + } } ModuleMacro *Preprocessor::addModuleMacro(Module *Mod, IdentifierInfo *II, diff --git a/clang/test/Modules/Inputs/pch-config-macros/include/Mod1.h b/clang/test/Modules/Inputs/pch-config-macros/include/Mod1.h new file mode 100644 index 0000000000000..3b8f33877dcd2 --- /dev/null +++ b/clang/test/Modules/Inputs/pch-config-macros/include/Mod1.h @@ -0,0 +1,5 @@ +#if CONFIG1 +int foo() { return 42; } +#else +int foo() { return 43; } +#endif diff --git a/clang/test/Modules/Inputs/pch-config-macros/include/module.modulemap b/clang/test/Modules/Inputs/pch-config-macros/include/module.modulemap new file mode 100644 index 0000000000000..9d5f2e714ec88 --- /dev/null +++ b/clang/test/Modules/Inputs/pch-config-macros/include/module.modulemap @@ -0,0 +1,4 @@ +module Mod1 { + header "Mod1.h" + config_macros CONFIG1,CONFIG2 +} diff --git a/clang/test/Modules/pch-config-macros.c b/clang/test/Modules/pch-config-macros.c new file mode 100644 index 0000000000000..1cf7f60eea11a --- /dev/null +++ b/clang/test/Modules/pch-config-macros.c @@ -0,0 +1,48 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: cd %t + +// This test builds two PCHs. bridging.h.pch depends on h1.h.pch. +// Then the test uses bridiging.h.pch in a source file that imports +// a module with config macros. +// This is a normal use case and no warnings should be issued. +// RUN: %clang_cc1 -fmodules \ +// RUN: -fmodule-map-file=%S/Inputs/pch-config-macros/include/module.modulemap \ +// RUN: -fmodules-cache-path=%t/cache -I %S/Inputs/pch-config-macros/include \ +// RUN: h1.h -emit-pch -o h1.h.pch -DCONFIG1 -DCONFIG2 +// RUN: %clang_cc1 -fmodules \ +// RUN: -fmodule-map-file=%S/Inputs/pch-config-macros/include/module.modulemap \ +// RUN: -fmodules-cache-path=%t/cache -I %S/Inputs/pch-config-macros/include \ +// RUN: -include-pch h1.h.pch bridging.h -emit-pch -o bridging.h.pch \ +// RUN: -DCONFIG1 -DCONFIG2 +// RUN: %clang_cc1 -fmodules \ +// RUN: -fmodule-map-file=%S/Inputs/pch-config-macros/include/module.modulemap \ +// RUN: -fmodules-cache-path=%t/cache -I %S/Inputs/pch-config-macros/include \ +// RUN: -emit-obj -o main.o main.c -include-pch bridging.h.pch \ +// RUN: -DCONFIG1 -DCONFIG2 -verify + +//--- h1.h +#if CONFIG1 +int bar1() { return 42; } +#else +int bar2() { return 43; } +#endif + +//--- bridging.h +#if CONFIG1 +int bar() { return bar1(); } +#else +int bar() { return bar2(); } +#endif + +#if CONFIG2 +int baz() { return 77; } +#endif + +//--- main.c +#include "Mod1.h" +// expected-no-diagnostics + +int main_func() { + return foo() + bar(); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
