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 bug 21342


This patch fixes bug 21342, a regression in the diagnosis of some
obscure cases of incompatible declarations in separate scopes, fallout
from my fix of bug 13801.  In the course of testing an earlier version
of this patch I found another more serious problem which was also
fallout from that fix and is also fixed by this patch: an ICE on code
of uncertain validity shown in the new testcase redecl-15.c.  (This is
not valid code in standard C, but I think the conclusion in GNU C is
that we accept declarations to return void following an implicit
declaration, with a pedwarn, though you need to go back to 3.0 to find
a version which accepted this particular testcase in that way.)

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  Applied
to mainline and 4.0 branch.

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    joseph@codesourcery.com (CodeSourcery mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

2005-05-10  Joseph S. Myers  <joseph@codesourcery.com>

	PR c/21342
	* c-decl.c (pushdecl): When there is a declaration in the current
	scope and the declarations are external linkage, check for
	compatibility with the type in the external scope and update the
	type in the external scope with the composite type information.
	Do not form a composite type of the new type and the visible type
	if they are incompatible.

testsuite:
2005-05-10  Joseph S. Myers  <joseph@codesourcery.com>

	PR c/21342
	* gcc.dg/redecl-11.c, gcc.dg/redecl-12.c, gcc.dg/redecl-13.c,
	gcc.dg/redecl-14.c, gcc.dg/redecl-15.c: New tests.

diff -rupN GCC.orig/gcc/c-decl.c GCC/gcc/c-decl.c
--- GCC.orig/gcc/c-decl.c	2005-05-04 10:38:59.000000000 +0000
+++ GCC/gcc/c-decl.c	2005-05-10 00:52:38.000000000 +0000
@@ -2029,11 +2029,52 @@ pushdecl (tree x)
   b = I_SYMBOL_BINDING (name);
   if (b && B_IN_SCOPE (b, scope))
     {
+      struct c_binding *b_ext, *b_use;
+      tree type = TREE_TYPE (x);
+      tree visdecl = b->decl;
+      tree vistype = TREE_TYPE (visdecl);
       if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
 	  && COMPLETE_TYPE_P (TREE_TYPE (x)))
 	b->inner_comp = false;
-      if (duplicate_decls (x, b->decl))
-	return b->decl;
+      b_use = b;
+      b_ext = b;
+      /* If this is an external linkage declaration, we should check
+	 for compatibility with the type in the external scope before
+	 setting the type at this scope based on the visible
+	 information only.  */
+      if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl))
+	{
+	  while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+	    b_ext = b_ext->shadowed;
+	  if (b_ext)
+	    {
+	      b_use = b_ext;
+	      if (b_use->type)
+		TREE_TYPE (b_use->decl) = b_use->type;
+	    }
+	}
+      if (duplicate_decls (x, b_use->decl))
+	{
+	  if (b_use != b)
+	    {
+	      /* Save the updated type in the external scope and
+		 restore the proper type for this scope.  */
+	      tree thistype;
+	      if (comptypes (vistype, type))
+		thistype = composite_type (vistype, type);
+	      else
+		thistype = TREE_TYPE (b_use->decl);
+	      b_use->type = TREE_TYPE (b_use->decl);
+	      if (TREE_CODE (b_use->decl) == FUNCTION_DECL
+		  && DECL_BUILT_IN (b_use->decl))
+		thistype
+		  = build_type_attribute_variant (thistype,
+						  TYPE_ATTRIBUTES
+						  (b_use->type));
+	      TREE_TYPE (b_use->decl) = thistype;
+	    }
+	  return b_use->decl;
+	}
       else
 	goto skip_external_and_shadow_checks;
     }
@@ -2120,7 +2161,15 @@ pushdecl (tree x)
 	  && duplicate_decls (x, b->decl))
 	{
 	  tree thistype;
-	  thistype = (vistype ? composite_type (vistype, type) : type);
+	  if (vistype)
+	    {
+	      if (comptypes (vistype, type))
+		thistype = composite_type (vistype, type);
+	      else
+		thistype = TREE_TYPE (b->decl);
+	    }
+	  else
+	    thistype = type;
 	  b->type = TREE_TYPE (b->decl);
 	  if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
 	    thistype
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/redecl-11.c GCC/gcc/testsuite/gcc.dg/redecl-11.c
--- GCC.orig/gcc/testsuite/gcc.dg/redecl-11.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/redecl-11.c	2005-05-09 22:29:01.000000000 +0000
@@ -0,0 +1,9 @@
+/* Some incompatible external linkage declarations were not diagnosed.
+   Bug 21342.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+int f(int (*)[]);
+void g() { int f(int (*)[2]); } /* { dg-error "error: previous declaration of 'f' was here" } */
+int f(int (*)[3]); /* { dg-error "error: conflicting types for 'f'" } */
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/redecl-12.c GCC/gcc/testsuite/gcc.dg/redecl-12.c
--- GCC.orig/gcc/testsuite/gcc.dg/redecl-12.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/redecl-12.c	2005-05-09 22:29:30.000000000 +0000
@@ -0,0 +1,9 @@
+/* Some incompatible external linkage declarations were not diagnosed.
+   Bug 21342.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+extern int a[];
+void f(void) { extern int a[]; extern int a[10]; } /* { dg-error "error: previous declaration of 'a' was here" } */
+extern int a[5]; /* { dg-error "error: conflicting types for 'a'" } */
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/redecl-13.c GCC/gcc/testsuite/gcc.dg/redecl-13.c
--- GCC.orig/gcc/testsuite/gcc.dg/redecl-13.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/redecl-13.c	2005-05-09 22:30:06.000000000 +0000
@@ -0,0 +1,9 @@
+/* Some incompatible external linkage declarations were not diagnosed.
+   Bug 21342.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+extern int a[];
+void f(void) { extern int a[10]; } /* { dg-error "error: previous declaration of 'a' was here" } */
+extern int a[5]; /* { dg-error "error: conflicting types for 'a'" } */
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/redecl-14.c GCC/gcc/testsuite/gcc.dg/redecl-14.c
--- GCC.orig/gcc/testsuite/gcc.dg/redecl-14.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/redecl-14.c	2005-05-09 22:10:49.000000000 +0000
@@ -0,0 +1,22 @@
+/* Some incompatible external linkage declarations were not diagnosed.
+   Bug 21342.  Test type in inner scope is correct.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef int IA[];
+typedef int IA5[5];
+typedef IA *IAP;
+typedef IA5 *IA5P;
+extern IAP a[];
+void
+f (void)
+{
+  {
+    extern IA5P a[];
+    sizeof (*a[0]);
+  }
+  extern IAP a[];
+  extern IAP a[5];
+  sizeof (*a[0]); /* { dg-error "error: invalid application of 'sizeof' to incomplete type 'IA'" } */
+}
diff -rupN GCC.orig/gcc/testsuite/gcc.dg/redecl-15.c GCC/gcc/testsuite/gcc.dg/redecl-15.c
--- GCC.orig/gcc/testsuite/gcc.dg/redecl-15.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.dg/redecl-15.c	2005-05-10 00:48:37.000000000 +0000
@@ -0,0 +1,14 @@
+/* Test for ICE with redeclaration in inner scope which is accepted
+   despite incompatible type.  */
+/* Origin: Joseph Myers <joseph@codesourcery.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+f (void)
+{
+  g(); /* { dg-warning "warning: previous implicit declaration of 'g' was here" } */
+  {
+    void g(); /* { dg-warning "warning: conflicting types for 'g'" } */
+  }
+}


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