diff mbox series

[C] Fix bogus nested enum error message

Message ID mptk1bsc7hd.fsf@arm.com
State New
Headers show
Series [C] Fix bogus nested enum error message | expand

Commit Message

Richard Sandiford Aug. 5, 2019, 9 a.m. UTC
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).

Tested on aarch64-linux-gnu, armeb-eabi and x86_64-linux-gnu.
OK to install?

Richard


2019-08-05  Richard Sandiford  <richard.sandiford@arm.com>

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.

Comments

Jeff Law Aug. 8, 2019, 4:48 p.m. UTC | #1
On 8/5/19 3:00 AM, Richard Sandiford wrote:
> 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).
> 
> Tested on aarch64-linux-gnu, armeb-eabi and x86_64-linux-gnu.
> OK to install?
> 
> Richard
> 
> 
> 2019-08-05  Richard Sandiford  <richard.sandiford@arm.com>
> 
> 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.
OK
jeff
diff mbox series

Patch

Index: gcc/c/c-decl.c
===================================================================
--- gcc/c/c-decl.c	2019-07-29 09:39:47.630182350 +0100
+++ gcc/c/c-decl.c	2019-08-05 09:58:36.509124799 +0100
@@ -8781,6 +8781,8 @@  finish_enum (tree enumtype, tree values,
       && !in_sizeof && !in_typeof && !in_alignof)
     struct_parse_info->struct_types.safe_push (enumtype);
 
+  C_TYPE_BEING_DEFINED (enumtype) = 0;
+
   return enumtype;
 }
 
Index: gcc/testsuite/gcc.dg/pr79983.c
===================================================================
--- gcc/testsuite/gcc.dg/pr79983.c	2019-03-08 18:15:07.100852863 +0000
+++ gcc/testsuite/gcc.dg/pr79983.c	2019-08-05 09:58:36.509124799 +0100
@@ -8,7 +8,7 @@  struct S { int i, j; }; /* { dg-error "r
 
 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" } */
Index: gcc/testsuite/gcc.dg/enum-redef-1.c
===================================================================
--- /dev/null	2019-07-30 08:53:31.317691683 +0100
+++ gcc/testsuite/gcc.dg/enum-redef-1.c	2019-08-05 09:58:36.509124799 +0100
@@ -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 })
+};