From e281ccc6e5c7bc85ccf49ae4ddd10198b34ae88f Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Tue, 13 Jan 2004 02:52:37 +0000 Subject: 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 --- gcc/ChangeLog | 9 ++++ gcc/c-decl.c | 81 +++++++++++++++++++++-------------- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/gcc.dg/typedef-redecl.c | 6 +++ gcc/testsuite/gcc.dg/typedef-redecl.h | 7 +++ 5 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/typedef-redecl.c create mode 100644 gcc/testsuite/gcc.dg/typedef-redecl.h diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3bc907ebeae..5f4a76d458f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-01-12 Zack Weinberg + + 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 * varray.h (VARRAY_POP): Add checking variant, aborts on underflow. 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 + + PR 13656 + * gcc.dg/typedef-redecl.c: New test case. + * gcc.dg/typedef-redecl.h: New support file. + 2004-01-13 Jan Hubicka * 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 , + 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 , + reduced from glibc. */ + +#pragma GCC system_header +typedef int x; +typedef int x; -- cgit v1.2.3