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.

Reply via email to