https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114423
Lewis Hyatt <lhyatt at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- See Also| |https://gcc.gnu.org/bugzill | |a/show_bug.cgi?id=7263 CC| |dmalcolm at gcc dot gnu.org --- Comment #6 from Lewis Hyatt <lhyatt at gcc dot gnu.org> --- I realized there is something to consider about the fix that has been applied for this issue. t.h: ----- #pragma GCC system_header #warning "warning1" #pragma GCC warning "warning2" #define WARN _Pragma("GCC warning \"warning3\"") ----- t.c: ----- #include "t.h" WARN ----- Prior to r15-4505, the output consists of "warning1" and "warning3", without "warning2". After r15-4505, "warning3" is also suppressed. The behavior of #warning in system headers is by design (libcpp/directives.cc): ----- void do_warning (cpp_reader *pfile) { /* We want #warning diagnostics to be emitted in system headers too. */ do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, CPP_W_WARNING_DIRECTIVE, 1); } ----- We do not issue #pragma GCC warning in system headers, because we use CPP_DL_WARNING instead of CPP_DL_WARNING_SYSHDR. I don't know if this is intentional or just the way it ended up. For warning3, the only reason it was output before my patch was that GCC didn't realize that it was dealing with a system header location; r15-4505 fixed that and led to the warning being suppressed as designed. The way things are currently meant to work, is that warnings do not get issued if they come from expanding macros that were defined in a system header file. This is intentional, e.g. here (gcc/input.h): ----- /* Return a positive value if LOCATION is the locus of a token that is located in a system header, O otherwise. It returns 1 if LOCATION is the locus of a token that is located in a system header, and 2 if LOCATION is the locus of a token located in a C system header that therefore needs to be extern "C" protected in C++. Note that this function returns 1 if LOCATION belongs to a token that is part of a macro replacement-list defined in a system header, but expanded in a non-system file. */ inline int in_system_header_at (location_t loc) { return linemap_location_in_system_header_p (line_table, loc); } ----- PR 7263 seems to embody a bunch of work to make sure macros in system headers work this way. I am concerned though that this change may feel like a downgrade, even though it only worked by chance previously? Is it surprising that you can't define a macro in a system header that can be used to generate warnings? I also wonder if it makes sense that #warning and "#pragma GCC warning" work differently in this respect. If "#pragma GCC warning" were changed to use CPP_DL_WARNING_SYSHDR as #warning does, then they would be consistent, and also the behavior incidentally changed by r15-4505 would go back to how it was in GCC 14. This could potentially lead to many other problems from code assuming the current behavior, though.