aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zack@codesourcery.com>2004-01-13 02:52:37 +0000
committerZack Weinberg <zack@codesourcery.com>2004-01-13 02:52:37 +0000
commite281ccc6e5c7bc85ccf49ae4ddd10198b34ae88f (patch)
tree6afc5d8ff769e05c6c4b584eb8acf804d26ac923
parent65da2b2aebe32fd42b1db0f103e0aec4f2d843b5 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@75787 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/c-decl.c81
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/typedef-redecl.c6
-rw-r--r--gcc/testsuite/gcc.dg/typedef-redecl.h7
5 files changed, 76 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3bc907ebeae..5f4a76d458f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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.
(VARRAY_TOP): Use VARRAY_CHECK so the access is bounds-checked.
* varray.c: No need to prototype error.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index 2513b4f820d..77f6cfbb69f 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2e48b756259..14e0a2b320a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..8ac5282fb70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/typedef-redecl.c
@@ -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
index 00000000000..9fa7da05db0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/typedef-redecl.h
@@ -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;