re PR c/13656 (ICE after redeclaring size_t in the system headers)
authorZack Weinberg <zack@codesourcery.com>
Tue, 13 Jan 2004 02:52:37 +0000 (02:52 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Tue, 13 Jan 2004 02:52:37 +0000 (02:52 +0000)
PR 13656
* c-decl.c (diagnose_mismatched_decls): Whenever newtype or
oldtype is set, set *newtypep or *oldtypep too.  Do not set
them at the very end.
(validate_proto_after_old_defn): Restructure for comprehensibility;
make error messages clearer.
testsuite:
* gcc.dg/typedef-redecl.c: New test case.
* gcc.dg/typedef-redecl.h: New support file.

From-SVN: r75787

gcc/ChangeLog
gcc/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/typedef-redecl.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/typedef-redecl.h [new file with mode: 0644]

index 3bc907ebeaefc0548267946425b99ac82578e9b1..5f4a76d458f479c894c9d8d7d41c7e91b052bcb4 100644 (file)
@@ -1,3 +1,12 @@
+2004-01-12  Zack Weinberg  <zack@codesourcery.com>
+
+       PR 13656
+       * c-decl.c (diagnose_mismatched_decls): Whenever newtype or
+       oldtype is set, set *newtypep or *oldtypep too.  Do not set
+       them at the very end.
+       (validate_proto_after_old_defn): Restructure for comprehensibility;
+       make error messages clearer.
+
 2004-01-12  Zack Weinberg  <zack@codesourcery.com>
 
        * varray.h (VARRAY_POP): Add checking variant, aborts on underflow.
index 2513b4f820deb6a3f2651c6f17a61db6747e3a1e..77f6cfbb69f83ca71450f943d7d7259909d68037 100644 (file)
@@ -839,42 +839,59 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
 static bool
 validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
 {
-  tree type, parm;
-  int nargs;
-  /* Prototype decl follows defn w/o prototype.  */
-
-  for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
-        type = TYPE_ARG_TYPES (newtype),
-        nargs = 1;
-       ;
-       parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
-    {
-      if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
-         && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+  tree newargs, oldargs;
+  int i;
+
+  /* ??? Elsewhere TYPE_MAIN_VARIANT is not used in this context.  */
+#define END_OF_ARGLIST(t) (TYPE_MAIN_VARIANT (t) == void_type_node)
+
+  oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype);
+  newargs = TYPE_ARG_TYPES (newtype);
+  i = 1;
+
+  for (;;)
+    {
+      tree oldargtype = TREE_VALUE (oldargs);
+      tree newargtype = TREE_VALUE (newargs);
+
+      if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
+       break;
+
+      /* Reaching the end of just one list means the two decls don't
+        agree on the number of arguments.  */
+      if (END_OF_ARGLIST (oldargtype))
        {
-         /* End of list.  */
-         warning ("%Jprototype for '%D' follows non-prototype definition",
-                  newdecl, newdecl);
-         return true;
+         error ("%Jprototype for '%D' declares more arguments "
+                "than previous old-style definition", newdecl, newdecl);
+         return false;
        }
-
-      if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
-         || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+      else if (END_OF_ARGLIST (newargtype))
        {
-         error ("%Jprototype for '%D' with different number of arguments "
-                "follows non-prototype definition", newdecl, newdecl);
+         error ("%Jprototype for '%D' declares fewer arguments "
+                "than previous old-style definition", newdecl, newdecl);
          return false;
        }
-      /* Type for passing arg must be consistent
-        with that declared for the arg.  */
-      if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type),
-                      COMPARE_STRICT))
+
+      /* Type for passing arg must be consistent with that declared
+        for the arg.  */
+      else if (! comptypes (oldargtype, newargtype, COMPARE_STRICT))
        {
-         error ("%Jprototype for '%D' with incompatible argument %d "
-                "follows non-prototype definition", newdecl, newdecl, nargs);
+         error ("%Jprototype for '%D' declares arg %d with incompatible type",
+                newdecl, newdecl, i);
          return false;
        }
+
+      oldargs = TREE_CHAIN (oldargs);
+      newargs = TREE_CHAIN (newargs);
+      i++;
     }
+
+  /* If we get here, no errors were found, but do issue a warning
+     for this poor-style construct.  */
+  warning ("%Jprototype for '%D' follows non-prototype definition",
+          newdecl, newdecl);
+  return true;
+#undef END_OF_ARGLIST
 }
 
 /* Subroutine of diagnose_mismatched_decls.  Report the location of DECL,
@@ -913,8 +930,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
      the previous decl - we're in an error cascade already.  */
   if (olddecl == error_mark_node || newdecl == error_mark_node)
     return false;
-  oldtype = TREE_TYPE (olddecl);
-  newtype = TREE_TYPE (newdecl);
+  *oldtypep = oldtype = TREE_TYPE (olddecl);
+  *newtypep = newtype = TREE_TYPE (newdecl);
   if (oldtype == error_mark_node || newtype == error_mark_node)
     return false;
 
@@ -946,7 +963,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          tree trytype = match_builtin_function_types (newtype, oldtype);
 
          if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
-           oldtype = trytype;
+           *oldtypep = oldtype = trytype;
          else
            {
              /* If types don't match for a built-in, throw away the
@@ -978,7 +995,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        {
          pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
          /* Make sure we keep void as the return type.  */
-         TREE_TYPE (newdecl) = newtype = oldtype;
+         TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
          C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
          pedwarned = true;
        }
@@ -1230,8 +1247,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (warned || pedwarned)
     locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
 
-  *newtypep = newtype;
-  *oldtypep = oldtype;
   return true;
 }
 
index 2e48b75625948e567516c92d92b466b3c1883aa1..14e0a2b320ac24f5288c17e899acc2f9956b580e 100644 (file)
@@ -1,3 +1,9 @@
+2004-01-12  Zack Weinberg  <zack@codesourcery.com>
+
+       PR 13656
+       * gcc.dg/typedef-redecl.c: New test case.
+       * gcc.dg/typedef-redecl.h: New support file.
+
 2004-01-13  Jan Hubicka  <jh@suse.cz>
 
        * gcc.dg/always_inline.c: New test.
diff --git a/gcc/testsuite/gcc.dg/typedef-redecl.c b/gcc/testsuite/gcc.dg/typedef-redecl.c
new file mode 100644 (file)
index 0000000..8ac5282
--- /dev/null
@@ -0,0 +1,6 @@
+/* Redeclaration of typedef (invalid but accepted in system headers)
+   causes ICE; PR 13656.  Test case by Richard Sandiford <rsandifo@redhat.com>,
+   reduced from glibc.  */
+
+#include "typedef-redecl.h"
+x a;
diff --git a/gcc/testsuite/gcc.dg/typedef-redecl.h b/gcc/testsuite/gcc.dg/typedef-redecl.h
new file mode 100644 (file)
index 0000000..9fa7da0
--- /dev/null
@@ -0,0 +1,7 @@
+/* Redeclaration of typedef (invalid but accepted in system headers)
+   causes ICE; PR 13656.  Test case by Richard Sandiford <rsandifo@redhat.com>,
+   reduced from glibc.  */
+
+#pragma GCC system_header
+typedef int x;
+typedef int x;