https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69126
David Malcolm <dmalcolm at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED --- Comment #25 from David Malcolm <dmalcolm at gcc dot gnu.org> --- Stephan provided me with a tarball of his reproducer (thanks!), and I'm able to reproduce this locally. The root cause is a bug in linemap_compare_locations. (gdb) call inform (pre, "pre") test.cc:8:16: note: pre #define IGNORE _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") ^ test.cc:8:16: note: in definition of macro ‘IGNORE’ #define IGNORE _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") ^~~~~~~ (gdb) call inform (post, "post") test.cc:12:5: note: post f(); ^ After macro expansion, we have (at the end of linemap_compare_locations): (gdb) p /x l0 $13 = 0x800101ec (gdb) p /x l1 $14 = 0x50684c05 and hence: (gdb) p /x l1 - l0 $23 = 0xd0674a19 it's effectively negative, and so before_p is false. But this is wrong: l0 is an ad-hoc loc, whereas l1 is a non-ad-hoc loc. It's clearly insane to treat all ad-hoc locations as being later than all non-ad-hoc locations. The fix is simple: resolve ads-hoc locations at the end of linemap_compare_locations. For this bug to occur, we need a location for the macro name that's an ad-hoc location, and a location for the diagnostic that's *not* an ad-hoc location. The reason it triggered for Stephan is that the sheer quantity of code in his reproducer meant that both locations in question were above LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES (but below LINE_MAP_MAX_LOCATION_WITH_COLS), so range-packing was disabled, in particular for the "IGNORE" macro. I can reproduce it trivially by using a macro name that's >=32 characters (thus forcing the use of an ad-hoc location): /* { dg-options "-Wdeprecated-declarations" } */ #define IGNORE_WHERE_MACRO_IS_LONGER_THAN_31_CHARS _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") __attribute__((deprecated)) void f(); int main() { IGNORE_WHERE_MACRO_IS_LONGER_THAN_31_CHARS f(); } I have a patch that seems to work for this test case; am testing it more thoroughly now.