Author: Qiongsi Wu Date: 2026-03-04T08:26:50-08:00 New Revision: 668d09b2846d9794b35daa2744bf6d4c66c5ec42
URL: https://github.com/llvm/llvm-project/commit/668d09b2846d9794b35daa2744bf6d4c66c5ec42 DIFF: https://github.com/llvm/llvm-project/commit/668d09b2846d9794b35daa2744bf6d4c66c5ec42.diff LOG: [clang][Modules] Fixing unexpected warnings triggered by a PCH and a module with config macros (#177078) When a PCH is compiled with macro definitions on the command line, such as `-DCONFIG1`, an unexpected warning can occur if the macro definitions happen to belong to an imported module's config macros. The warning may look like the following: ``` definition of configuration macro 'CONFIG1' has no effect on the import of 'Mod1'; pass '-DCONFIG1=...' on the command line to configure the module ``` while `-DCONFIG1` is clearly on the command line when `clang` compiles the source that uses the PCH and the module. The reason this can happen is a combination of two things: 1. The logic that checks for config macros is not aware of any command line macros passed through the PCH ([here](https://github.com/llvm/llvm-project/blob/7976ac990000a58a7474269a3ca95e16aed8c35b/clang/lib/Frontend/CompilerInstance.cpp#L1562)). 2. `clang` _replaces_ the predefined macros on the command line with the predefined macros from the PCH, which does not include any builtins ([here](https://github.com/llvm/llvm-project/blob/7976ac990000a58a7474269a3ca95e16aed8c35b/clang/lib/Frontend/CompilerInstance.cpp#L679)). This PR teaches the preprocessor to recognize the command line macro definitions passed transitively through the PCH, so that the error check does not miss these definitions by mistake. The config macro itself works fine, and it is only the error check that needs fixing. rdar://95261458 Added: clang/test/Modules/Inputs/pch-config-macros/include/Mod1.h clang/test/Modules/Inputs/pch-config-macros/include/module.modulemap clang/test/Modules/pch-config-macros.c Modified: clang/lib/Frontend/CompilerInstance.cpp Removed: ################################################################################ diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 135923058bc55..dd774f7319bb2 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1578,9 +1578,14 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, // Find the macro definition from the command line. MacroInfo *CmdLineDefinition = nullptr; 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()) + SourceLocation MDLoc = MD->getLocation(); + FileID FID = SourceMgr.getFileID(MDLoc); + if (FID.isInvalid()) + continue; + // We only care about the predefines buffer, or if the macro is defined + // over the command line transitively through a PCH. + if (FID != PP.getPredefinesFileID() && + !SourceMgr.isWrittenInCommandLineFile(MDLoc)) continue; if (auto *DMD = dyn_cast<DefMacroDirective>(MD)) CmdLineDefinition = DMD->getMacroInfo(); @@ -1602,7 +1607,7 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, << true; return; } else if (!CmdLineDefinition) { - // There was no definition for this macro in the predefines buffer, + // There was no definition for this macro in the command line, // but there was a local definition. Complain. PP.Diag(ImportLoc, diag::warn_module_config_macro_undef) << false << ConfigMacro << Mod->getFullModuleName(); 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..3018629d31d25 --- /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,CONFIG3 +} diff --git a/clang/test/Modules/pch-config-macros.c b/clang/test/Modules/pch-config-macros.c new file mode 100644 index 0000000000000..348d079d34dad --- /dev/null +++ b/clang/test/Modules/pch-config-macros.c @@ -0,0 +1,93 @@ +// 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. +// The warnings should not fire if the config macros are specified when +// building the pch and the main TU. +// 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: %t/h1.h -emit-pch -o %t/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 %t/h1.h.pch %t/bridging.h -emit-pch -o %t/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 %t/main.o %t/main.c -include-pch %t/bridging.h.pch \ +// RUN: -DCONFIG1 -DCONFIG2 -verify + +// Checking that the warnings fire correctly when we compile with a chain of +// PCHs. +// 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 %t/compile_warning_1.o %t/compile_warning_1.c -include-pch \ +// RUN: %t/bridging.h.pch -DCONFIG1 -DCONFIG2 -verify +// 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 %t/compile_warning_2.o %t/compile_warning_2.c -include-pch \ +// RUN: %t/bridging.h.pch -DCONFIG1 -DCONFIG2 -verify +// 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 %t/compile_warning_3.o %t/compile_warning_3.c -include-pch \ +// RUN: %t/bridging.h.pch -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(); +} + +// Checks against expected warnings. +//--- compile_warning_1.c +#undef CONFIG1 // expected-note{{macro was #undef'd here}} +#include "Mod1.h" // expected-warning{{#undef of configuration macro 'CONFIG1' has no effect on the import of 'Mod1'; pass '-UCONFIG1' on the command line to configure the module}} + +int main_func() { + return foo() + bar(); +} + +//--- compile_warning_2.c +#define CONFIG3 // expected-note{{macro was defined here}} +#include "Mod1.h" // expected-warning{{definition of configuration macro 'CONFIG3' has no effect on the import of 'Mod1'; pass '-DCONFIG3=...' on the command line to configure the module}} + +int main_func() { + return foo() + bar(); +} + +//--- compile_warning_3.c +#define CONFIG1 2 // expected-warning{{'CONFIG1' macro redefined}} expected-note{{previous definition is here}} expected-note{{macro was defined here}} +#include "Mod1.h" // expected-warning{{definition of configuration macro 'CONFIG1' has no effect on the import of 'Mod1'; pass '-DCONFIG1=...' on the command line to configure the module}} + +int main_func() { + return foo() + bar(); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
