This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch for tag and enum redeclarations


This patch started out as fixing bug 17188, where redefinitions of
empty structs (a GNU extension) were not diagnosed because TYPE_FIELDS
was used to check for a struct having been previously defined but was
NULL for empty structs.  Testcase writing showed that not only were
there more cases not diagnosed than shown in that bug report, but the
diagnostics for various cases of nested redefinitions of tags and
enumerators were missing in some cases, so this patch fixes the other
problems in this area.

Incidentally, C_TYPE_BEING_DEFINED, which this patch causes to be used
again, was long being set with no uses (there was a single use in 2.x,
conditioned out with #if 0, back to 2.0).  It never gets reset when
the type has finished being defined, but this does not cause problems
as other diagnostics apply in that case.

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
  http://www.srcf.ucam.org/~jsm28/gcc/#c90status - status of C90 for GCC 4.0
    jsm@polyomino.org.uk (personal mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

2004-09-24  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/17188
	* c-decl.c (diagnose_mismatched_decls): Check for duplicate
	declarations of enumerators.
	(start_struct): Check TYPE_SIZE rather than TYPE_FIELDS to check
	for redefinition.  Check for nested redefinition.
	(finish_struct): Don't check for nested redefinition.
	(start_enum): Check for nested redefinition.

testsuite:
2004-09-24  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/17188
	* gcc.dg/nested-redef-1.c, gcc.dg/pr17188-1.c: New tests.
	* gcc.dg/decl-3.c: Adjust expected message.

diff -rupN GCC.orig/gcc/c-decl.c GCC/gcc/c-decl.c
--- GCC.orig/gcc/c-decl.c	2004-09-22 08:40:40.000000000 +0000
+++ GCC/gcc/c-decl.c	2004-09-23 22:28:49.000000000 +0000
@@ -1145,6 +1145,15 @@ diagnose_mismatched_decls (tree newdecl,
       return false;
     }
 
+  /* Enumerators have no linkage, so may only be declared once in a
+     given scope.  */
+  if (TREE_CODE (olddecl) == CONST_DECL)
+    {
+      error ("%Jredeclaration of enumerator %qD", newdecl, newdecl);
+      locate_old_decl (olddecl, error);
+      return false;
+    }
+
   if (!comptypes (oldtype, newtype))
     {
       if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -4910,13 +4919,22 @@ start_struct (enum tree_code code, tree 
     ref = lookup_tag (code, name, 1);
   if (ref && TREE_CODE (ref) == code)
     {
-      if (TYPE_FIELDS (ref))
+      if (TYPE_SIZE (ref))
         {
 	  if (code == UNION_TYPE)
 	    error ("redefinition of %<union %s%>", IDENTIFIER_POINTER (name));
           else
 	    error ("redefinition of %<struct %s%>", IDENTIFIER_POINTER (name));
 	}
+      else if (C_TYPE_BEING_DEFINED (ref))
+	{
+	  if (code == UNION_TYPE)
+	    error ("nested redefinition of %<union %s%>",
+		   IDENTIFIER_POINTER (name));
+          else
+	    error ("nested redefinition of %<struct %s%>",
+		   IDENTIFIER_POINTER (name));
+	}
     }
   else
     {
@@ -5123,11 +5141,6 @@ finish_struct (tree t, tree fieldlist, t
       if (C_DECL_VARIABLE_SIZE (x))
 	C_TYPE_VARIABLE_SIZE (t) = 1;
 
-      /* Detect invalid nested redefinition.  */
-      if (TREE_TYPE (x) == t)
-	error ("nested redefinition of %qs",
-	       IDENTIFIER_POINTER (TYPE_NAME (t)));
-
       if (DECL_INITIAL (x))
 	{
 	  unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
@@ -5330,6 +5343,9 @@ start_enum (tree name)
       pushtag (name, enumtype);
     }
 
+  if (C_TYPE_BEING_DEFINED (enumtype))
+    error ("nested redefinition of %<enum %s%>", IDENTIFIER_POINTER (name));
+
   C_TYPE_BEING_DEFINED (enumtype) = 1;
 
   if (TYPE_VALUES (enumtype) != 0)
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/decl-3.c GCC/gcc/testsuite/gcc.dg/decl-3.c
--- GCC.orig/gcc/testsuite/gcc.dg/decl-3.c	2004-01-11 12:56:59.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/decl-3.c	2004-09-24 16:01:55.000000000 +0000
@@ -2,4 +2,4 @@
 /* { dg-do compile } */
 
 enum { CODES }; /* { dg-error "previous definition" } */
-enum { CODES }; /* { dg-error "conflicting types" } */
+enum { CODES }; /* { dg-error "conflicting types|redeclaration of enumerator" } */
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/nested-redef-1.c GCC/gcc/testsuite/gcc.dg/nested-redef-1.c
--- GCC.orig/gcc/testsuite/gcc.dg/nested-redef-1.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/nested-redef-1.c	2004-09-24 13:04:50.000000000 +0000
@@ -0,0 +1,44 @@
+/* Test diagnosis of nested tag redefinitions.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct s0 {
+  struct s0 { int a; } x; /* { dg-error "error: nested redefinition of 'struct s0'" } */
+};
+
+struct s1 {
+  const struct s1 { int b; } x; /* { dg-error "error: nested redefinition of 'struct s1'" } */
+};
+
+struct s2 {
+  struct s2 { int c; } *x; /* { dg-error "error: nested redefinition of 'struct s2'" } */
+};
+
+struct s3 {
+  struct s4 {
+    struct s5 {
+      struct s3 { int a; } **x; /* { dg-error "error: nested redefinition of 'struct s3'" } */
+    } y;
+  } z;
+};
+
+struct s6;
+struct s6 { struct s6 *p; };
+
+union u0 {
+  union u0 { int c; } *x; /* { dg-error "error: nested redefinition of 'union u0'" } */
+};
+
+enum e0 {
+  E0 = sizeof(enum e0 { E1 }) /* { dg-error "error: nested redefinition of 'enum e0'" } */
+};
+
+enum e1 {
+  E2 = sizeof(enum e2 { E2 }), /* { dg-error "error: redeclaration of enumerator 'E2'" } */
+  /* { dg-error "previous definition" "previous E2" { target *-*-* } 38 } */
+  E3
+};
+
+enum e3;
+enum e3 { E4 = 0 };
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/pr17188-1.c GCC/gcc/testsuite/gcc.dg/pr17188-1.c
--- GCC.orig/gcc/testsuite/gcc.dg/pr17188-1.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/pr17188-1.c	2004-09-23 22:00:02.000000000 +0000
@@ -0,0 +1,31 @@
+/* A redefinition of an empty struct should be diagnosed the same as a
+   redefinition of any other tag, but formerly only s2 and s4 were
+   diagnosed.  Bug 17188.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct s0 { };
+struct s0;
+struct s0 { }; /* { dg-error "error: redefinition of 'struct s0'" } */
+
+struct s1 { };
+struct s1 { }; /* { dg-error "error: redefinition of 'struct s1'" } */
+
+struct s2 { int a : 1; };
+struct s2 { int a : 1; }; /* { dg-error "error: redefinition of 'struct s2'" } */
+
+struct s3 { };
+struct s3 { int a : 1; }; /* { dg-error "error: redefinition of 'struct s3'" } */
+
+struct s4 { int a : 1; };
+struct s4 { }; /* { dg-error "error: redefinition of 'struct s4'" } */
+
+struct s5 { int a : 1; };
+struct s5;
+
+struct s6;
+struct s6 { int a : 1; };
+
+struct s7;
+struct s7 { };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]