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");

Reply via email to