https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81795
Bug ID: 81795 Summary: Stray "originally defined here" when using -Wc++-compat with #pragma GCC diagnostic push/pop Product: gcc Version: 8.0 Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: egallager at gcc dot gnu.org Target Milestone: --- Host: i386-apple-darwin9.8.0 Target: i386-apple-darwin9.8.0 Build: i386-apple-darwin9.8.0 Let's say I have source like this: $ cat originally_defined_here0.c struct debug_type { int foo; }; typedef struct debug_type *debug_type; debug_type dt0; debug_type dt1; $ /usr/local/bin/gcc -c -Wc++-compat originally_defined_here0.c originally_defined_here0.c:4:28: warning: using ‘debug_type’ as both a typedef and a tag is invalid in C++ [-Wc++-compat] typedef struct debug_type *debug_type; ^~~~~~~~~~ originally_defined_here0.c:2:8: note: originally defined here struct debug_type { int foo; }; ^~~~~~~~~~ $ I want to avoid this warning but keep using the flag in general when compiling, so I use #pragma GCC diagnostic push/pop to avoid it: $ cat originally_defined_here1.c struct debug_type { int foo; }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++-compat" typedef struct debug_type *debug_type; debug_type dt0; #pragma GCC diagnostic pop debug_type dt1; $ This silences the warning, but there's still a stray note left behind: $ /usr/local/bin/gcc -c -Wc++-compat originally_defined_here1.c originally_defined_here1.c:2:8: note: originally defined here struct debug_type { int foo; }; ^~~~~~~~~~ $ The stray note remains even when moving the first pragma above where the struct is originally defined. Grepping the gcc sources for "originally defined here" shows that there's 4 inform calls where the message comes from in gcc/c/c-decl.c, 2 of which follow warning_at calls with OPT_Wc___compat. The inform calls are guarded by: if (b->locus != UNKNOWN_LOCATION) and that's it. warning_at returns true if the warning was printed, and false if it was inhibited, so shouldn't the calls to inform have a check against the return value of warning_at added to their guarding conditions, too? i.e. something like this: bool warned = warning_at (loc, OPT_Wc___compat, ("using %qD as both a typedef and a tag is " "invalid in C++"), b->decl); if ((b->locus != UNKNOWN_LOCATION) && warned) inform (b->locus, "originally defined here");