https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60304
--- Comment #31 from Harald van Dijk <harald at gigawatt dot nl> --- (In reply to Jonathan Wakely from comment #30) > I'm curious why the preprocessed code in comment 28 doesn't warn, This was still bugging me, so I looked into it a little bit, and since I had trouble finding this written down somewhere I thought it would be worth including here. The line "# 2 "b.C" 3 4" means that what follows is line 2 of b.C, and b.C is a C system header. The relevant bits of GCC code to see this are https://github.com/gcc-mirror/gcc/blob/releases/gcc-10.2.0/libcpp/directives.c#L1061 https://github.com/gcc-mirror/gcc/blob/releases/gcc-10.2.0/libcpp/internal.h#L358 So this means that "false" is coming from a system header. It is: it is coming from the macro expansion of "false", and the macro definition was in a system header. So far, so good. However, during normal operation, with the integrated preprocessor, when a warning would be emitted in a system header, that get_location_for_expr_unwinding_for_system_header function added by the commit you were asking about, https://github.com/gcc-mirror/gcc/blob/releases/gcc-10.2.0/gcc/cp/call.c#L7146, would change the warning location to that of the macro expansion point, if the warning location was actually inside a macro definition from a system header. Such macro unwinding is not possible when the preprocessor is invoked separately, as this information is missing in the -E output. A non-system-header effect of this can be seen in this test: test.h: #define FALSE false test.cc: #include "test.h" void *p = FALSE; g++ -std=c++03 -c test.cc: In file included from test.cc:1: test.h:1:15: warning: converting ‘false’ to pointer type ‘void*’ [-Wconversion-null] 1 | #define FALSE false | ^~~~~ test.cc:2:11: note: in expansion of macro ‘FALSE’ 2 | void *p = FALSE; | ^~~~~ g++ -std=c++03 -c test.cc -save-temps test.cc:2:11: warning: converting ‘false’ to pointer type ‘void*’ [-Wconversion-null] 2 | void *p = FALSE; | ^~~~~ The addition of -save-temps causes the "note: in expansion of macro ‘FALSE’" to go missing, because the information needed to produce that note is gone by the time the warning is emitted: the macro expansion tracking is only available at preprocessing time. It was that macro expansion tracking functionality that GCC needs to determine that really, the warning should be treated as *not* coming from a system header, even though it really was. In short: I think there is no lingering bug here, this is just an unfortunate result of the current design. However, if you disagree, if you think the macro expansion tracking state should be included somehow in the preprocessor output so that the compiler always has access to it, I can report that as a new bug if you like.