From 99769e7fb6ed153a53174b7f08415eee347655f0 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 8 Aug 2019 17:12:05 +0000 Subject: [PATCH] [C] Fix bogus nested enum error message MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit For: enum a { A }; enum a { B }; we emit a bogus error about nested definitions before the real error: foo.c:2:6: error: nested redefinition of ‘enum a’ 2 | enum a { B }; | ^ foo.c:2:6: error: redeclaration of ‘enum a’ foo.c:1:6: note: originally defined here 1 | enum a { A }; | ^ This is because we weren't clearing C_TYPE_BEING_DEFINED once the definition was over. I think it's OK to clear C_TYPE_BEING_DEFINED even for a definition that actually is nested (and so whose outer definition is still open), since we'll already have given an error by then. It means that second and subsequent attempts to define a nested enum will usually get the redeclaration error instead of the nested error, but that seems just as accurate (nested_first and nested_second in the test). The only exception is if the first nested enum was also invalid by being empty, but then the enum as a whole has already produced two errors (nested_empty in the test). 2019-08-08 Richard Sandiford gcc/c/ * c-decl.c (finish_enum): Clear C_TYPE_BEING_DEFINED. gcc/testsuite/ * gcc.dg/pr79983.c (enum E): Don't allow an error about nested definitions. * gcc.dg/enum-redef-1.c: New test. From-SVN: r274213 --- gcc/c/ChangeLog | 4 ++++ gcc/c/c-decl.c | 2 ++ gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/gcc.dg/enum-redef-1.c | 29 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr79983.c | 2 +- 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/enum-redef-1.c diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 4944696a1d6..533aebc40c3 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,7 @@ +2019-08-08 Richard Sandiford + + * c-decl.c (finish_enum): Clear C_TYPE_BEING_DEFINED. + 2019-08-08 Jakub Jelinek * c-typeck.c (c_finish_omp_clauses): For C_ORT_OMP diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index f85f481eb51..9859cc7b22f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -8781,6 +8781,8 @@ finish_enum (tree enumtype, tree values, tree attributes) && !in_sizeof && !in_typeof && !in_alignof) struct_parse_info->struct_types.safe_push (enumtype); + C_TYPE_BEING_DEFINED (enumtype) = 0; + return enumtype; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ed8aabaec8..a9f6c54aa84 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-08-08 Richard Sandiford + + * gcc.dg/pr79983.c (enum E): Don't allow an error about nested + definitions. + * gcc.dg/enum-redef-1.c: New test. + 2019-08-08 Marek Polacek PR c++/87519 - bogus warning with -Wsign-conversion. diff --git a/gcc/testsuite/gcc.dg/enum-redef-1.c b/gcc/testsuite/gcc.dg/enum-redef-1.c new file mode 100644 index 00000000000..b3fa6cbf8f1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/enum-redef-1.c @@ -0,0 +1,29 @@ +enum a { A }; +enum a { B }; /* { dg-bogus "nested redefinition" } */ +/* { dg-error "redeclaration of 'enum a'" "" { target *-*-* } .-1 } */ + +enum empty {}; /* { dg-error "empty enum is invalid" } */ +enum empty {}; /* { dg-bogus "nested redefinition" } */ +/* { dg-error "empty enum is invalid" "" { target *-*-* } .-1 } */ + +enum nested_first { + C1 = sizeof(enum nested_first { C1a }), /* { dg-error "nested redefinition of 'enum nested_first" } */ + C2 = sizeof(enum nested_first { C2a }) /* { dg-error "redeclaration of 'enum nested_first'" "" } */ +}; + +enum nested_second { + D1, + D2 = sizeof(enum nested_second { D2a }), /* { dg-error "nested redefinition of 'enum nested_second" } */ + D3 = sizeof(enum nested_second { D3a }) /* { dg-error "redeclaration of 'enum nested_second'" "" } */ +}; + +enum nested_repeat { E }; +enum nested_repeat { /* { dg-error "redeclaration of 'enum nested_repeat'" "" } */ + F = sizeof(enum nested_repeat { Fa }) /* { dg-error "nested redefinition of 'enum nested_repeat" } */ +}; + +enum nested_empty { + G1 = sizeof(enum nested_empty {}), /* { dg-error "nested redefinition of 'enum nested_empty" } */ + /* { dg-error "empty enum is invalid" "" { target *-*-* } .-1 } */ + G2 = sizeof(enum nested_empty { G2a }) +}; diff --git a/gcc/testsuite/gcc.dg/pr79983.c b/gcc/testsuite/gcc.dg/pr79983.c index 84aae691318..1e292d42108 100644 --- a/gcc/testsuite/gcc.dg/pr79983.c +++ b/gcc/testsuite/gcc.dg/pr79983.c @@ -8,7 +8,7 @@ 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'" } */ +enum E { D, F }; /* { dg-error "redeclaration of 'enum E'" } */ union U; union U { int i; }; /* { dg-message "originally defined here" } */ -- 2.30.2