This patch brings better enum and struct redefinition diagnostic. In particular, we'll now point to the first definition in the "originally defined here" note, not to the forward declaration.
Now, you could argue that we don't have to be setting the location by lookup_tag at all, because we should always have the location in TYPE_STUB_DECL, and then we could get rid of that lookup_tag parameter completely, but I think this is good enough for now. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2017-06-06 Marek Polacek <pola...@redhat.com> PR c/79983 * c-decl.c (start_struct): Use the location of TYPE_STUB_DECL of ref. (start_enum): Use the location of TYPE_STUB_DECL of enumtype. * gcc.dg/pr79983.c: New test. diff --git gcc/c/c-decl.c gcc/c/c-decl.c index f2b8096..3a0a4f5 100644 --- gcc/c/c-decl.c +++ gcc/c/c-decl.c @@ -7453,6 +7453,9 @@ start_struct (location_t loc, enum tree_code code, tree name, ref = lookup_tag (code, name, true, &refloc); if (ref && TREE_CODE (ref) == code) { + if (TYPE_STUB_DECL (ref)) + refloc = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (ref)); + if (TYPE_SIZE (ref)) { if (code == UNION_TYPE) @@ -8185,7 +8188,10 @@ start_enum (location_t loc, struct c_enum_contents *the_enum, tree name) /* Update type location to the one of the definition, instead of e.g. a forward declaration. */ else if (TYPE_STUB_DECL (enumtype)) - DECL_SOURCE_LOCATION (TYPE_STUB_DECL (enumtype)) = loc; + { + enumloc = DECL_SOURCE_LOCATION (TYPE_STUB_DECL (enumtype)); + DECL_SOURCE_LOCATION (TYPE_STUB_DECL (enumtype)) = loc; + } if (C_TYPE_BEING_DEFINED (enumtype)) error_at (loc, "nested redefinition of %<enum %E%>", name); diff --git gcc/testsuite/gcc.dg/pr79983.c gcc/testsuite/gcc.dg/pr79983.c index e69de29..84aae69 100644 --- gcc/testsuite/gcc.dg/pr79983.c +++ gcc/testsuite/gcc.dg/pr79983.c @@ -0,0 +1,15 @@ +/* PR c/79983 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +struct S; +struct S { int i; }; /* { dg-message "originally defined here" } */ +struct S { int i, j; }; /* { dg-error "redefinition of 'struct S'" } */ + +enum E; +enum E { A, B, C }; /* { dg-message "originally defined here" } */ +enum E { D, F }; /* { dg-error "nested redefinition of 'enum E'|redeclaration of 'enum E'" } */ + +union U; +union U { int i; }; /* { dg-message "originally defined here" } */ +union U { int i; double d; }; /* { dg-error "redefinition of 'union U'" } */ Marek