OSDN Git Service

* c-common.h (objc_comptypes): Remove prototype.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 8b75ab7..8653d8f 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "input.h"
 #include "tm.h"
 #include "intl.h"
 #include "tree.h"
@@ -91,23 +92,29 @@ static tree enum_next_value;
 
 static int enum_overflow;
 
-/* These #defines are for clarity in working with the information block
-   returned by get_parm_info.  */
-#define ARG_INFO_PARMS(args)  TREE_PURPOSE(args)
-#define ARG_INFO_TAGS(args)   TREE_VALUE(args)
-#define ARG_INFO_TYPES(args)  TREE_CHAIN(args)
-#define ARG_INFO_OTHERS(args) TREE_TYPE(args)
-
 /* The file and line that the prototype came from if this is an
    old-style definition; used for diagnostics in
    store_parm_decls_oldstyle.  */
 
 static location_t current_function_prototype_locus;
 
+/* Whether this prototype was built-in.  */
+
+static bool current_function_prototype_built_in;
+
+/* The argument type information of this prototype.  */
+
+static tree current_function_prototype_arg_types;
+
 /* The argument information structure for the function currently being
    defined.  */
 
-static GTY(()) tree current_function_arg_info;
+static struct c_arg_info *current_function_arg_info;
+
+/* The obstack on which parser and related data structures, which are
+   not live beyond their top-level declaration or definition, are
+   allocated.  */
+struct obstack parser_obstack;
 
 /* The current statement tree.  */
 
@@ -150,6 +157,11 @@ static int warn_about_return_type;
 
 static int current_extern_inline;
 
+/* Nonzero when the current toplevel function contains a declaration
+   of a nested function which is never defined.  */
+
+static bool undef_nested_function;
+
 /* True means global_bindings_p should return false even if the scope stack
    says we are in file scope.  */
 bool c_override_global_bindings_to_false;
@@ -207,17 +219,17 @@ struct c_binding GTY((chain_next ("%h.prev")))
 #define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
 
 #define I_SYMBOL_BINDING(node) \
-  (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->symbol_binding)
+  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
 #define I_SYMBOL_DECL(node) \
  (I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
 
 #define I_TAG_BINDING(node) \
-  (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->tag_binding)
+  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
 #define I_TAG_DECL(node) \
  (I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
 
 #define I_LABEL_BINDING(node) \
-  (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->label_binding)
+  (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
 #define I_LABEL_DECL(node) \
  (I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
 
@@ -241,7 +253,7 @@ extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 
 union lang_tree_node
   GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *) TREE_CHAIN (&%h.generic)")))
 {
   union tree_node GTY ((tag ("0"),
                        desc ("tree_node_structure (&%h)")))
@@ -400,8 +412,10 @@ static GTY(()) tree static_dtors;
 /* Forward declarations.  */
 static tree lookup_name_in_scope (tree, struct c_scope *);
 static tree c_make_fname_decl (tree, int);
-static tree grokdeclarator (tree, tree, enum decl_context, bool, tree *);
-static tree grokparms (tree, bool);
+static tree grokdeclarator (const struct c_declarator *,
+                           struct c_declspecs *,
+                           enum decl_context, bool, tree *);
+static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
 \f
 /* States indicating how grokdeclarator() should handle declspecs marked
@@ -477,7 +491,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
     case ERROR_MARK:     here = &I_SYMBOL_BINDING (name);  break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   /* Locate the appropriate place in the chain of shadowed decls
@@ -518,12 +532,12 @@ c_finish_incomplete_decl (tree decl)
       tree type = TREE_TYPE (decl);
       if (type != error_mark_node
          && TREE_CODE (type) == ARRAY_TYPE
-         && ! DECL_EXTERNAL (decl)
+         && !DECL_EXTERNAL (decl)
          && TYPE_DOMAIN (type) == 0)
        {
-         warning ("%Jarray '%D' assumed to have one element", decl, decl);
+         warning (0, "%Jarray %qD assumed to have one element", decl, decl);
 
-         complete_array_type (type, NULL_TREE, 1);
+         complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
 
          layout_decl (decl, 0);
        }
@@ -552,15 +566,7 @@ objc_mark_locals_volatile (void *enclosing_blk)
        scope = scope->outer)
     {
       for (b = scope->bindings; b; b = b->prev)
-       {
-         if (TREE_CODE (b->decl) == VAR_DECL
-             || TREE_CODE (b->decl) == PARM_DECL)
-           {
-             C_DECL_REGISTER (b->decl) = 0;
-             DECL_REGISTER (b->decl) = 0;
-             TREE_THIS_VOLATILE (b->decl) = 1;
-           }
-       }
+       objc_volatilize_decl (b->decl);
 
       /* Do not climb up past the current function.  */
       if (scope->function_body)
@@ -634,7 +640,7 @@ push_scope (void)
       if (current_scope && scope->depth == 0)
        {
          scope->depth--;
-         sorry ("GCC supports only %u nested scopes\n", scope->depth);
+         sorry ("GCC supports only %u nested scopes", scope->depth);
        }
 
       current_scope        = scope;
@@ -667,6 +673,8 @@ pop_scope (void)
   bool functionbody = scope->function_body;
   bool keep = functionbody || scope->keep || scope->bindings;
 
+  c_end_vm_scope (scope->depth);
+
   /* If appropriate, create a BLOCK to record the decls for the life
      of this function.  */
   block = 0;
@@ -718,23 +726,20 @@ pop_scope (void)
          /* Warnings for unused labels, errors for undefined labels.  */
          if (TREE_USED (p) && !DECL_INITIAL (p))
            {
-             error ("%Jlabel `%D' used but not defined", p, p);
+             error ("%Jlabel %qD used but not defined", p, p);
              DECL_INITIAL (p) = error_mark_node;
            }
          else if (!TREE_USED (p) && warn_unused_label)
            {
              if (DECL_INITIAL (p))
-               warning ("%Jlabel `%D' defined but not used", p, p);
+               warning (0, "%Jlabel %qD defined but not used", p, p);
              else
-               warning ("%Jlabel `%D' declared but not defined", p, p);
+               warning (0, "%Jlabel %qD declared but not defined", p, p);
            }
          /* Labels go in BLOCK_VARS.  */
          TREE_CHAIN (p) = BLOCK_VARS (block);
          BLOCK_VARS (block) = p;
-
-#ifdef ENABLE_CHECKING
-         if (I_LABEL_BINDING (b->id) != b) abort ();
-#endif
+         gcc_assert (I_LABEL_BINDING (b->id) == b);
          I_LABEL_BINDING (b->id) = b->shadowed;
          break;
 
@@ -747,9 +752,7 @@ pop_scope (void)
             appears in the bindings list with b->id NULL.  */
          if (b->id)
            {
-#ifdef ENABLE_CHECKING
-             if (I_TAG_BINDING (b->id) != b) abort ();
-#endif
+             gcc_assert (I_TAG_BINDING (b->id) == b);
              I_TAG_BINDING (b->id) = b->shadowed;
            }
          break;
@@ -757,12 +760,18 @@ pop_scope (void)
        case FUNCTION_DECL:
          /* Propagate TREE_ADDRESSABLE from nested functions to their
             containing functions.  */
-         if (! TREE_ASM_WRITTEN (p)
+         if (!TREE_ASM_WRITTEN (p)
              && DECL_INITIAL (p) != 0
              && TREE_ADDRESSABLE (p)
              && DECL_ABSTRACT_ORIGIN (p) != 0
              && DECL_ABSTRACT_ORIGIN (p) != p)
            TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
+         if (!DECL_EXTERNAL (p)
+             && DECL_INITIAL (p) == 0)
+           {
+             error ("%Jnested function %qD declared but never defined", p, p);
+             undef_nested_function = true;
+           }
          goto common_symbol;
 
        case VAR_DECL:
@@ -772,11 +781,9 @@ pop_scope (void)
              && !DECL_IN_SYSTEM_HEADER (p)
              && DECL_NAME (p)
              && !DECL_ARTIFICIAL (p)
-             && (scope != file_scope
-                 || (TREE_STATIC (p) && !TREE_PUBLIC (p)
-                     && !TREE_THIS_VOLATILE (p)))
-             && scope != external_scope)
-           warning ("%Junused variable `%D'", p, p);
+             && scope != file_scope
+             && scope != external_scope) 
+           warning (0, "%Junused variable %qD", p, p);
 
          if (b->inner_comp)
            {
@@ -819,9 +826,7 @@ pop_scope (void)
             here with b->id NULL in this case.  */
          if (b->id)
            {
-#ifdef ENABLE_CHECKING
-             if (I_SYMBOL_BINDING (b->id) != b) abort ();
-#endif
+             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
              I_SYMBOL_BINDING (b->id) = b->shadowed;
              if (b->shadowed && b->shadowed->type)
                TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
@@ -829,7 +834,7 @@ pop_scope (void)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -905,6 +910,8 @@ pop_file_scope (void)
   /* Pop off the file scope and close this translation unit.  */
   pop_scope ();
   file_scope = 0;
+
+  maybe_apply_pending_pragma_weaks ();
   cgraph_finalize_compilation_unit ();
 }
 
@@ -972,10 +979,10 @@ match_builtin_function_types (tree newtype, tree oldtype)
 
   while (oldargs || newargs)
     {
-      if (! oldargs
-         || ! newargs
-         || ! TREE_VALUE (oldargs)
-         || ! TREE_VALUE (newargs)
+      if (!oldargs
+         || !newargs
+         || !TREE_VALUE (oldargs)
+         || !TREE_VALUE (newargs)
          || TYPE_MODE (TREE_VALUE (oldargs))
             != TYPE_MODE (TREE_VALUE (newargs)))
        return 0;
@@ -1014,14 +1021,14 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
       if (TREE_CHAIN (t) == 0
          && TYPE_MAIN_VARIANT (type) != void_type_node)
        {
-         inform ("a parameter list with an ellipsis can't match "
+         inform ("a parameter list with an ellipsis can%'t match "
                  "an empty parameter name list declaration");
          break;
        }
 
       if (c_type_promotes_to (type) != type)
        {
-         inform ("an argument type that has a default promotion can't match "
+         inform ("an argument type that has a default promotion can%'t match "
                  "an empty parameter name list declaration");
          break;
        }
@@ -1038,8 +1045,7 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
   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)
+#define END_OF_ARGLIST(t) ((t) == void_type_node)
 
   oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype);
   newargs = TYPE_ARG_TYPES (newtype);
@@ -1047,8 +1053,8 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
 
   for (;;)
     {
-      tree oldargtype = TREE_VALUE (oldargs);
-      tree newargtype = TREE_VALUE (newargs);
+      tree oldargtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs));
+      tree newargtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs));
 
       if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
        break;
@@ -1057,22 +1063,23 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
         agree on the number of arguments.  */
       if (END_OF_ARGLIST (oldargtype))
        {
-         error ("%Jprototype for '%D' declares more arguments "
+         error ("%Jprototype for %qD declares more arguments "
                 "than previous old-style definition", newdecl, newdecl);
          return false;
        }
       else if (END_OF_ARGLIST (newargtype))
        {
-         error ("%Jprototype for '%D' declares fewer arguments "
+         error ("%Jprototype for %qD 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.  */
-      else if (! comptypes (oldargtype, newargtype))
+      else if (!comptypes (oldargtype, newargtype))
        {
-         error ("%Jprototype for '%D' declares arg %d with incompatible type",
+         error ("%Jprototype for %qD declares argument %d"
+                " with incompatible type",
                 newdecl, newdecl, i);
          return false;
        }
@@ -1084,7 +1091,7 @@ validate_proto_after_old_defn (tree newdecl, tree newtype, tree oldtype)
 
   /* 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",
+  warning (0, "%Jprototype for %qD follows non-prototype definition",
           newdecl, newdecl);
   return true;
 #undef END_OF_ARGLIST
@@ -1099,11 +1106,11 @@ locate_old_decl (tree decl, void (*diag)(const char *, ...))
   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
     ;
   else if (DECL_INITIAL (decl))
-    diag (N_("%Jprevious definition of '%D' was here"), decl, decl);
+    diag (N_("%Jprevious definition of %qD was here"), decl, decl);
   else if (C_DECL_IMPLICIT (decl))
-    diag (N_("%Jprevious implicit declaration of '%D' was here"), decl, decl);
+    diag (N_("%Jprevious implicit declaration of %qD was here"), decl, decl);
   else
-    diag (N_("%Jprevious declaration of '%D' was here"), decl, decl);
+    diag (N_("%Jprevious declaration of %qD was here"), decl, decl);
 }
 
 /* Subroutine of duplicate_decls.  Compare NEWDECL to OLDDECL.
@@ -1121,6 +1128,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   tree newtype, oldtype;
   bool pedwarned = false;
   bool warned = false;
+  bool retval = true;
 
   /* If we have error_mark_node for either decl or type, just discard
      the previous decl - we're in an error cascade already.  */
@@ -1139,19 +1147,28 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
            && DECL_BUILT_IN (olddecl)
            && !C_DECL_DECLARED_BUILTIN (olddecl)))
        {
-         error ("%J'%D' redeclared as different kind of symbol",
+         error ("%J%qD redeclared as different kind of symbol",
                 newdecl, newdecl);
          locate_old_decl (olddecl, error);
        }
       else if (TREE_PUBLIC (newdecl))
-       warning ("%Jbuilt-in function '%D' declared as non-function",
+       warning (0, "%Jbuilt-in function %qD declared as non-function",
                 newdecl, newdecl);
       else if (warn_shadow)
-       warning ("%Jdeclaration of '%D' shadows a built-in function",
+       warning (0, "%Jdeclaration of %qD shadows a built-in function",
                 newdecl, 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
@@ -1168,7 +1185,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
              /* If types don't match for a built-in, throw away the
                 built-in.  No point in calling locate_old_decl here, it
                 won't print anything.  */
-             warning ("%Jconflicting types for built-in function '%D'",
+             warning (0, "%Jconflicting types for built-in function %qD",
                       newdecl, newdecl);
              return false;
            }
@@ -1190,20 +1207,32 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
               && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
               && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
-              && C_FUNCTION_IMPLICIT_INT (newdecl))
+              && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
        {
-         pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
+         pedwarn ("%Jconflicting types for %qD", newdecl, newdecl);
          /* Make sure we keep void as the return type.  */
          TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
          C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
          pedwarned = true;
        }
+      /* Permit void foo (...) to match an earlier call to foo (...) with
+        no declared type (thus, implicitly int).  */
+      else if (TREE_CODE (newdecl) == FUNCTION_DECL
+              && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node
+              && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
+              && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
+       {
+         pedwarn ("%Jconflicting types for %qD", newdecl, newdecl);
+         /* Make sure we keep void as the return type.  */
+         TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
+         pedwarned = true;
+       }
       else
        {
          if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
-           error ("%J conflicting type qualifiers for '%D'", newdecl, newdecl);
+           error ("%J conflicting type qualifiers for %qD", newdecl, newdecl);
          else
-           error ("%Jconflicting types for '%D'", newdecl, newdecl);
+           error ("%Jconflicting types for %qD", newdecl, newdecl);
          diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
          locate_old_decl (olddecl, error);
          return false;
@@ -1218,7 +1247,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
        return true;  /* Allow OLDDECL to continue in use.  */
 
-      error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
+      error ("%Jredefinition of typedef %qD", newdecl, newdecl);
       locate_old_decl (olddecl, error);
       return false;
     }
@@ -1242,7 +1271,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
                  && !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
        {
          if (warn_shadow)
-           warning ("%Jdeclaration of '%D' shadows a built-in function",
+           warning (0, "%Jdeclaration of %qD shadows a built-in function",
                     newdecl, newdecl);
          /* Discard the old built-in function.  */
          return false;
@@ -1250,17 +1279,47 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
       if (DECL_INITIAL (newdecl))
        {
-         if (DECL_INITIAL (olddecl)
-             && !(DECL_DECLARED_INLINE_P (olddecl)
-                  && DECL_EXTERNAL (olddecl)
-                  && !(DECL_DECLARED_INLINE_P (newdecl)
-                       && DECL_EXTERNAL (newdecl)
-                       && same_translation_unit_p (olddecl, newdecl))))
+         if (DECL_INITIAL (olddecl))
            {
-             error ("%Jredefinition of '%D'", newdecl, newdecl);
-             locate_old_decl (olddecl, error);
-             return false;
-           }
+             /* If both decls have extern inline and are in the same TU,
+                reject the new decl.  */
+             if (DECL_DECLARED_INLINE_P (olddecl)
+                 && DECL_EXTERNAL (olddecl)
+                 && DECL_DECLARED_INLINE_P (newdecl)
+                 && DECL_EXTERNAL (newdecl)
+                 && same_translation_unit_p (newdecl, olddecl))
+               {
+                 error ("%Jredefinition of %qD", newdecl, newdecl);
+                 locate_old_decl (olddecl, error);
+                 return false;
+               }
+             /* If both decls have not extern inline, reject the new decl.  */
+             if (!DECL_DECLARED_INLINE_P (olddecl)
+                 && !DECL_EXTERNAL (olddecl)
+                 && !DECL_DECLARED_INLINE_P (newdecl)
+                 && !DECL_EXTERNAL (newdecl))
+               {
+                 error ("%Jredefinition of %qD", newdecl, newdecl);
+                 locate_old_decl (olddecl, error);
+                 return false;
+               }
+             /* If the new decl is declared as extern inline, error if they are
+                in the same TU, otherwise retain the old decl.  */
+             if (!DECL_DECLARED_INLINE_P (olddecl)
+                 && !DECL_EXTERNAL (olddecl)
+                 && DECL_DECLARED_INLINE_P (newdecl)
+                 && DECL_EXTERNAL (newdecl))
+               {
+                 if (same_translation_unit_p (newdecl, olddecl))
+                   {
+                     error ("%Jredefinition of %qD", newdecl, newdecl);
+                     locate_old_decl (olddecl, error);
+                     return false;
+                   }
+                 else
+                   retval = false;
+               }
+          }
        }
       /* If we have a prototype after an old-style function definition,
         the argument types must be checked specially.  */
@@ -1280,7 +1339,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
         not undefined behavior, and is the most convenient way to get
         some effects (see e.g.  what unwind-dw2-fde-glibc.c does to
         the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but
-        we do diagnose it if -Wtraditional. */
+        we do diagnose it if -Wtraditional.  */
       if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
        {
          /* Two exceptions to the rule.  If olddecl is an extern
@@ -1292,7 +1351,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
              && !(DECL_EXTERNAL (olddecl)
                   && DECL_DECLARED_INLINE_P (olddecl)))
            {
-             error ("%Jstatic declaration of '%D' follows "
+             error ("%Jstatic declaration of %qD follows "
                     "non-static declaration", newdecl, newdecl);
              locate_old_decl (olddecl, error);
            }
@@ -1302,14 +1361,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        {
          if (DECL_CONTEXT (olddecl))
            {
-             error ("%Jnon-static declaration of '%D' follows "
+             error ("%Jnon-static declaration of %qD follows "
                     "static declaration", newdecl, newdecl);
              locate_old_decl (olddecl, error);
              return false;
            }
          else if (warn_traditional)
            {
-             warning ("%Jnon-static declaration of '%D' follows "
+             warning (0, "%Jnon-static declaration of %qD follows "
                       "static declaration", newdecl, newdecl);
              warned = true;
            }
@@ -1322,10 +1381,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl))
        {
          if (DECL_THREAD_LOCAL (newdecl))
-           error ("%Jthread-local declaration of '%D' follows "
+           error ("%Jthread-local declaration of %qD follows "
                   "non-thread-local declaration", newdecl, newdecl);
          else
-           error ("%Jnon-thread-local declaration of '%D' follows "
+           error ("%Jnon-thread-local declaration of %qD follows "
                   "thread-local declaration", newdecl, newdecl);
 
          locate_old_decl (olddecl, error);
@@ -1335,7 +1394,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       /* Multiple initialized definitions are not allowed (6.9p3,5).  */
       if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
        {
-         error ("%Jredefinition of '%D'", newdecl, newdecl);
+         error ("%Jredefinition of %qD", newdecl, newdecl);
          locate_old_decl (olddecl, error);
          return false;
        }
@@ -1362,7 +1421,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
                }
              else if (warn_traditional)
                {
-                 warning ("%Jnon-static declaration of '%D' follows "
+                 warning (0, "%Jnon-static declaration of %qD follows "
                           "static declaration", newdecl, newdecl);
                  warned = true;
                }
@@ -1370,10 +1429,10 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          else
            {
              if (TREE_PUBLIC (newdecl))
-               error ("%Jnon-static declaration of '%D' follows "
+               error ("%Jnon-static declaration of %qD follows "
                       "static declaration", newdecl, newdecl);
              else
-               error ("%Jstatic declaration of '%D' follows "
+               error ("%Jstatic declaration of %qD follows "
                       "non-static declaration", newdecl, newdecl);
 
              locate_old_decl (olddecl, error);
@@ -1391,13 +1450,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
            }
          else if (DECL_EXTERNAL (olddecl))
            {
-             error ("%Jdeclaration of '%D' with no linkage follows "
+             error ("%Jdeclaration of %qD with no linkage follows "
                     "extern declaration", newdecl, newdecl);
              locate_old_decl (olddecl, error);
            }
          else
            {
-             error ("%Jredeclaration of '%D' with no linkage",
+             error ("%Jredeclaration of %qD with no linkage",
                     newdecl, newdecl);
              locate_old_decl (olddecl, error);
            }
@@ -1411,7 +1470,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
       && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
     {
-      warning ("%Jredeclaration of '%D' with different visibility "
+      warning (0, "%Jredeclaration of %qD with different visibility "
               "(old visibility preserved)", newdecl, newdecl);
       warned = true;
     }
@@ -1422,14 +1481,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       if (DECL_DECLARED_INLINE_P (newdecl)
          && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
        {
-         warning ("%Jinline declaration of '%D' follows "
+         warning (0, "%Jinline declaration of %qD follows "
                   "declaration with attribute noinline", newdecl, newdecl);
          warned = true;
        }
       else if (DECL_DECLARED_INLINE_P (olddecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
        {
-         warning ("%Jdeclaration of '%D' with attribute noinline follows "
+         warning (0, "%Jdeclaration of %qD with attribute noinline follows "
                   "inline declaration ", newdecl, newdecl);
          warned = true;
        }
@@ -1444,13 +1503,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
        {
          if (TREE_USED (olddecl))
            {
-             warning ("%J'%D' declared inline after being called",
+             warning (0, "%J%qD declared inline after being called",
                       olddecl, olddecl);
              warned = true;
            }
          else if (DECL_INITIAL (olddecl))
            {
-             warning ("%J'%D' declared inline after its definition",
+             warning (0, "%J%qD declared inline after its definition",
                       olddecl, olddecl);
              warned = true;
            }
@@ -1470,7 +1529,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       if (TREE_CODE (newdecl) == PARM_DECL
          && (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
        {
-         error ("%Jredefinition of parameter '%D'", newdecl, newdecl);
+         error ("%Jredefinition of parameter %qD", newdecl, newdecl);
          locate_old_decl (olddecl, error);
          return false;
        }
@@ -1483,7 +1542,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
         definition.  */
       && !(TREE_CODE (newdecl) == FUNCTION_DECL
           && DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
-      /* Don't warn about redundant redeclarations of builtins. */
+      /* Don't warn about redundant redeclarations of builtins.  */
       && !(TREE_CODE (newdecl) == FUNCTION_DECL
           && !DECL_BUILT_IN (newdecl)
           && DECL_BUILT_IN (olddecl)
@@ -1494,15 +1553,15 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
       && !(TREE_CODE (newdecl) == PARM_DECL
           && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)))
     {
-      warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl);
+      warning (0, "%Jredundant redeclaration of %qD", newdecl, newdecl);
       warned = true;
     }
 
   /* Report location of previous decl/defn in a consistent manner.  */
   if (warned || pedwarned)
-    locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
+    locate_old_decl (olddecl, pedwarned ? pedwarn : warning0);
 
-  return true;
+  return retval;
 }
 
 /* Subroutine of duplicate_decls.  NEWDECL has been found to be
@@ -1515,19 +1574,23 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
 {
   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
                           && DECL_INITIAL (newdecl) != 0);
+  int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
+                         && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
+  int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
+                         && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
 
   /* For real parm decl following a forward decl, rechain the old decl
      in its new location and clear TREE_ASM_WRITTEN (it's not a
      forward decl anymore).  */
   if (TREE_CODE (newdecl) == PARM_DECL
-      && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
+      && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
     {
       struct c_binding *b, **here;
 
       for (here = &current_scope->bindings; *here; here = &(*here)->prev)
        if ((*here)->decl == olddecl)
          goto found;
-      abort ();
+      gcc_unreachable ();
 
     found:
       b = *here;
@@ -1547,7 +1610,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
     = composite_type (newtype, oldtype);
 
   /* Lay the type out, unless already done.  */
-  if (oldtype != TREE_TYPE (newdecl))
+  if (!comptypes (oldtype, TREE_TYPE (newdecl)))
     {
       if (TREE_TYPE (newdecl) != error_mark_node)
        layout_type (TREE_TYPE (newdecl));
@@ -1584,8 +1647,16 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
        make_var_volatile (newdecl);
     }
 
-  /* Keep source location of definition rather than declaration.  */
-  if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+  /* Merge deprecatedness.  */
+  if (TREE_DEPRECATED (newdecl))
+    TREE_DEPRECATED (olddecl) = 1;
+
+  /* Keep source location of definition rather than declaration and of
+     prototype rather than non-prototype unless that prototype is
+     built-in.  */
+  if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+      || (old_is_prototype && !new_is_prototype
+         && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
     DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
 
   /* Merge the unused-warning information.  */
@@ -1627,6 +1698,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
       TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
       DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
       DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+      DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
     }
 
   /* Merge the storage class information.  */
@@ -1640,7 +1712,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
         copy the attributes of NEWDECL into OLDDECL.  */
       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
       /* If this clears `static', clear it in the identifier too.  */
-      if (! TREE_PUBLIC (olddecl))
+      if (!TREE_PUBLIC (olddecl))
        TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
     }
   if (DECL_EXTERNAL (newdecl))
@@ -1650,7 +1722,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
 
       /* An extern decl does not override previous storage class.  */
       TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
-      if (! DECL_EXTERNAL (newdecl))
+      if (!DECL_EXTERNAL (newdecl))
        {
          DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
          DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
@@ -1700,10 +1772,15 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
          DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
          C_DECL_DECLARED_BUILTIN (newdecl) = 1;
+         if (new_is_prototype)
+           C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+         else
+           C_DECL_BUILTIN_PROTOTYPE (newdecl)
+             = C_DECL_BUILTIN_PROTOTYPE (olddecl);
        }
 
       /* Also preserve various other info from the definition.  */
-      if (! new_is_definition)
+      if (!new_is_definition)
        {
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
          DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
@@ -1713,7 +1790,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
 
          /* Set DECL_INLINE on the declaration if we've got a body
             from which to instantiate.  */
-         if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+         if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
            {
              DECL_INLINE (newdecl) = 1;
              DECL_ABSTRACT_ORIGIN (newdecl)
@@ -1725,7 +1802,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
          /* If a previous declaration said inline, mark the
             definition as inlinable.  */
          if (DECL_DECLARED_INLINE_P (newdecl)
-             && ! DECL_UNINLINABLE (newdecl))
+             && !DECL_UNINLINABLE (newdecl))
            DECL_INLINE (newdecl) = 1;
        }
     }
@@ -1799,23 +1876,30 @@ warn_if_shadowing (tree new_decl)
       {
        tree old_decl = b->decl;
 
-       if (TREE_CODE (old_decl) == PARM_DECL)
-         warning ("%Jdeclaration of '%D' shadows a parameter",
+       if (old_decl == error_mark_node)
+         {
+           warning (0, "%Jdeclaration of %qD shadows previous non-variable",
+                    new_decl, new_decl);
+           break;
+         }
+       else if (TREE_CODE (old_decl) == PARM_DECL)
+         warning (0, "%Jdeclaration of %qD shadows a parameter",
                   new_decl, new_decl);
        else if (DECL_FILE_SCOPE_P (old_decl))
-         warning ("%Jdeclaration of '%D' shadows a global declaration",
+         warning (0, "%Jdeclaration of %qD shadows a global declaration",
                   new_decl, new_decl);
        else if (TREE_CODE (old_decl) == FUNCTION_DECL
                 && DECL_BUILT_IN (old_decl))
-         warning ("%Jdeclaration of '%D' shadows a built-in function",
-                  new_decl, new_decl);
+         {
+           warning (0, "%Jdeclaration of %qD shadows a built-in function",
+                    new_decl, new_decl);
+           break;
+         }
        else
-         warning ("%Jdeclaration of '%D' shadows a previous local",
+         warning (0, "%Jdeclaration of %qD shadows a previous local",
                   new_decl, new_decl);
 
-       if (TREE_CODE (old_decl) != FUNCTION_DECL
-           || ! DECL_BUILT_IN (old_decl))
-         warning ("%Jshadowed declaration is here", old_decl);
+       warning (0, "%Jshadowed declaration is here", old_decl);
 
        break;
       }
@@ -1903,7 +1987,7 @@ pushdecl (tree x)
   bool nested = false;
 
   /* Functions need the lang_decl data.  */
-  if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
+  if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x))
     DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
 
   /* Must set DECL_CONTEXT for everything not at file scope or
@@ -1914,6 +1998,12 @@ pushdecl (tree x)
          || DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
     DECL_CONTEXT (x) = current_function_decl;
 
+  /* If this is of variably modified type, prevent jumping into its
+     scope.  */
+  if ((TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == TYPE_DECL)
+      && variably_modified_type_p (TREE_TYPE (x), NULL_TREE))
+    c_begin_vm_scope (scope->depth);
+
   /* Anonymous decls are just inserted in the scope.  */
   if (!name)
     {
@@ -1931,11 +2021,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;
     }
@@ -1969,7 +2100,7 @@ pushdecl (tree x)
       if (warn_nested_externs
          && scope != file_scope
          && !DECL_IN_SYSTEM_HEADER (x))
-       warning ("nested extern declaration of '%D'", x);
+       warning (0, "nested extern declaration of %qD", x);
 
       while (b && !B_IN_EXTERNAL_SCOPE (b))
        {
@@ -1981,7 +2112,7 @@ pushdecl (tree x)
             its type saved; the others will already have had their
             proper types saved and the types will not have changed as
             their scopes will not have been re-entered.  */
-         if (DECL_FILE_SCOPE_P (b->decl) && !type_saved)
+         if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved)
            {
              b->type = TREE_TYPE (b->decl);
              type_saved = true;
@@ -2022,7 +2153,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
@@ -2042,6 +2181,7 @@ pushdecl (tree x)
                 just need to fall through to make the declaration in
                 this scope.  */
              nested = true;
+             x = visdecl;
            }
          else
            {
@@ -2051,30 +2191,6 @@ pushdecl (tree x)
            }
        }
     }
-  /* Similarly, a declaration of a function with static linkage at
-     block scope must be checked against any existing declaration
-     of that function at file scope.  */
-  else if (TREE_CODE (x) == FUNCTION_DECL && scope != file_scope
-          && !TREE_PUBLIC (x) && !DECL_INITIAL (x))
-    {
-      if (warn_nested_externs && !DECL_IN_SYSTEM_HEADER (x))
-       warning ("nested static declaration of '%D'", x);
-
-      while (b && !B_IN_FILE_SCOPE (b))
-       b = b->shadowed;
-
-      if (b && same_translation_unit_p (x, b->decl)
-         && duplicate_decls (x, b->decl))
-       {
-         bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
-         return b->decl;
-       }
-      else
-       {
-         bind (name, x, file_scope, /*invisible=*/true, /*nested=*/false);
-         nested = true;
-       }
-    }
 
   warn_if_shadowing (x);
 
@@ -2123,14 +2239,11 @@ pushdecl_top_level (tree x)
 {
   tree name;
   bool nested = false;
-
-  if (TREE_CODE (x) != VAR_DECL)
-    abort ();
+  gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
 
   name = DECL_NAME (x);
 
-  if (I_SYMBOL_BINDING (name))
-    abort ();
+ gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name));
 
   if (TREE_PUBLIC (x))
     {
@@ -2150,12 +2263,12 @@ implicit_decl_warning (tree id, tree olddecl)
   switch (mesg_implicit_function_declaration)
     {
     case 0: return;
-    case 1: diag = warning; break;
+    case 1: diag = warning0; break;
     case 2: diag = error;   break;
-    default: abort ();
+    default: gcc_unreachable ();
     }
 
-  diag (N_("implicit declaration of function '%E'"), id);
+  diag (N_("implicit declaration of function %qE"), id);
   if (olddecl)
     locate_old_decl (olddecl, diag);
 }
@@ -2168,6 +2281,8 @@ implicitly_declare (tree functionid)
 {
   struct c_binding *b;
   tree decl = 0;
+  tree asmspec_tree;
+
   for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
     {
       if (B_IN_SCOPE (b, external_scope))
@@ -2179,6 +2294,9 @@ implicitly_declare (tree functionid)
 
   if (decl)
     {
+      if (decl == error_mark_node)
+       return decl;
+
       /* FIXME: Objective-C has weird not-really-builtin functions
         which are supposed to be visible automatically.  They wind up
         in the external scope because they're pushed before the file
@@ -2211,7 +2329,7 @@ implicitly_declare (tree functionid)
                                                      (TREE_TYPE (decl)));
              if (!comptypes (newtype, TREE_TYPE (decl)))
                {
-                 warning ("incompatible implicit declaration of built-in"
+                 warning (0, "incompatible implicit declaration of built-in"
                           " function %qD", decl);
                  newtype = TREE_TYPE (decl);
                }
@@ -2239,6 +2357,9 @@ implicitly_declare (tree functionid)
   TREE_PUBLIC (decl) = 1;
   C_DECL_IMPLICIT (decl) = 1;
   implicit_decl_warning (functionid, 0);
+  asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL);
+  if (asmspec_tree)
+    set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree));
 
   /* C89 says implicit declarations are in the innermost block.
      So we record the decl in the standard fashion.  */
@@ -2261,26 +2382,26 @@ implicitly_declare (tree functionid)
    ID, including a reference to a builtin outside of function-call
    context.  Establish a binding of the identifier to error_mark_node
    in an appropriate scope, which will suppress further errors for the
-   same identifier.  */
+   same identifier.  The error message should be given location LOC.  */
 void
-undeclared_variable (tree id)
+undeclared_variable (tree id, location_t loc)
 {
   static bool already = false;
   struct c_scope *scope;
 
   if (current_function_decl == 0)
     {
-      error ("'%E' undeclared here (not in a function)", id);
+      error ("%H%qE undeclared here (not in a function)", &loc, id);
       scope = current_scope;
     }
   else
     {
-      error ("'%E' undeclared (first use in this function)", id);
+      error ("%H%qE undeclared (first use in this function)", &loc, id);
 
-      if (! already)
+      if (!already)
        {
-         error ("(Each undeclared identifier is reported only once");
-         error ("for each function it appears in.)");
+         error ("%H(Each undeclared identifier is reported only once", &loc);
+         error ("%Hfor each function it appears in.)", &loc);
          already = true;
        }
 
@@ -2318,8 +2439,7 @@ lookup_label (tree name)
 
   if (current_function_decl == 0)
     {
-      error ("label %s referenced outside of any function",
-            IDENTIFIER_POINTER (name));
+      error ("label %qE referenced outside of any function", name);
       return 0;
     }
 
@@ -2361,7 +2481,7 @@ declare_label (tree name)
      at this scope */
   if (b && B_IN_CURRENT_SCOPE (b))
     {
-      error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
+      error ("duplicate label declaration %qE", name);
       locate_old_decl (b->decl, error);
 
       /* Just use the previous declaration.  */
@@ -2389,6 +2509,7 @@ define_label (location_t location, tree name)
      if there is a containing function with a declared label with
      the same name.  */
   tree label = I_LABEL_DECL (name);
+  struct c_label_list *nlist_se, *nlist_vm;
 
   if (label
       && ((DECL_CONTEXT (label) == current_function_decl
@@ -2396,7 +2517,7 @@ define_label (location_t location, tree name)
          || (DECL_CONTEXT (label) != current_function_decl
              && C_DECLARED_LABEL_FLAG (label))))
     {
-      error ("%Hduplicate label `%D'", &location, label);
+      error ("%Hduplicate label %qD", &location, label);
       locate_old_decl (label, error);
       return 0;
     }
@@ -2405,6 +2526,11 @@ define_label (location_t location, tree name)
       /* The label has been used or declared already in this function,
         but not defined.  Update its location to point to this
         definition.  */
+      if (C_DECL_UNDEFINABLE_STMT_EXPR (label))
+       error ("%Jjump into statement expression", label);
+      if (C_DECL_UNDEFINABLE_VM (label))
+       error ("%Jjump into scope of identifier with variably modified type",
+              label);
       DECL_SOURCE_LOCATION (label) = location;
     }
   else
@@ -2418,9 +2544,18 @@ define_label (location_t location, tree name)
     }
 
   if (warn_traditional && !in_system_header && lookup_name (name))
-    warning ("%Htraditional C lacks a separate namespace for labels, "
-             "identifier `%s' conflicts", &location,
-            IDENTIFIER_POINTER (name));
+    warning (0, "%Htraditional C lacks a separate namespace for labels, "
+             "identifier %qE conflicts", &location, name);
+
+  nlist_se = XOBNEW (&parser_obstack, struct c_label_list);
+  nlist_se->next = label_context_stack_se->labels_def;
+  nlist_se->label = label;
+  label_context_stack_se->labels_def = nlist_se;
+
+  nlist_vm = XOBNEW (&parser_obstack, struct c_label_list);
+  nlist_vm->next = label_context_stack_vm->labels_def;
+  nlist_vm->label = label;
+  label_context_stack_vm->labels_def = nlist_vm;
 
   /* Mark label as having been defined.  */
   DECL_INITIAL (label) = error_mark_node;
@@ -2484,9 +2619,8 @@ void
 pending_xref_error (void)
 {
   if (pending_invalid_xref != 0)
-    error ("%H`%s' defined as wrong kind of tag",
-           &pending_invalid_xref_location,
-           IDENTIFIER_POINTER (pending_invalid_xref));
+    error ("%H%qE defined as wrong kind of tag",
+           &pending_invalid_xref_location, pending_invalid_xref);
   pending_invalid_xref = 0;
 }
 
@@ -2526,15 +2660,15 @@ lookup_name_in_scope (tree name, struct c_scope *scope)
 void
 c_init_decl_processing (void)
 {
-  tree endlink;
-  tree ptr_ftype_void, ptr_ftype_ptr;
   location_t save_loc = input_location;
 
-  /* Adds some ggc roots, and reserved words for c-parse.in.  */
+  /* Initialize reserved words for parser.  */
   c_parse_init ();
 
   current_function_decl = 0;
 
+  gcc_obstack_init (&parser_obstack);
+
   /* Make the externals scope.  */
   push_scope ();
   external_scope = current_scope;
@@ -2562,12 +2696,6 @@ c_init_decl_processing (void)
   pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
                        boolean_type_node));
 
-  endlink = void_list_node;
-  ptr_ftype_void = build_function_type (ptr_type_node, endlink);
-  ptr_ftype_ptr
-    = build_function_type (ptr_type_node,
-                          tree_cons (NULL_TREE, ptr_type_node, endlink));
-
   input_location = save_loc;
 
   pedantic_lvalues = true;
@@ -2590,9 +2718,9 @@ c_make_fname_decl (tree id, int type_dep)
   tree decl, type, init;
   size_t length = strlen (name);
 
-  type =  build_array_type
-          (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
-          build_index_type (size_int (length)));
+  type = build_array_type (char_type_node,
+                          build_index_type (size_int (length)));
+  type = c_build_qualified_type (type, TYPE_QUAL_CONST);
 
   decl = build_decl (VAR_DECL, id, type);
 
@@ -2640,12 +2768,12 @@ builtin_function (const char *name, tree type, int function_code,
   DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
   DECL_BUILT_IN_CLASS (decl) = cl;
   DECL_FUNCTION_CODE (decl) = function_code;
+  C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
 
   /* Should never be called on a symbol with a preexisting meaning.  */
-  if (I_SYMBOL_BINDING (id))
-    abort ();
+  gcc_assert (!I_SYMBOL_BINDING (id));
 
   bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
 
@@ -2675,7 +2803,7 @@ builtin_function (const char *name, tree type, int function_code,
    Otherwise, it is an error.  */
 
 void
-shadow_tag (tree declspecs)
+shadow_tag (const struct c_declspecs *declspecs)
 {
   shadow_tag_warned (declspecs, 0);
 }
@@ -2683,21 +2811,13 @@ shadow_tag (tree declspecs)
 /* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
    but no pedwarn.  */
 void
-shadow_tag_warned (tree declspecs, int warned)
+shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
 {
-  int found_tag = 0;
-  tree link;
-  tree specs, attrs;
-
-  pending_invalid_xref = 0;
-
-  /* Remove the attributes from declspecs, since they will confuse the
-     following code.  */
-  split_specs_attrs (declspecs, &specs, &attrs);
+  bool found_tag = false;
 
-  for (link = specs; link; link = TREE_CHAIN (link))
+  if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
     {
-      tree value = TREE_VALUE (link);
+      tree value = declspecs->type;
       enum tree_code code = TREE_CODE (value);
 
       if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
@@ -2707,7 +2827,7 @@ shadow_tag_warned (tree declspecs, int warned)
          tree name = TYPE_NAME (value);
          tree t;
 
-         found_tag++;
+         found_tag = true;
 
          if (name == 0)
            {
@@ -2718,8 +2838,29 @@ shadow_tag_warned (tree declspecs, int warned)
                  warned = 1;
                }
            }
+         else if (!declspecs->tag_defined_p
+                  && declspecs->storage_class != csc_none)
+           {
+             if (warned != 1)
+               pedwarn ("empty declaration with storage class specifier "
+                        "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
+         else if (!declspecs->tag_defined_p
+                  && (declspecs->const_p
+                      || declspecs->volatile_p
+                      || declspecs->restrict_p))
+           {
+             if (warned != 1)
+               pedwarn ("empty declaration with type qualifier "
+                        "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
          else
            {
+             pending_invalid_xref = 0;
              t = lookup_tag (code, name, 1);
 
              if (t == 0)
@@ -2731,182 +2872,174 @@ shadow_tag_warned (tree declspecs, int warned)
        }
       else
        {
-         if (!warned && ! in_system_header)
+         if (warned != 1 && !in_system_header)
            {
-             warning ("useless keyword or type name in empty declaration");
-             warned = 2;
+             pedwarn ("useless type name in empty declaration");
+             warned = 1;
            }
        }
     }
+  else if (warned != 1 && !in_system_header && declspecs->typedef_p)
+    {
+      pedwarn ("useless type name in empty declaration");
+      warned = 1;
+    }
+
+  pending_invalid_xref = 0;
+
+  if (declspecs->inline_p)
+    {
+      error ("%<inline%> in empty declaration");
+      warned = 1;
+    }
+
+  if (current_scope == file_scope && declspecs->storage_class == csc_auto)
+    {
+      error ("%<auto%> in file-scope empty declaration");
+      warned = 1;
+    }
+
+  if (current_scope == file_scope && declspecs->storage_class == csc_register)
+    {
+      error ("%<register%> in file-scope empty declaration");
+      warned = 1;
+    }
+
+  if (!warned && !in_system_header && declspecs->storage_class != csc_none)
+    {
+      warning (0, "useless storage class specifier in empty declaration");
+      warned = 2;
+    }
 
-  if (found_tag > 1)
-    error ("two types specified in one empty declaration");
+  if (!warned && !in_system_header && declspecs->thread_p)
+    {
+      warning (0, "useless %<__thread%> in empty declaration");
+      warned = 2;
+    }
+
+  if (!warned && !in_system_header && (declspecs->const_p
+                                      || declspecs->volatile_p
+                                      || declspecs->restrict_p))
+    {
+      warning (0, "useless type qualifier in empty declaration");
+      warned = 2;
+    }
 
   if (warned != 1)
     {
-      if (found_tag == 0)
+      if (!found_tag)
        pedwarn ("empty declaration");
     }
 }
 \f
+
+/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_*
+   bits.  SPECS represents declaration specifiers that the grammar
+   only permits to contain type qualifiers and attributes.  */
+
+int
+quals_from_declspecs (const struct c_declspecs *specs)
+{
+  int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
+              | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
+              | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+  gcc_assert (!specs->type
+             && !specs->decl_attr
+             && specs->typespec_word == cts_none
+             && specs->storage_class == csc_none
+             && !specs->typedef_p
+             && !specs->explicit_signed_p
+             && !specs->deprecated_p
+             && !specs->long_p
+             && !specs->long_long_p
+             && !specs->short_p
+             && !specs->signed_p
+             && !specs->unsigned_p
+             && !specs->complex_p
+             && !specs->inline_p
+             && !specs->thread_p);
+  return quals;
+}
+
 /* Construct an array declarator.  EXPR is the expression inside [], or
    NULL_TREE.  QUALS are the type qualifiers inside the [] (to be applied
    to the pointer to which a parameter array is converted).  STATIC_P is
    true if "static" is inside the [], false otherwise.  VLA_UNSPEC_P
    is true if the array is [*], a VLA of unspecified length which is
    nevertheless a complete type (not currently implemented by GCC),
-   false otherwise.  The declarator is constructed as an ARRAY_REF
-   (to be decoded by grokdeclarator), whose operand 0 is what's on the
-   left of the [] (filled by in set_array_declarator_inner) and operand 1
-   is the expression inside; whose TREE_TYPE is the type qualifiers and
-   which has TREE_STATIC set if "static" is used.  */
+   false otherwise.  The field for the contained declarator is left to be
+   filled in by set_array_declarator_inner.  */
 
-tree
-build_array_declarator (tree expr, tree quals, bool static_p,
+struct c_declarator *
+build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
                        bool vla_unspec_p)
 {
-  tree decl;
-  decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
-  TREE_TYPE (decl) = quals;
-  TREE_STATIC (decl) = (static_p ? 1 : 0);
+  struct c_declarator *declarator = XOBNEW (&parser_obstack,
+                                           struct c_declarator);
+  declarator->kind = cdk_array;
+  declarator->declarator = 0;
+  declarator->u.array.dimen = expr;
+  if (quals)
+    {
+      declarator->u.array.attrs = quals->attrs;
+      declarator->u.array.quals = quals_from_declspecs (quals);
+    }
+  else
+    {
+      declarator->u.array.attrs = NULL_TREE;
+      declarator->u.array.quals = 0;
+    }
+  declarator->u.array.static_p = static_p;
+  declarator->u.array.vla_unspec_p = vla_unspec_p;
   if (pedantic && !flag_isoc99)
     {
-      if (static_p || quals != NULL_TREE)
-       pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
+      if (static_p || quals != NULL)
+       pedwarn ("ISO C90 does not support %<static%> or type "
+                "qualifiers in parameter array declarators");
       if (vla_unspec_p)
-       pedwarn ("ISO C90 does not support `[*]' array declarators");
+       pedwarn ("ISO C90 does not support %<[*]%> array declarators");
     }
   if (vla_unspec_p)
-    warning ("GCC does not yet properly implement `[*]' array declarators");
-  return decl;
+    warning (0, "GCC does not yet properly implement %<[*]%> array declarators");
+  return declarator;
 }
 
-/* Set the type of an array declarator.  DECL is the declarator, as
-   constructed by build_array_declarator; TYPE is what appears on the left
-   of the [] and goes in operand 0.  ABSTRACT_P is true if it is an
-   abstract declarator, false otherwise; this is used to reject static and
-   type qualifiers in abstract declarators, where they are not in the
-   C99 grammar.  */
+/* Set the contained declarator of an array declarator.  DECL is the
+   declarator, as constructed by build_array_declarator; INNER is what
+   appears on the left of the [].  ABSTRACT_P is true if it is an
+   abstract declarator, false otherwise; this is used to reject static
+   and type qualifiers in abstract declarators, where they are not in
+   the C99 grammar (subject to possible change in DR#289).  */
 
-tree
-set_array_declarator_inner (tree decl, tree type, bool abstract_p)
+struct c_declarator *
+set_array_declarator_inner (struct c_declarator *decl,
+                           struct c_declarator *inner, bool abstract_p)
 {
-  TREE_OPERAND (decl, 0) = type;
-  if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+  decl->declarator = inner;
+  if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
+                    || decl->u.array.attrs != NULL_TREE
+                    || decl->u.array.static_p))
     error ("static or type qualifiers in abstract declarator");
   return decl;
 }
 \f
-/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
-   lists.  SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
-
-   The head of the declspec list is stored in DECLSPECS.
-   The head of the attribute list is stored in PREFIX_ATTRIBUTES.
-
-   Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
-   the list elements.  We drop the containing TREE_LIST nodes and link the
-   resulting attributes together the way decl_attributes expects them.  */
-
-void
-split_specs_attrs (tree specs_attrs, tree *declspecs, tree *prefix_attributes)
-{
-  tree t, s, a, next, specs, attrs;
-
-  /* This can happen after an __extension__ in pedantic mode.  */
-  if (specs_attrs != NULL_TREE
-      && TREE_CODE (specs_attrs) == INTEGER_CST)
-    {
-      *declspecs = NULL_TREE;
-      *prefix_attributes = NULL_TREE;
-      return;
-    }
-
-  /* This can happen in c++ (eg: decl: typespec initdecls ';').  */
-  if (specs_attrs != NULL_TREE
-      && TREE_CODE (specs_attrs) != TREE_LIST)
-    {
-      *declspecs = specs_attrs;
-      *prefix_attributes = NULL_TREE;
-      return;
-    }
-
-  /* Remember to keep the lists in the same order, element-wise.  */
-
-  specs = s = NULL_TREE;
-  attrs = a = NULL_TREE;
-  for (t = specs_attrs; t; t = next)
-    {
-      next = TREE_CHAIN (t);
-      /* Declspecs have a non-NULL TREE_VALUE.  */
-      if (TREE_VALUE (t) != NULL_TREE)
-       {
-         if (specs == NULL_TREE)
-           specs = s = t;
-         else
-           {
-             TREE_CHAIN (s) = t;
-             s = t;
-           }
-       }
-      /* The TREE_PURPOSE may also be empty in the case of
-        __attribute__(()).  */
-      else if (TREE_PURPOSE (t) != NULL_TREE)
-       {
-         if (attrs == NULL_TREE)
-           attrs = a = TREE_PURPOSE (t);
-         else
-           {
-             TREE_CHAIN (a) = TREE_PURPOSE (t);
-             a = TREE_PURPOSE (t);
-           }
-         /* More attrs can be linked here, move A to the end.  */
-         while (TREE_CHAIN (a) != NULL_TREE)
-           a = TREE_CHAIN (a);
-       }
-    }
-
-  /* Terminate the lists.  */
-  if (s != NULL_TREE)
-    TREE_CHAIN (s) = NULL_TREE;
-  if (a != NULL_TREE)
-    TREE_CHAIN (a) = NULL_TREE;
-
-  /* All done.  */
-  *declspecs = specs;
-  *prefix_attributes = attrs;
-}
-
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (tree type_name)
+groktypename (struct c_type_name *type_name)
 {
-  tree specs, attrs;
-
-  if (TREE_CODE (type_name) != TREE_LIST)
-    return type_name;
+  tree type;
+  tree attrs = type_name->specs->attrs;
 
-  split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
+  type_name->specs->attrs = NULL_TREE;
 
-  type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
-                            NULL);
+  type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
+                        false, NULL);
 
   /* Apply attributes.  */
-  decl_attributes (&type_name, attrs, 0);
+  decl_attributes (&type, attrs, 0);
 
-  return type_name;
-}
-
-/* Return a PARM_DECL node for a given pair of specs and declarator.  */
-
-tree
-groktypename_in_parm_context (tree type_name)
-{
-  if (TREE_CODE (type_name) != TREE_LIST)
-    return type_name;
-  return grokdeclarator (TREE_VALUE (type_name),
-                        TREE_PURPOSE (type_name),
-                        PARM, false, NULL);
+  return type;
 }
 
 /* Decode a declarator in an ordinary declaration or data definition.
@@ -2925,7 +3058,8 @@ groktypename_in_parm_context (tree type_name)
    grokfield and not through here.  */
 
 tree
-start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
+start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
+           bool initialized, tree attributes)
 {
   tree decl;
   tree tem;
@@ -2937,12 +3071,14 @@ start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
 
   decl = grokdeclarator (declarator, declspecs,
                         NORMAL, initialized, NULL);
+  if (!decl)
+    return 0;
 
   deprecated_state = DEPRECATED_NORMAL;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
       && MAIN_NAME_P (DECL_NAME (decl)))
-    warning ("%J'%D' is usually a function", decl, decl);
+    warning (0, "%J%qD is usually a function", decl, decl);
 
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
@@ -2951,18 +3087,18 @@ start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       error ("typedef '%D' is initialized (use __typeof__ instead)", decl);
+       error ("typedef %qD is initialized (use __typeof__ instead)", decl);
        initialized = 0;
        break;
 
       case FUNCTION_DECL:
-       error ("function '%D' is initialized like a variable", decl);
+       error ("function %qD is initialized like a variable", decl);
        initialized = 0;
        break;
 
       case PARM_DECL:
        /* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE.  */
-       error ("parameter '%D' is initialized", decl);
+       error ("parameter %qD is initialized", decl);
        initialized = 0;
        break;
 
@@ -2987,12 +3123,16 @@ start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
          }
        else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
          {
-           error ("variable '%D' has initializer but incomplete type", decl);
+           error ("variable %qD has initializer but incomplete type", decl);
            initialized = 0;
          }
-       else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
+       else if (C_DECL_VARIABLE_SIZE (decl))
          {
-           error ("elements of array '%D' have incomplete type", decl);
+           /* Although C99 is unclear about whether incomplete arrays
+              of VLAs themselves count as VLAs, it does not make
+              sense to permit them to be initialized given that
+              ordinary VLAs may not be initialized.  */
+           error ("variable-sized object may not be initialized");
            initialized = 0;
          }
       }
@@ -3038,13 +3178,13 @@ start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (decl)))
     {
-      tree ce = declarator;
+      struct c_declarator *ce = declarator;
 
-      if (TREE_CODE (ce) == INDIRECT_REF)
-       ce = TREE_OPERAND (declarator, 0);
-      if (TREE_CODE (ce) == CALL_EXPR)
+      if (ce->kind == cdk_pointer)
+       ce = declarator->declarator;
+      if (ce->kind == cdk_function)
        {
-         tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1));
+         tree args = ce->u.arg_info->parms;
          for (; args; args = TREE_CHAIN (args))
            {
              tree type = TREE_TYPE (args);
@@ -3059,14 +3199,17 @@ start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning ("%Jinline function '%D' given attribute noinline", decl, decl);
+    warning (0, "%Jinline function %qD given attribute noinline", decl, decl);
 
   /* Add this decl to the current scope.
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
 
-  if (initialized)
-    DECL_EXTERNAL (tem) = 0;
+  if (initialized && DECL_EXTERNAL (tem))
+    {
+      DECL_EXTERNAL (tem) = 0;
+      TREE_STATIC (tem) = 1;
+    }
 
   return tem;
 }
@@ -3084,7 +3227,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
   const char *asmspec = 0;
 
   /* If a name was specified, get the string.  */
-  if (current_scope == file_scope)
+  if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+      && DECL_FILE_SCOPE_P (decl))
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -3110,41 +3254,66 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
       && TYPE_DOMAIN (type) == 0
       && TREE_CODE (decl) != TYPE_DECL)
     {
-      int do_default
+      bool do_default
        = (TREE_STATIC (decl)
           /* Even if pedantic, an external linkage array
              may have incomplete type at first.  */
           ? pedantic && !TREE_PUBLIC (decl)
           : !DECL_EXTERNAL (decl));
       int failure
-       = complete_array_type (type, DECL_INITIAL (decl), do_default);
+       = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl),
+                              do_default);
 
       /* Get the completed type made by complete_array_type.  */
       type = TREE_TYPE (decl);
 
-      if (failure == 1)
-       error ("%Jinitializer fails to determine size of '%D'", decl, decl);
-
-      else if (failure == 2)
+      switch (failure)
        {
+       case 1:
+         error ("%Jinitializer fails to determine size of %qD", decl, decl);
+         break;
+
+       case 2:
          if (do_default)
-           error ("%Jarray size missing in '%D'", decl, decl);
+           error ("%Jarray size missing in %qD", decl, decl);
          /* If a `static' var's size isn't known,
             make it extern as well as static, so it does not get
             allocated.
             If it is not `static', then do not mark extern;
             finish_incomplete_decl will give it a default size
             and it will get allocated.  */
-         else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl))
+         else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
            DECL_EXTERNAL (decl) = 1;
+         break;
+
+       case 3:
+         error ("%Jzero or negative size array %qD", decl, decl);
+         break;
+
+       case 0:
+         /* For global variables, update the copy of the type that
+            exists in the binding.  */
+         if (TREE_PUBLIC (decl))
+           {
+             struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
+             while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+               b_ext = b_ext->shadowed;
+             if (b_ext)
+               {
+                 if (b_ext->type)
+                   b_ext->type = composite_type (b_ext->type, type);
+                 else
+                   b_ext->type = type;
+               }
+           }
+         break;
+
+       default:
+         gcc_unreachable ();
        }
 
-      /* TYPE_MAX_VALUE is always one less than the number of elements
-        in the array, because we start counting at zero.  Therefore,
-        warn only if the value is less than zero.  */
-      else if (pedantic && TYPE_DOMAIN (type) != 0
-              && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
-       error ("%Jzero or negative size array '%D'", decl, decl);
+      if (DECL_INITIAL (decl))
+       TREE_TYPE (DECL_INITIAL (decl)) = type;
 
       layout_decl (decl, 0);
     }
@@ -3170,7 +3339,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
                 is an error.  */
              : !DECL_EXTERNAL (decl)))
         {
-          error ("%Jstorage size of '%D' isn't known", decl, decl);
+          error ("%Jstorage size of %qD isn%'t known", decl, decl);
           TREE_TYPE (decl) = error_mark_node;
         }
 
@@ -3180,7 +3349,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
          if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
            constant_expression_warning (DECL_SIZE (decl));
          else
-           error ("%Jstorage size of '%D' isn't constant", decl, decl);
+           error ("%Jstorage size of %qD isn%'t constant", decl, decl);
        }
 
       if (TREE_USED (type))
@@ -3193,20 +3362,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
       if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
-       {
-         tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
-         set_user_assembler_name (builtin, asmspec);
-          if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
-            init_block_move_fn (asmspec);
-          else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
-            init_block_clear_fn (asmspec);
-        }
+       set_builtin_user_assembler_name (decl, asmspec);
       set_user_assembler_name (decl, asmspec);
     }
 
   /* If #pragma weak was used, mark the decl weak now.  */
-  if (current_scope == file_scope)
-    maybe_apply_pragma_weak (decl);
+  maybe_apply_pragma_weak (decl);
 
   /* If this is a variable definition, determine its ELF visibility.  */
   if (TREE_CODE (decl) == VAR_DECL 
@@ -3231,12 +3392,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
             ordinary, non-register local variable.  Historically,
             GCC has accepted -- but ignored -- the ASMSPEC in
             this case.  */
-         if (! DECL_FILE_SCOPE_P (decl)
+         if (!DECL_FILE_SCOPE_P (decl)
              && TREE_CODE (decl) == VAR_DECL
              && !C_DECL_REGISTER (decl)
              && !TREE_STATIC (decl))
-           warning ("%Jignoring asm-specifier for non-static local "
-                    "variable '%D'", decl, decl);
+           warning (0, "%Jignoring asm-specifier for non-static local "
+                    "variable %qD", decl, decl);
          else if (C_DECL_REGISTER (decl))
            change_decl_assembler_name (decl, get_identifier (asmspec));
          else
@@ -3295,7 +3456,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
          /* Recompute the RTL of a local array now
             if it used to be an incomplete type.  */
          if (was_incomplete
-             && ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
+             && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
            {
              /* If we used it already as memory, it must stay in memory.  */
              TREE_ADDRESSABLE (decl) = TREE_USED (decl);
@@ -3363,13 +3524,12 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
 /* Given a parsed parameter declaration, decode it into a PARM_DECL.  */
 
 tree
-grokparm (tree parm)
+grokparm (const struct c_parm *parm)
 {
-  tree decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
-                             TREE_PURPOSE (TREE_PURPOSE (parm)),
-                             PARM, false, NULL);
+  tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
+                             NULL);
 
-  decl_attributes (&decl, TREE_VALUE (parm), 0);
+  decl_attributes (&decl, parm->attrs, 0);
 
   return decl;
 }
@@ -3378,14 +3538,12 @@ grokparm (tree parm)
    and push that on the current scope.  */
 
 void
-push_parm_decl (tree parm)
+push_parm_decl (const struct c_parm *parm)
 {
   tree decl;
 
-  decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
-                        TREE_PURPOSE (TREE_PURPOSE (parm)),
-                        PARM, false, NULL);
-  decl_attributes (&decl, TREE_VALUE (parm), 0);
+  decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+  decl_attributes (&decl, parm->attrs, 0);
 
   decl = pushdecl (decl);
 
@@ -3424,9 +3582,14 @@ build_compound_literal (tree type, tree init)
   /* We do not use start_decl here because we have a type, not a declarator;
      and do not use finish_decl because the decl should be stored inside
      the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR.  */
-  tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+  tree decl;
   tree complit;
   tree stmt;
+
+  if (type == error_mark_node)
+    return error_mark_node;
+
+  decl = build_decl (VAR_DECL, NULL_TREE, type);
   DECL_EXTERNAL (decl) = 0;
   TREE_PUBLIC (decl) = 0;
   TREE_STATIC (decl) = (current_scope == file_scope);
@@ -3438,17 +3601,19 @@ build_compound_literal (tree type, tree init)
 
   if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
     {
-      int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
-      if (failure)
-       abort ();
+      int failure = complete_array_type (&TREE_TYPE (decl),
+                                        DECL_INITIAL (decl), true);
+      gcc_assert (!failure);
+
+      type = TREE_TYPE (decl);
+      TREE_TYPE (DECL_INITIAL (decl)) = type;
     }
 
-  type = TREE_TYPE (decl);
   if (type == error_mark_node || !COMPLETE_TYPE_P (type))
     return error_mark_node;
 
   stmt = build_stmt (DECL_EXPR, decl);
-  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+  complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
   TREE_SIDE_EFFECTS (complit) = 1;
 
   layout_decl (decl, 0);
@@ -3466,6 +3631,7 @@ build_compound_literal (tree type, tree init)
       DECL_DEFER_OUTPUT (decl) = 1;
       DECL_COMDAT (decl) = 1;
       DECL_ARTIFICIAL (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
       pushdecl (decl);
       rest_of_decl_compilation (decl, 1, 0);
     }
@@ -3473,73 +3639,6 @@ build_compound_literal (tree type, tree init)
   return complit;
 }
 \f
-/* Make TYPE a complete type based on INITIAL_VALUE.
-   Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
-   2 if there was no information (in which case assume 1 if DO_DEFAULT).  */
-
-int
-complete_array_type (tree type, tree initial_value, int do_default)
-{
-  tree maxindex = NULL_TREE;
-  int value = 0;
-
-  if (initial_value)
-    {
-      /* Note MAXINDEX  is really the maximum index,
-        one less than the size.  */
-      if (TREE_CODE (initial_value) == STRING_CST)
-       {
-         int eltsize
-           = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
-         maxindex = build_int_cst (NULL_TREE,
-                                   (TREE_STRING_LENGTH (initial_value)
-                                    / eltsize) - 1);
-       }
-      else if (TREE_CODE (initial_value) == CONSTRUCTOR)
-       {
-         tree elts = CONSTRUCTOR_ELTS (initial_value);
-         maxindex = build_int_cst (NULL_TREE, -1);
-         for (; elts; elts = TREE_CHAIN (elts))
-           {
-             if (TREE_PURPOSE (elts))
-               maxindex = TREE_PURPOSE (elts);
-             else
-               maxindex = fold (build2 (PLUS_EXPR, integer_type_node,
-                                        maxindex, integer_one_node));
-           }
-       }
-      else
-       {
-         /* Make an error message unless that happened already.  */
-         if (initial_value != error_mark_node)
-           value = 1;
-
-         /* Prevent further error messages.  */
-         maxindex = build_int_cst (NULL_TREE, 0);
-       }
-    }
-
-  if (!maxindex)
-    {
-      if (do_default)
-       maxindex = build_int_cst (NULL_TREE, 0);
-      value = 2;
-    }
-
-  if (maxindex)
-    {
-      TYPE_DOMAIN (type) = build_index_type (maxindex);
-      if (!TREE_TYPE (maxindex))
-       abort ();
-    }
-
-  /* Lay out the type now that we can get the real answer.  */
-
-  layout_type (type);
-
-  return value;
-}
-\f
 /* Determine whether TYPE is a structure with a flexible array member,
    or a union containing such a structure (possibly recursively).  */
 
@@ -3583,14 +3682,12 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
   unsigned HOST_WIDE_INT w;
   const char *name = orig_name ? orig_name: _("<anonymous>");
 
-  /* Necessary?  */
-  STRIP_NOPS (*width);
-
   /* Detect and ignore out of range field width and process valid
      field widths.  */
-  if (TREE_CODE (*width) != INTEGER_CST)
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (*width))
+      || TREE_CODE (*width) != INTEGER_CST)
     {
-      error ("bit-field `%s' width not an integer constant", name);
+      error ("bit-field %qs width not an integer constant", name);
       *width = integer_one_node;
     }
   else
@@ -3598,12 +3695,12 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
       constant_expression_warning (*width);
       if (tree_int_cst_sgn (*width) < 0)
        {
-         error ("negative width in bit-field `%s'", name);
+         error ("negative width in bit-field %qs", name);
          *width = integer_one_node;
        }
       else if (integer_zerop (*width) && orig_name)
        {
-         error ("zero width for bit-field `%s'", name);
+         error ("zero width for bit-field %qs", name);
          *width = integer_one_node;
        }
     }
@@ -3613,7 +3710,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
       && TREE_CODE (*type) != BOOLEAN_TYPE
       && TREE_CODE (*type) != ENUMERAL_TYPE)
     {
-      error ("bit-field `%s' has invalid type", name);
+      error ("bit-field %qs has invalid type", name);
       *type = unsigned_type_node;
     }
 
@@ -3622,7 +3719,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
       && type_mv != integer_type_node
       && type_mv != unsigned_type_node
       && type_mv != boolean_type_node)
-    pedwarn ("type of bit-field `%s' is a GCC extension", name);
+    pedwarn ("type of bit-field %qs is a GCC extension", name);
 
   if (type_mv == boolean_type_node)
     max_width = CHAR_TYPE_SIZE;
@@ -3631,7 +3728,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
 
   if (0 < compare_tree_int (*width, max_width))
     {
-      error ("width of `%s' exceeds its type", name);
+      error ("width of %qs exceeds its type", name);
       w = max_width;
       *width = build_int_cst (NULL_TREE, w);
     }
@@ -3644,7 +3741,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
       if (!lt
           || w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
          || w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
-       warning ("`%s' is narrower than values of its type", name);
+       warning (0, "%qs is narrower than values of its type", name);
     }
 }
 \f
@@ -3654,8 +3751,7 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
    (In one case we can return a ..._TYPE node instead.
     For invalid input we sometimes return 0.)
 
-   DECLSPECS is a chain of tree_list nodes whose value fields
-    are the storage classes and type specifiers.
+   DECLSPECS is a c_declspecs structure for the declaration specifiers.
 
    DECL_CONTEXT says which syntactic context this declaration is in:
      NORMAL for most contexts.  Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
@@ -3679,34 +3775,30 @@ check_bitfield_type_and_width (tree *type, tree *width, const char *orig_name)
    and `extern' are interpreted.  */
 
 static tree
-grokdeclarator (tree declarator, tree declspecs,
+grokdeclarator (const struct c_declarator *declarator,
+               struct c_declspecs *declspecs,
                enum decl_context decl_context, bool initialized, tree *width)
 {
-  int specbits = 0;
-  tree spec;
-  tree type = NULL_TREE;
-  int longlong = 0;
+  tree type = declspecs->type;
+  bool threadp = declspecs->thread_p;
+  enum c_storage_class storage_class = declspecs->storage_class;
   int constp;
   int restrictp;
   int volatilep;
   int type_quals = TYPE_UNQUALIFIED;
-  int inlinep;
-  int explicit_int = 0;
-  int explicit_char = 0;
-  int defaulted_int = 0;
-  tree typedef_decl = 0;
   const char *name, *orig_name;
   tree typedef_type = 0;
   int funcdef_flag = 0;
-  enum tree_code innermost_code = ERROR_MARK;
+  bool funcdef_syntax = false;
   int size_varies = 0;
-  tree decl_attr = NULL_TREE;
-  tree array_ptr_quals = NULL_TREE;
+  tree decl_attr = declspecs->decl_attr;
+  int array_ptr_quals = TYPE_UNQUALIFIED;
+  tree array_ptr_attrs = NULL_TREE;
   int array_parm_static = 0;
   tree returned_attrs = NULL_TREE;
   bool bitfield = width != NULL;
   tree element_type;
-  tree arg_info = NULL_TREE;
+  struct c_arg_info *arg_info = 0;
 
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
@@ -3714,30 +3806,31 @@ grokdeclarator (tree declarator, tree declspecs,
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   {
-    tree decl = declarator;
+    const struct c_declarator *decl = declarator;
     name = 0;
 
     while (decl)
-      switch (TREE_CODE (decl))
+      switch (decl->kind)
        {
-       case ARRAY_REF:
-       case INDIRECT_REF:
-       case CALL_EXPR:
-         innermost_code = TREE_CODE (decl);
-         decl = TREE_OPERAND (decl, 0);
+       case cdk_function:
+       case cdk_array:
+       case cdk_pointer:
+         funcdef_syntax = (decl->kind == cdk_function);
+         decl = decl->declarator;
          break;
 
-       case TREE_LIST:
-         decl = TREE_VALUE (decl);
+       case cdk_attrs:
+         decl = decl->declarator;
          break;
 
-       case IDENTIFIER_NODE:
-         name = IDENTIFIER_POINTER (decl);
+       case cdk_id:
+         if (decl->u.id)
+           name = IDENTIFIER_POINTER (decl->u.id);
          decl = 0;
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     orig_name = name;
     if (name == 0)
@@ -3747,7 +3840,7 @@ grokdeclarator (tree declarator, tree declspecs,
   /* A function definition's declarator must have the form of
      a function declarator.  */
 
-  if (funcdef_flag && innermost_code != CALL_EXPR)
+  if (funcdef_flag && !funcdef_syntax)
     return 0;
 
   /* If this looks like a function definition, make it one,
@@ -3756,296 +3849,32 @@ grokdeclarator (tree declarator, tree declspecs,
   if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
     decl_context = PARM;
 
-  /* Look through the decl specs and record which ones appear.
-     Some typespecs are defined as built-in typenames.
-     Others, the ones that are modifiers of other types,
-     are represented by bits in SPECBITS: set the bits for
-     the modifiers that appear.  Storage class keywords are also in SPECBITS.
-
-     If there is a typedef name or a type, store the type in TYPE.
-     This includes builtin typedefs such as `int'.
+  if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
+    warn_deprecated_use (declspecs->type);
 
-     Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char'
-     and did not come from a user typedef.
+  typedef_type = type;
+  size_varies = C_TYPE_VARIABLE_SIZE (type);
 
-     Set LONGLONG if `long' is mentioned twice.  */
+  /* Diagnose defaulting to "int".  */
 
-  for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+  if (declspecs->default_int_p && !in_system_header)
     {
-      tree id = TREE_VALUE (spec);
-
-      /* If the entire declaration is itself tagged as deprecated then
-         suppress reports of deprecated items.  */
-      if (id && TREE_DEPRECATED (id))
-        {
-         if (deprecated_state != DEPRECATED_SUPPRESS)
-           warn_deprecated_use (id);
-        }
-
-      if (id == ridpointers[(int) RID_INT])
-       explicit_int = 1;
-      if (id == ridpointers[(int) RID_CHAR])
-       explicit_char = 1;
-
-      if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
-       {
-         enum rid i = C_RID_CODE (id);
-         if ((int) i <= (int) RID_LAST_MODIFIER)
-           {
-             if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
-               {
-                 if (longlong)
-                   error ("`long long long' is too long for GCC");
-                 else
-                   {
-                     if (pedantic && !flag_isoc99 && ! in_system_header
-                         && warn_long_long)
-                       pedwarn ("ISO C90 does not support `long long'");
-                     longlong = 1;
-                   }
-               }
-             else if (specbits & (1 << (int) i))
-               {
-                 if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
-                   {
-                     if (pedantic && !flag_isoc99)
-                       pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
-                   }
-                 else
-                   error ("duplicate `%s'", IDENTIFIER_POINTER (id));
-               }
+      /* Issue a warning if this is an ISO C 99 program or if
+        -Wreturn-type and this is a function, or if -Wimplicit;
+        prefer the former warning since it is more explicit.  */
+      if ((warn_implicit_int || warn_return_type || flag_isoc99)
+         && funcdef_flag)
+       warn_about_return_type = 1;
+      else if (warn_implicit_int || flag_isoc99)
+       pedwarn_c99 ("type defaults to %<int%> in declaration of %qs", name);
+    }
 
-             /* Diagnose "__thread extern".  Recall that this list
-                is in the reverse order seen in the text.  */
-             if (i == RID_THREAD
-                 && (specbits & (1 << (int) RID_EXTERN
-                                 | 1 << (int) RID_STATIC)))
-               {
-                 if (specbits & 1 << (int) RID_EXTERN)
-                   error ("`__thread' before `extern'");
-                 else
-                   error ("`__thread' before `static'");
-               }
-
-             specbits |= 1 << (int) i;
-             goto found;
-           }
-       }
-      if (type)
-       error ("two or more data types in declaration of `%s'", name);
-      /* Actual typedefs come to us as TYPE_DECL nodes.  */
-      else if (TREE_CODE (id) == TYPE_DECL)
-       {
-         if (TREE_TYPE (id) == error_mark_node)
-           ; /* Allow the type to default to int to avoid cascading errors.  */
-         else
-           {
-             type = TREE_TYPE (id);
-             decl_attr = DECL_ATTRIBUTES (id);
-             typedef_decl = id;
-           }
-       }
-      /* Built-in types come as identifiers.  */
-      else if (TREE_CODE (id) == IDENTIFIER_NODE)
-       {
-         tree t = lookup_name (id);
-          if (!t || TREE_CODE (t) != TYPE_DECL)
-           error ("`%s' fails to be a typedef or built in type",
-                  IDENTIFIER_POINTER (id));
-          else if (TREE_TYPE (t) == error_mark_node)
-           ;
-         else
-           {
-             type = TREE_TYPE (t);
-             typedef_decl = t;
-           }
-       }
-      else if (TREE_CODE (id) != ERROR_MARK)
-       type = id;
-
-    found:
-      ;
-    }
-
-  typedef_type = type;
-  if (type)
-    size_varies = C_TYPE_VARIABLE_SIZE (type);
-
-  /* No type at all: default to `int', and set DEFAULTED_INT
-     because it was not a user-defined typedef.  */
-
-  if (type == 0)
-    {
-      if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                         | (1 << (int) RID_SIGNED)
-                         | (1 << (int) RID_UNSIGNED)
-                         | (1 << (int) RID_COMPLEX))))
-         /* Don't warn about typedef foo = bar.  */
-         && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
-         && ! in_system_header)
-       {
-         /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type
-            and this is a function, or if -Wimplicit; prefer the former
-            warning since it is more explicit.  */
-         if ((warn_implicit_int || warn_return_type || flag_isoc99)
-             && funcdef_flag)
-           warn_about_return_type = 1;
-         else if (warn_implicit_int || flag_isoc99)
-           pedwarn_c99 ("type defaults to `int' in declaration of `%s'",
-                        name);
-       }
-
-      defaulted_int = 1;
-      type = integer_type_node;
-    }
-
-  /* Now process the modifiers that were specified
-     and check for invalid combinations.  */
-
-  /* Long double is a special combination.  */
-
-  if ((specbits & 1 << (int) RID_LONG) && ! longlong
-      && TYPE_MAIN_VARIANT (type) == double_type_node)
-    {
-      specbits &= ~(1 << (int) RID_LONG);
-      type = long_double_type_node;
-    }
-
-  /* Check all other uses of type modifiers.  */
-
-  if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                 | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)))
-    {
-      int ok = 0;
-
-      if ((specbits & 1 << (int) RID_LONG)
-         && (specbits & 1 << (int) RID_SHORT))
-       error ("both long and short specified for `%s'", name);
-      else if (((specbits & 1 << (int) RID_LONG)
-               || (specbits & 1 << (int) RID_SHORT))
-              && explicit_char)
-       error ("long or short specified with char for `%s'", name);
-      else if (((specbits & 1 << (int) RID_LONG)
-               || (specbits & 1 << (int) RID_SHORT))
-              && TREE_CODE (type) == REAL_TYPE)
-       {
-         static int already = 0;
-
-         error ("long or short specified with floating type for `%s'", name);
-         if (! already && ! pedantic)
-           {
-             error ("the only valid combination is `long double'");
-             already = 1;
-           }
-       }
-      else if ((specbits & 1 << (int) RID_SIGNED)
-              && (specbits & 1 << (int) RID_UNSIGNED))
-       error ("both signed and unsigned specified for `%s'", name);
-      else if (TREE_CODE (type) != INTEGER_TYPE)
-       error ("long, short, signed or unsigned invalid for `%s'", name);
-      else
-       {
-         ok = 1;
-         if (!explicit_int && !defaulted_int && !explicit_char)
-           {
-             error ("long, short, signed or unsigned used invalidly for `%s'",
-                    name);
-             ok = 0;
-           }
-       }
-
-      /* Discard the type modifiers if they are invalid.  */
-      if (! ok)
-       {
-         specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                       | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED));
-         longlong = 0;
-       }
-    }
-
-  if ((specbits & (1 << (int) RID_COMPLEX))
-      && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
-    {
-      error ("complex invalid for `%s'", name);
-      specbits &= ~(1 << (int) RID_COMPLEX);
-    }
-
-  /* Decide whether an integer type is signed or not.
-     Optionally treat bit-fields as signed by default.  */
-  if (specbits & 1 << (int) RID_UNSIGNED
-      || (bitfield && ! flag_signed_bitfields
-         && (explicit_int || defaulted_int || explicit_char
-             /* A typedef for plain `int' without `signed'
-                can be controlled just like plain `int'.  */
-             || ! (typedef_decl != 0
-                   && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
-         && TREE_CODE (type) != ENUMERAL_TYPE
-         && !(specbits & 1 << (int) RID_SIGNED)))
-    {
-      if (longlong)
-       type = long_long_unsigned_type_node;
-      else if (specbits & 1 << (int) RID_LONG)
-       type = long_unsigned_type_node;
-      else if (specbits & 1 << (int) RID_SHORT)
-       type = short_unsigned_type_node;
-      else if (type == char_type_node)
-       type = unsigned_char_type_node;
-      else if (typedef_decl)
-       type = c_common_unsigned_type (type);
-      else
-       type = unsigned_type_node;
-    }
-  else if ((specbits & 1 << (int) RID_SIGNED)
-          && type == char_type_node)
-    type = signed_char_type_node;
-  else if (longlong)
-    type = long_long_integer_type_node;
-  else if (specbits & 1 << (int) RID_LONG)
-    type = long_integer_type_node;
-  else if (specbits & 1 << (int) RID_SHORT)
-    type = short_integer_type_node;
-
-  if (specbits & 1 << (int) RID_COMPLEX)
-    {
-      if (pedantic && !flag_isoc99)
-       pedwarn ("ISO C90 does not support complex types");
-      /* If we just have "complex", it is equivalent to
-        "complex double", but if any modifiers at all are specified it is
-        the complex form of TYPE.  E.g, "complex short" is
-        "complex short int".  */
-
-      if (defaulted_int && ! longlong
-         && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                           | (1 << (int) RID_SIGNED)
-                           | (1 << (int) RID_UNSIGNED))))
-       {
-         if (pedantic)
-           pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
-         type = complex_double_type_node;
-       }
-      else if (type == integer_type_node)
-       {
-         if (pedantic)
-           pedwarn ("ISO C does not support complex integer types");
-         type = complex_integer_type_node;
-       }
-      else if (type == float_type_node)
-       type = complex_float_type_node;
-      else if (type == double_type_node)
-       type = complex_double_type_node;
-      else if (type == long_double_type_node)
-       type = complex_long_double_type_node;
-      else
-       {
-         if (pedantic)
-           pedwarn ("ISO C does not support complex integer types");
-         type = build_complex_type (type);
-       }
-    }
-
-  /* Check the type and width of a bit-field.  */
-  if (bitfield)
-    check_bitfield_type_and_width (&type, width, orig_name);
+  /* Adjust the type if a bit-field is being declared,
+     -funsigned-bitfields applied and the type is not explicitly
+     "signed".  */
+  if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p
+      && TREE_CODE (type) == INTEGER_TYPE)
+    type = c_common_unsigned_type (type);
 
   /* Figure out the type qualifiers for the declaration.  There are
      two ways a declaration can become qualified.  One is something
@@ -4059,141 +3888,127 @@ grokdeclarator (tree declarator, tree declspecs,
      duplicate qualifiers should be diagnosed in this case, but it
      seems most appropriate to do so).  */
   element_type = strip_array_types (type);
-  constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (element_type);
-  restrictp
-    = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (element_type);
-  volatilep
-    = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type);
-  inlinep = !! (specbits & (1 << (int) RID_INLINE));
+  constp = declspecs->const_p + TYPE_READONLY (element_type);
+  restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
+  volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
   if (pedantic && !flag_isoc99)
     {
       if (constp > 1)
-       pedwarn ("duplicate `const'");
+       pedwarn ("duplicate %<const%>");
       if (restrictp > 1)
-       pedwarn ("duplicate `restrict'");
+       pedwarn ("duplicate %<restrict%>");
       if (volatilep > 1)
-       pedwarn ("duplicate `volatile'");
+       pedwarn ("duplicate %<volatile%>");
     }
-  if (! flag_gen_aux_info && (TYPE_QUALS (type)))
+  if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
     type = TYPE_MAIN_VARIANT (type);
   type_quals = ((constp ? TYPE_QUAL_CONST : 0)
                | (restrictp ? TYPE_QUAL_RESTRICT : 0)
                | (volatilep ? TYPE_QUAL_VOLATILE : 0));
 
-  /* Warn if two storage classes are given. Default to `auto'.  */
-
-  {
-    int nclasses = 0;
-
-    if (specbits & 1 << (int) RID_AUTO) nclasses++;
-    if (specbits & 1 << (int) RID_STATIC) nclasses++;
-    if (specbits & 1 << (int) RID_EXTERN) nclasses++;
-    if (specbits & 1 << (int) RID_REGISTER) nclasses++;
-    if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
-
-    /* "static __thread" and "extern __thread" are allowed.  */
-    if ((specbits & (1 << (int) RID_THREAD
-                    | 1 << (int) RID_STATIC
-                    | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
-      nclasses++;
-
-    /* Warn about storage classes that are invalid for certain
-       kinds of declarations (parameters, typenames, etc.).  */
-
-    if (nclasses > 1)
-      error ("multiple storage classes in declaration of `%s'", name);
-    else if (funcdef_flag
-            && (specbits
-                & ((1 << (int) RID_REGISTER)
-                   | (1 << (int) RID_AUTO)
-                   | (1 << (int) RID_TYPEDEF)
-                   | (1 << (int) RID_THREAD))))
-      {
-       if (specbits & 1 << (int) RID_AUTO
-           && (pedantic || current_scope == file_scope))
-         pedwarn ("function definition declared `auto'");
-       if (specbits & 1 << (int) RID_REGISTER)
-         error ("function definition declared `register'");
-       if (specbits & 1 << (int) RID_TYPEDEF)
-         error ("function definition declared `typedef'");
-       if (specbits & 1 << (int) RID_THREAD)
-         error ("function definition declared `__thread'");
-       specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
-                     | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
-      }
-    else if (decl_context != NORMAL && nclasses > 0)
-      {
-       if (decl_context == PARM && specbits & 1 << (int) RID_REGISTER)
-         ;
-       else
-         {
-           switch (decl_context)
-             {
-             case FIELD:
-               error ("storage class specified for structure field `%s'",
-                      name);
-               break;
-             case PARM:
-               error ("storage class specified for parameter `%s'", name);
-               break;
-             default:
-               error ("storage class specified for typename");
-               break;
-             }
-           specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
-                         | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
-                         | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
-         }
-      }
-    else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
-      {
-       /* `extern' with initialization is invalid if not at file scope.  */
-       if (current_scope == file_scope)
-         warning ("`%s' initialized and declared `extern'", name);
-       else
-         error ("`%s' has both `extern' and initializer", name);
-      }
-    else if (current_scope == file_scope)
-      {
-       if (specbits & 1 << (int) RID_AUTO)
-         error ("file-scope declaration of `%s' specifies `auto'", name);
-      }
-    else
-      {
-       if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
-         error ("nested function `%s' declared `extern'", name);
-       else if ((specbits & (1 << (int) RID_THREAD
-                              | 1 << (int) RID_EXTERN
-                              | 1 << (int) RID_STATIC))
-                == (1 << (int) RID_THREAD))
-         {
-           error ("function-scope `%s' implicitly auto and declared `__thread'",
-                  name);
-           specbits &= ~(1 << (int) RID_THREAD);
-         }
-      }
-  }
+  /* Warn about storage classes that are invalid for certain
+     kinds of declarations (parameters, typenames, etc.).  */
+
+  if (funcdef_flag
+      && (threadp
+         || storage_class == csc_auto
+         || storage_class == csc_register
+         || storage_class == csc_typedef))
+    {
+      if (storage_class == csc_auto
+         && (pedantic || current_scope == file_scope))
+       pedwarn ("function definition declared %<auto%>");
+      if (storage_class == csc_register)
+       error ("function definition declared %<register%>");
+      if (storage_class == csc_typedef)
+       error ("function definition declared %<typedef%>");
+      if (threadp)
+       error ("function definition declared %<__thread%>");
+      threadp = false;
+      if (storage_class == csc_auto
+         || storage_class == csc_register
+         || storage_class == csc_typedef)
+       storage_class = csc_none;
+    }
+  else if (decl_context != NORMAL && (storage_class != csc_none || threadp))
+    {
+      if (decl_context == PARM && storage_class == csc_register)
+       ;
+      else
+       {
+         switch (decl_context)
+           {
+           case FIELD:
+             error ("storage class specified for structure field %qs",
+                    name);
+             break;
+           case PARM:
+             error ("storage class specified for parameter %qs", name);
+             break;
+           default:
+             error ("storage class specified for typename");
+             break;
+           }
+         storage_class = csc_none;
+         threadp = false;
+       }
+    }
+  else if (storage_class == csc_extern
+          && initialized
+          && !funcdef_flag)
+    {
+      /* 'extern' with initialization is invalid if not at file scope.  */
+      if (current_scope == file_scope)
+       warning (0, "%qs initialized and declared %<extern%>", name);
+      else
+       error ("%qs has both %<extern%> and initializer", name);
+    }
+  else if (current_scope == file_scope)
+    {
+      if (storage_class == csc_auto)
+       error ("file-scope declaration of %qs specifies %<auto%>", name);
+      if (pedantic && storage_class == csc_register)
+       pedwarn ("file-scope declaration of %qs specifies %<register%>", name);
+    }
+  else
+    {
+      if (storage_class == csc_extern && funcdef_flag)
+       error ("nested function %qs declared %<extern%>", name);
+      else if (threadp && storage_class == csc_none)
+       {
+         error ("function-scope %qs implicitly auto and declared "
+                "%<__thread%>",
+                name);
+         threadp = false;
+       }
+    }
 
   /* Now figure out the structure of the declarator proper.
      Descend through it, creating more complex types, until we reach
-     the declared identifier (or NULL_TREE, in an absolute declarator).  */
+     the declared identifier (or NULL_TREE, in an absolute declarator).
+     At each stage we maintain an unqualified version of the type
+     together with any qualifiers that should be applied to it with
+     c_build_qualified_type; this way, array types including
+     multidimensional array types are first built up in unqualified
+     form and then the qualified form is created with
+     TYPE_MAIN_VARIANT pointing to the unqualified form.  */
 
-  while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
+  while (declarator && declarator->kind != cdk_id)
     {
       if (type == error_mark_node)
        {
-         declarator = TREE_OPERAND (declarator, 0);
+         declarator = declarator->declarator;
          continue;
        }
 
-      /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
-        an INDIRECT_REF (for *...),
-        a CALL_EXPR (for ...(...)),
-        a TREE_LIST (for nested attributes),
-        an identifier (for the name being declared)
-        or a null pointer (for the place in an absolute declarator
+      /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
+        a cdk_pointer (for *...),
+        a cdk_function (for ...(...)),
+        a cdk_attrs (for nested attributes),
+        or a cdk_id (for the name being declared
+        or the place in an absolute declarator
         where the name was omitted).
-        For the last two cases, we have just exited the loop.
+        For the last case, we have just exited the loop.
 
         At this point, TYPE is the type of elements of an array,
         or for a function to return, or for a pointer to point to.
@@ -4201,346 +4016,316 @@ grokdeclarator (tree declarator, tree declspecs,
         array or function or pointer, and DECLARATOR has had its
         outermost layer removed.  */
 
-      if (array_ptr_quals != NULL_TREE || array_parm_static)
+      if (array_ptr_quals != TYPE_UNQUALIFIED
+         || array_ptr_attrs != NULL_TREE
+         || array_parm_static)
        {
          /* Only the innermost declarator (making a parameter be of
             array type which is converted to pointer type)
             may have static or type qualifiers.  */
          error ("static or type qualifiers in non-parameter array declarator");
-         array_ptr_quals = NULL_TREE;
+         array_ptr_quals = TYPE_UNQUALIFIED;
+         array_ptr_attrs = NULL_TREE;
          array_parm_static = 0;
        }
 
-      if (TREE_CODE (declarator) == TREE_LIST)
+      switch (declarator->kind)
        {
-         /* We encode a declarator with embedded attributes using
-            a TREE_LIST.  */
-         tree attrs = TREE_PURPOSE (declarator);
-         tree inner_decl;
-         int attr_flags = 0;
-         declarator = TREE_VALUE (declarator);
-         inner_decl = declarator;
-         while (inner_decl != NULL_TREE
-                && TREE_CODE (inner_decl) == TREE_LIST)
-           inner_decl = TREE_VALUE (inner_decl);
-         if (inner_decl == NULL_TREE
-             || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
-           attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
-         else if (TREE_CODE (inner_decl) == CALL_EXPR)
-           attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
-         else if (TREE_CODE (inner_decl) == ARRAY_REF)
-           attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
-         returned_attrs = decl_attributes (&type,
-                                           chainon (returned_attrs, attrs),
-                                           attr_flags);
-       }
-      else if (TREE_CODE (declarator) == ARRAY_REF)
-       {
-         tree itype = NULL_TREE;
-         tree size = TREE_OPERAND (declarator, 1);
-         /* The index is a signed object `sizetype' bits wide.  */
-         tree index_type = c_common_signed_type (sizetype);
-
-         array_ptr_quals = TREE_TYPE (declarator);
-         array_parm_static = TREE_STATIC (declarator);
-
-         declarator = TREE_OPERAND (declarator, 0);
-
-         /* Check for some types that there cannot be arrays of.  */
-
-         if (VOID_TYPE_P (type))
-           {
-             error ("declaration of `%s' as array of voids", name);
-             type = error_mark_node;
-           }
-
-         if (TREE_CODE (type) == FUNCTION_TYPE)
-           {
-             error ("declaration of `%s' as array of functions", name);
+       case cdk_attrs:
+         {
+           /* A declarator with embedded attributes.  */
+           tree attrs = declarator->u.attrs;
+           const struct c_declarator *inner_decl;
+           int attr_flags = 0;
+           declarator = declarator->declarator;
+           inner_decl = declarator;
+           while (inner_decl->kind == cdk_attrs)
+             inner_decl = inner_decl->declarator;
+           if (inner_decl->kind == cdk_id)
+             attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+           else if (inner_decl->kind == cdk_function)
+             attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+           else if (inner_decl->kind == cdk_array)
+             attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+           returned_attrs = decl_attributes (&type,
+                                             chainon (returned_attrs, attrs),
+                                             attr_flags);
+           break;
+         }
+       case cdk_array:
+         {
+           tree itype = NULL_TREE;
+           tree size = declarator->u.array.dimen;
+           /* The index is a signed object `sizetype' bits wide.  */
+           tree index_type = c_common_signed_type (sizetype);
+
+           array_ptr_quals = declarator->u.array.quals;
+           array_ptr_attrs = declarator->u.array.attrs;
+           array_parm_static = declarator->u.array.static_p;
+           
+           declarator = declarator->declarator;
+
+           /* Check for some types that there cannot be arrays of.  */
+           
+           if (VOID_TYPE_P (type))
+             {
+               error ("declaration of %qs as array of voids", name);
+               type = error_mark_node;
+             }
+           
+           if (TREE_CODE (type) == FUNCTION_TYPE)
+             {
+               error ("declaration of %qs as array of functions", name);
+               type = error_mark_node;
+             }
+           
+           if (pedantic && !in_system_header && flexible_array_type_p (type))
+             pedwarn ("invalid use of structure with flexible array member");
+           
+           if (size == error_mark_node)
              type = error_mark_node;
-           }
-
-         if (pedantic && !in_system_header && flexible_array_type_p (type))
-           pedwarn ("invalid use of structure with flexible array member");
-
-         if (size == error_mark_node)
-           type = error_mark_node;
-
-         if (type == error_mark_node)
-           continue;
-
-         /* If size was specified, set ITYPE to a range-type for that size.
-            Otherwise, ITYPE remains null.  finish_decl may figure it out
-            from an initial value.  */
-
-         if (size)
-           {
-             /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
-             STRIP_TYPE_NOPS (size);
-
-             if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
-               {
-                 error ("size of array `%s' has non-integer type", name);
-                 size = integer_one_node;
-               }
-
-             if (pedantic && integer_zerop (size))
-               pedwarn ("ISO C forbids zero-size array `%s'", name);
-
-             if (TREE_CODE (size) == INTEGER_CST)
-               {
-                 constant_expression_warning (size);
-                 if (tree_int_cst_sgn (size) < 0)
-                   {
-                     error ("size of array `%s' is negative", name);
-                     size = integer_one_node;
-                   }
-               }
-             else
-               {
-                 /* Make sure the array size remains visibly nonconstant
-                    even if it is (eg) a const variable with known value.  */
-                 size_varies = 1;
-
-                 if (!flag_isoc99 && pedantic)
-                   {
-                     if (TREE_CONSTANT (size))
-                       pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
-                                name);
-                     else
-                       pedwarn ("ISO C90 forbids variable-size array `%s'",
-                                name);
-                   }
-               }
-
-             if (integer_zerop (size))
-               {
-                 /* A zero-length array cannot be represented with an
-                    unsigned index type, which is what we'll get with
-                    build_index_type.  Create an open-ended range instead.  */
-                 itype = build_range_type (sizetype, size, NULL_TREE);
-               }
-             else
-               {
-                 /* Compute the maximum valid index, that is, size - 1.
-                    Do the calculation in index_type, so that if it is
-                    a variable the computations will be done in the
-                    proper mode.  */
-                 itype = fold (build2 (MINUS_EXPR, index_type,
-                                       convert (index_type, size),
-                                       convert (index_type, size_one_node)));
-
-                 /* If that overflowed, the array is too big.
-                    ??? While a size of INT_MAX+1 technically shouldn't
-                    cause an overflow (because we subtract 1), the overflow
-                    is recorded during the conversion to index_type, before
-                    the subtraction.  Handling this case seems like an
-                    unnecessary complication.  */
-                 if (TREE_OVERFLOW (itype))
-                   {
-                     error ("size of array `%s' is too large", name);
-                     type = error_mark_node;
-                     continue;
-                   }
-
-                 if (size_varies)
-                   itype = variable_size (itype);
-                 itype = build_index_type (itype);
-               }
-           }
-         else if (decl_context == FIELD)
-           {
-             if (pedantic && !flag_isoc99 && !in_system_header)
-               pedwarn ("ISO C90 does not support flexible array members");
+           
+           if (type == error_mark_node)
+             continue;
 
-             /* ISO C99 Flexible array members are effectively identical
-                to GCC's zero-length array extension.  */
-             itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
-           }
+           /* If size was specified, set ITYPE to a range-type for
+              that size.  Otherwise, ITYPE remains null.  finish_decl
+              may figure it out from an initial value.  */
 
-         /* If pedantic, complain about arrays of incomplete types.  */
+           if (size)
+             {
+               /* Strip NON_LVALUE_EXPRs since we aren't using as an
+                  lvalue.  */
+               STRIP_TYPE_NOPS (size);
+               
+               if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+                 {
+                   error ("size of array %qs has non-integer type", name);
+                   size = integer_one_node;
+                 }
+               
+               if (pedantic && integer_zerop (size))
+                 pedwarn ("ISO C forbids zero-size array %qs", name);
+               
+               if (TREE_CODE (size) == INTEGER_CST)
+                 {
+                   constant_expression_warning (size);
+                   if (tree_int_cst_sgn (size) < 0)
+                     {
+                       error ("size of array %qs is negative", name);
+                       size = integer_one_node;
+                     }
+                 }
+               else
+                 {
+                   /* Make sure the array size remains visibly
+                      nonconstant even if it is (eg) a const variable
+                      with known value.  */
+                   size_varies = 1;
+                   
+                   if (!flag_isoc99 && pedantic)
+                     {
+                       if (TREE_CONSTANT (size))
+                         pedwarn ("ISO C90 forbids array %qs whose size "
+                                  "can%'t be evaluated",
+                                  name);
+                       else
+                         pedwarn ("ISO C90 forbids variable-size array %qs",
+                                  name);
+                     }
+                 }
 
-         if (pedantic && !COMPLETE_TYPE_P (type))
-           pedwarn ("array type has incomplete element type");
+               if (integer_zerop (size))
+                 {
+                   /*  A zero-length array cannot be represented with
+                       an unsigned index type, which is what we'll
+                       get with build_index_type.  Create an
+                       open-ended range instead.  */
+                   itype = build_range_type (sizetype, size, NULL_TREE);
+                 }
+               else
+                 {
+                   /* Arrange for the SAVE_EXPR on the inside of the
+                      MINUS_EXPR, which allows the -1 to get folded
+                      with the +1 that happens when building TYPE_SIZE.  */
+                   if (size_varies)
+                     size = variable_size (size);
+
+                   /* Compute the maximum valid index, that is, size
+                      - 1.  Do the calculation in index_type, so that
+                      if it is a variable the computations will be
+                      done in the proper mode.  */
+                   itype = fold (build2 (MINUS_EXPR, index_type,
+                                         convert (index_type, size),
+                                         convert (index_type,
+                                                  size_one_node)));
+
+                   /* If that overflowed, the array is too big.  ??? 
+                      While a size of INT_MAX+1 technically shouldn't
+                      cause an overflow (because we subtract 1), the
+                      overflow is recorded during the conversion to
+                      index_type, before the subtraction.  Handling
+                      this case seems like an unnecessary
+                      complication.  */
+                   if (TREE_OVERFLOW (itype))
+                     {
+                       error ("size of array %qs is too large", name);
+                       type = error_mark_node;
+                       continue;
+                     }
+                   
+                   itype = build_index_type (itype);
+                 }
+             }
+           else if (decl_context == FIELD)
+             {
+               if (pedantic && !flag_isoc99 && !in_system_header)
+                 pedwarn ("ISO C90 does not support flexible array members");
 
-         /* Build the array type itself, then merge any constancy or
-            volatility into the target type.  We must do it in this order
-            to ensure that the TYPE_MAIN_VARIANT field of the array type
-            is set correctly.  */
+               /* ISO C99 Flexible array members are effectively
+                  identical to GCC's zero-length array extension.  */
+               itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+             }
 
-         type = build_array_type (type, itype);
-         if (type_quals)
-           type = c_build_qualified_type (type, type_quals);
+            /* Complain about arrays of incomplete types.  */
+           if (!COMPLETE_TYPE_P (type))
+             {
+               error ("array type has incomplete element type");
+               type = error_mark_node;
+             }
+           else
+             type = build_array_type (type, itype);
 
-         if (size_varies)
-           C_TYPE_VARIABLE_SIZE (type) = 1;
+           if (size_varies)
+             C_TYPE_VARIABLE_SIZE (type) = 1;
 
-         /* The GCC extension for zero-length arrays differs from
-            ISO flexible array members in that sizeof yields zero.  */
-         if (size && integer_zerop (size))
-           {
-             layout_type (type);
-             TYPE_SIZE (type) = bitsize_zero_node;
-             TYPE_SIZE_UNIT (type) = size_zero_node;
-           }
-         else if (declarator && TREE_CODE (declarator) == INDIRECT_REF)
-           /* We can never complete an array type which is the target of a
-              pointer, so go ahead and lay it out.  */
-           layout_type (type);
+           /* The GCC extension for zero-length arrays differs from
+              ISO flexible array members in that sizeof yields
+              zero.  */
+           if (size && integer_zerop (size))
+             {
+               TYPE_SIZE (type) = bitsize_zero_node;
+               TYPE_SIZE_UNIT (type) = size_zero_node;
+             }
 
-         if (decl_context != PARM
-             && (array_ptr_quals != NULL_TREE || array_parm_static))
-           {
-             error ("static or type qualifiers in non-parameter array declarator");
-             array_ptr_quals = NULL_TREE;
-             array_parm_static = 0;
-           }
-       }
-      else if (TREE_CODE (declarator) == CALL_EXPR)
-       {
-         /* Say it's a definition only for the declarator closest to
-            the identifier, apart possibly from some attributes.  */
-         bool really_funcdef = false;
-         tree arg_types;
-         if (funcdef_flag)
-           {
-             tree t = TREE_OPERAND (declarator, 0);
-             while (TREE_CODE (t) == TREE_LIST)
-               t = TREE_VALUE (t);
-             really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE);
-           }
+           if (decl_context != PARM
+               && (array_ptr_quals != TYPE_UNQUALIFIED
+                   || array_ptr_attrs != NULL_TREE
+                   || array_parm_static))
+             {
+               error ("static or type qualifiers in non-parameter array declarator");
+               array_ptr_quals = TYPE_UNQUALIFIED;
+               array_ptr_attrs = NULL_TREE;
+               array_parm_static = 0;
+             }
+           break;
+         }
+       case cdk_function:
+         {
+           /* Say it's a definition only for the declarator closest
+              to the identifier, apart possibly from some
+              attributes.  */
+           bool really_funcdef = false;
+           tree arg_types;
+           if (funcdef_flag)
+             {
+               const struct c_declarator *t = declarator->declarator;
+               while (t->kind == cdk_attrs)
+                 t = t->declarator;
+               really_funcdef = (t->kind == cdk_id);
+             }
 
-         /* Declaring a function type.
-            Make sure we have a valid type for the function to return.  */
-         if (type == error_mark_node)
-           continue;
+           /* Declaring a function type.  Make sure we have a valid
+              type for the function to return.  */
+           if (type == error_mark_node)
+             continue;
+           
+           size_varies = 0;
 
-         size_varies = 0;
+           /* Warn about some types functions can't return.  */
+           if (TREE_CODE (type) == FUNCTION_TYPE)
+             {
+               error ("%qs declared as function returning a function", name);
+               type = integer_type_node;
+             }
+           if (TREE_CODE (type) == ARRAY_TYPE)
+             {
+               error ("%qs declared as function returning an array", name);
+               type = integer_type_node;
+             }
 
-         /* Warn about some types functions can't return.  */
+           /* Construct the function type and go to the next
+              inner layer of declarator.  */
+           arg_info = declarator->u.arg_info;
+           arg_types = grokparms (arg_info, really_funcdef);
 
-         if (TREE_CODE (type) == FUNCTION_TYPE)
-           {
-             error ("`%s' declared as function returning a function", name);
-             type = integer_type_node;
-           }
-         if (TREE_CODE (type) == ARRAY_TYPE)
+           /* Type qualifiers before the return type of the function
+              qualify the return type, not the function type.  */
+           if (type_quals)
+             {
+               /* Type qualifiers on a function return type are
+                  normally permitted by the standard but have no
+                  effect, so give a warning at -Wreturn-type.
+                  Qualifiers on a void return type are banned on
+                  function definitions in ISO C; GCC used to used
+                  them for noreturn functions.  */
+               if (VOID_TYPE_P (type) && really_funcdef)
+                 pedwarn ("function definition has qualified void return type");
+               else if (warn_return_type)
+                 warning (0, "type qualifiers ignored on function return type");
+               
+               type = c_build_qualified_type (type, type_quals);
+             }
+           type_quals = TYPE_UNQUALIFIED;
+           
+           type = build_function_type (type, arg_types);
+           declarator = declarator->declarator;
+           
+           /* Set the TYPE_CONTEXTs for each tagged type which is local to
+              the formal parameter list of this FUNCTION_TYPE to point to
+              the FUNCTION_TYPE node itself.  */
            {
-             error ("`%s' declared as function returning an array", name);
-             type = integer_type_node;
+             tree link;
+             
+             for (link = arg_info->tags;
+                  link;
+                  link = TREE_CHAIN (link))
+               TYPE_CONTEXT (TREE_VALUE (link)) = type;
            }
+           break;
+         }
+       case cdk_pointer:
+         {
+           /* Merge any constancy or volatility into the target type
+              for the pointer.  */
 
-         /* Construct the function type and go to the next
-            inner layer of declarator.  */
-         arg_info = TREE_OPERAND (declarator, 1);
-         arg_types = grokparms (arg_info, really_funcdef);
-
-         /* Type qualifiers before the return type of the function
-            qualify the return type, not the function type.  */
-         if (type_quals)
-           {
-             /* Type qualifiers on a function return type are
-                normally permitted by the standard but have no
-                effect, so give a warning at -Wreturn-type.
-                Qualifiers on a void return type are banned on
-                function definitions in ISO C; GCC used to used them
-                for noreturn functions.  */
-             if (VOID_TYPE_P (type) && really_funcdef)
-               pedwarn ("function definition has qualified void return type");
-             else if (warn_return_type)
-               warning ("type qualifiers ignored on function return type");
-
+           if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+               && type_quals)
+             pedwarn ("ISO C forbids qualified function types");
+           if (type_quals)
              type = c_build_qualified_type (type, type_quals);
-           }
-         type_quals = TYPE_UNQUALIFIED;
-
-         type = build_function_type (type, arg_types);
-         declarator = TREE_OPERAND (declarator, 0);
-
-         /* Set the TYPE_CONTEXTs for each tagged type which is local to
-            the formal parameter list of this FUNCTION_TYPE to point to
-            the FUNCTION_TYPE node itself.  */
+           size_varies = 0;
 
-         {
-           tree link;
+           type = build_pointer_type (type);
+           
+           /* Process type qualifiers (such as const or volatile)
+              that were given inside the `*'.  */
+           type_quals = declarator->u.pointer_quals;
 
-           for (link = ARG_INFO_TAGS (arg_info);
-                link;
-                link = TREE_CHAIN (link))
-             TYPE_CONTEXT (TREE_VALUE (link)) = type;
+           declarator = declarator->declarator;
+           break;
          }
+       default:
+         gcc_unreachable ();
        }
-      else if (TREE_CODE (declarator) == INDIRECT_REF)
-       {
-         /* Merge any constancy or volatility into the target type
-            for the pointer.  */
-
-         if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-             && type_quals)
-           pedwarn ("ISO C forbids qualified function types");
-         if (type_quals)
-           type = c_build_qualified_type (type, type_quals);
-         type_quals = TYPE_UNQUALIFIED;
-         size_varies = 0;
-
-         type = build_pointer_type (type);
-
-         /* Process a list of type modifier keywords
-            (such as const or volatile) that were given inside the `*'.  */
-
-         if (TREE_TYPE (declarator))
-           {
-             tree typemodlist;
-             int erred = 0;
-
-             constp = 0;
-             volatilep = 0;
-             restrictp = 0;
-             for (typemodlist = TREE_TYPE (declarator); typemodlist;
-                  typemodlist = TREE_CHAIN (typemodlist))
-               {
-                 tree qualifier = TREE_VALUE (typemodlist);
-
-                 if (C_IS_RESERVED_WORD (qualifier))
-                   {
-                     if (C_RID_CODE (qualifier) == RID_CONST)
-                       constp++;
-                     else if (C_RID_CODE (qualifier) == RID_VOLATILE)
-                       volatilep++;
-                     else if (C_RID_CODE (qualifier) == RID_RESTRICT)
-                       restrictp++;
-                     else
-                       erred++;
-                   }
-                 else
-                   erred++;
-               }
-
-             if (erred)
-               error ("invalid type modifier within pointer declarator");
-             if (pedantic && !flag_isoc99)
-               {
-                 if (constp > 1)
-                   pedwarn ("duplicate `const'");
-                 if (volatilep > 1)
-                   pedwarn ("duplicate `volatile'");
-                 if (restrictp > 1)
-                   pedwarn ("duplicate `restrict'");
-               }
-
-             type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-                           | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-                           | (volatilep ? TYPE_QUAL_VOLATILE : 0));
-           }
-
-         declarator = TREE_OPERAND (declarator, 0);
-       }
-      else
-       abort ();
-
     }
 
-  /* Now TYPE has the actual type.  */
+  /* Now TYPE has the actual type, apart from any qualifiers in
+     TYPE_QUALS.  */
+
+  /* Check the type and width of a bit-field.  */
+  if (bitfield)
+    check_bitfield_type_and_width (&type, width, orig_name);
 
   /* Did array size calculations overflow?  */
 
@@ -4548,7 +4333,7 @@ grokdeclarator (tree declarator, tree declspecs,
       && COMPLETE_TYPE_P (type)
       && TREE_OVERFLOW (TYPE_SIZE (type)))
     {
-      error ("size of array `%s' is too large", name);
+      error ("size of array %qs is too large", name);
       /* If we proceed with the array type as it is, we'll eventually
         crash in tree_low_cst().  */
       type = error_mark_node;
@@ -4556,21 +4341,20 @@ grokdeclarator (tree declarator, tree declspecs,
 
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
 
-  if (specbits & (1 << (int) RID_TYPEDEF))
+  if (storage_class == csc_typedef)
     {
       tree decl;
-      /* Note that the grammar rejects storage classes
-        in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
          && type_quals)
        pedwarn ("ISO C forbids qualified function types");
       if (type_quals)
        type = c_build_qualified_type (type, type_quals);
-      decl = build_decl (TYPE_DECL, declarator, type);
-      if ((specbits & (1 << (int) RID_SIGNED))
-         || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
+      decl = build_decl (TYPE_DECL, declarator->u.id, type);
+      if (declspecs->explicit_signed_p)
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
       decl_attributes (&decl, returned_attrs, 0);
+      if (declspecs->inline_p)
+       pedwarn ("%Jtypedef %qD declared %<inline%>", decl, decl);
       return decl;
     }
 
@@ -4594,8 +4378,10 @@ grokdeclarator (tree declarator, tree declspecs,
 
   if (decl_context == TYPENAME)
     {
-      /* Note that the grammar rejects storage classes
-        in typenames, fields or parameters */
+      /* Note that the grammar rejects storage classes in typenames
+        and fields.  */
+      gcc_assert (storage_class == csc_none && !threadp
+                 && !declspecs->inline_p);
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
          && type_quals)
        pedwarn ("ISO C forbids const or volatile function types");
@@ -4612,13 +4398,13 @@ grokdeclarator (tree declarator, tree declspecs,
      a better error message can be made later.  */
 
   if (VOID_TYPE_P (type) && decl_context != PARM
-      && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
-           && ((specbits & (1 << (int) RID_EXTERN))
+      && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
+           && (storage_class == csc_extern
                || (current_scope == file_scope
-                   && !(specbits
-                        & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
+                   && !(storage_class == csc_static
+                        || storage_class == csc_register)))))
     {
-      error ("variable or field `%s' declared void", name);
+      error ("variable or field %qs declared void", name);
       type = integer_type_node;
     }
 
@@ -4643,45 +4429,12 @@ grokdeclarator (tree declarator, tree declspecs,
            if (type_quals)
              type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
-           type_quals = TYPE_UNQUALIFIED;
-           if (array_ptr_quals)
-             {
-               tree new_ptr_quals, new_ptr_attrs;
-               int erred = 0;
-               split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
-               /* We don't yet implement attributes in this context.  */
-               if (new_ptr_attrs != NULL_TREE)
-                 warning ("attributes in parameter array declarator ignored");
-
-               constp = 0;
-               volatilep = 0;
-               restrictp = 0;
-               for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
-                 {
-                   tree qualifier = TREE_VALUE (new_ptr_quals);
+           type_quals = array_ptr_quals;
 
-                   if (C_IS_RESERVED_WORD (qualifier))
-                     {
-                       if (C_RID_CODE (qualifier) == RID_CONST)
-                         constp++;
-                       else if (C_RID_CODE (qualifier) == RID_VOLATILE)
-                         volatilep++;
-                       else if (C_RID_CODE (qualifier) == RID_RESTRICT)
-                         restrictp++;
-                       else
-                         erred++;
-                     }
-                   else
-                     erred++;
-                 }
-
-               if (erred)
-                 error ("invalid type modifier within array declarator");
+           /* We don't yet implement attributes in this context.  */
+           if (array_ptr_attrs != NULL_TREE)
+             warning (0, "attributes in parameter array declarator ignored");
 
-               type_quals = ((constp ? TYPE_QUAL_CONST : 0)
-                             | (restrictp ? TYPE_QUAL_RESTRICT : 0)
-                             | (volatilep ? TYPE_QUAL_VOLATILE : 0));
-             }
            size_varies = 0;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -4698,7 +4451,7 @@ grokdeclarator (tree declarator, tree declspecs,
 
        type_as_written = type;
 
-       decl = build_decl (PARM_DECL, declarator, type);
+       decl = build_decl (PARM_DECL, declarator->u.id, type);
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
 
@@ -4714,28 +4467,31 @@ grokdeclarator (tree declarator, tree declspecs,
 
        DECL_ARG_TYPE (decl) = promoted_type;
        DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
+       if (declspecs->inline_p)
+         pedwarn ("%Jparameter %qD declared %<inline%>", decl, decl);
       }
     else if (decl_context == FIELD)
       {
+       /* Note that the grammar rejects storage classes in typenames
+          and fields.  */
+       gcc_assert (storage_class == csc_none && !threadp
+                   && !declspecs->inline_p);
+
        /* Structure field.  It may not be a function.  */
 
        if (TREE_CODE (type) == FUNCTION_TYPE)
          {
-           error ("field `%s' declared as a function", name);
+           error ("field %qs declared as a function", name);
            type = build_pointer_type (type);
          }
        else if (TREE_CODE (type) != ERROR_MARK
                 && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
          {
-           error ("field `%s' has incomplete type", name);
+           error ("field %qs has incomplete type", name);
            type = error_mark_node;
          }
-       /* Move type qualifiers down to element of an array.  */
-       if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
-         type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
-                                                          type_quals),
-                                  TYPE_DOMAIN (type));
-       decl = build_decl (FIELD_DECL, declarator, type);
+       type = c_build_qualified_type (type, type_quals);
+       decl = build_decl (FIELD_DECL, declarator->u.id, type);
        DECL_NONADDRESSABLE_P (decl) = bitfield;
 
        if (size_varies)
@@ -4743,9 +4499,10 @@ grokdeclarator (tree declarator, tree declspecs,
       }
     else if (TREE_CODE (type) == FUNCTION_TYPE)
       {
-       if (specbits & (1 << (int) RID_REGISTER)
-           || specbits & (1 << (int) RID_THREAD))
-         error ("invalid storage class for function `%s'", name);
+       if (storage_class == csc_register || threadp)
+         {
+           error ("invalid storage class for function %qs", name);
+          }
        else if (current_scope != file_scope)
          {
            /* Function declaration not at file scope.  Storage
@@ -4753,58 +4510,64 @@ grokdeclarator (tree declarator, tree declspecs,
               6.7.1p5, and `extern' makes no difference.  However,
               GCC allows 'auto', perhaps with 'inline', to support
               nested functions.  */
-           if (specbits & (1 << (int) RID_AUTO))
+           if (storage_class == csc_auto)
              {
                if (pedantic)
-                 pedwarn ("invalid storage class for function `%s'", name);
+                 pedwarn ("invalid storage class for function %qs", name);
+             }
+           else if (storage_class == csc_static)
+             {
+               error ("invalid storage class for function %qs", name);
+               if (funcdef_flag)
+                 storage_class = declspecs->storage_class = csc_none;
+               else
+                 return 0;
              }
-           if (specbits & (1 << (int) RID_STATIC))
-             error ("invalid storage class for function `%s'", name);
          }
 
-       decl = build_decl (FUNCTION_DECL, declarator, type);
+       decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
        decl = build_decl_attribute_variant (decl, decl_attr);
 
        DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
 
-       if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+       if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ISO C forbids qualified function types");
 
        /* GNU C interprets a volatile-qualified function type to indicate
           that the function does not return.  */
        if ((type_quals & TYPE_QUAL_VOLATILE)
            && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
-         warning ("`noreturn' function returns non-void value");
+         warning (0, "%<noreturn%> function returns non-void value");
 
        /* Every function declaration is an external reference
           (DECL_EXTERNAL) except for those which are not at file
           scope and are explicitly declared "auto".  This is
           forbidden by standard C (C99 6.7.1p5) and is interpreted by
           GCC to signify a forward declaration of a nested function.  */
-       if ((specbits & (1 << RID_AUTO)) && current_scope != file_scope)
+       if (storage_class == csc_auto && current_scope != file_scope)
          DECL_EXTERNAL (decl) = 0;
        else
          DECL_EXTERNAL (decl) = 1;
 
        /* Record absence of global scope for `static' or `auto'.  */
        TREE_PUBLIC (decl)
-         = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
+         = !(storage_class == csc_static || storage_class == csc_auto);
 
        /* For a function definition, record the argument information
           block where store_parm_decls will look for it.  */
        if (funcdef_flag)
          current_function_arg_info = arg_info;
 
-       if (defaulted_int)
+       if (declspecs->default_int_p)
          C_FUNCTION_IMPLICIT_INT (decl) = 1;
 
        /* Record presence of `inline', if it is reasonable.  */
-       if (MAIN_NAME_P (declarator))
+       if (flag_hosted && MAIN_NAME_P (declarator->u.id))
          {
-           if (inlinep)
-             warning ("cannot inline function `main'");
+           if (declspecs->inline_p)
+             pedwarn ("cannot inline function %<main%>");
          }
-       else if (inlinep)
+       else if (declspecs->inline_p)
          {
            /* Record that the function is declared `inline'.  */
            DECL_DECLARED_INLINE_P (decl) = 1;
@@ -4816,7 +4579,7 @@ grokdeclarator (tree declarator, tree declspecs,
            if (initialized)
              {
                DECL_INLINE (decl) = 1;
-               if (specbits & (1 << (int) RID_EXTERN))
+               if (storage_class == csc_extern)
                  current_extern_inline = 1;
              }
          }
@@ -4830,19 +4593,9 @@ grokdeclarator (tree declarator, tree declspecs,
       {
        /* It's a variable.  */
        /* An uninitialized decl with `extern' is a reference.  */
-       int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
+       int extern_ref = !initialized && storage_class == csc_extern;
 
-       /* Move type qualifiers down to element of an array.  */
-       if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
-         {
-           int saved_align = TYPE_ALIGN(type);
-           type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
-                                                            type_quals),
-                                    TYPE_DOMAIN (type));
-           TYPE_ALIGN (type) = saved_align;
-         }
-       else if (type_quals)
-         type = c_build_qualified_type (type, type_quals);
+       type = c_build_qualified_type (type, type_quals);
 
        /* C99 6.2.2p7: It is invalid (compile-time undefined
           behavior) to create an 'extern' declaration for a
@@ -4852,28 +4605,29 @@ grokdeclarator (tree declarator, tree declspecs,
           the 'extern' declaration is taken to refer to that decl.) */
        if (extern_ref && current_scope != file_scope)
          {
-           tree global_decl  = identifier_global_value (declarator);
-           tree visible_decl = lookup_name (declarator);
+           tree global_decl  = identifier_global_value (declarator->u.id);
+           tree visible_decl = lookup_name (declarator->u.id);
 
            if (global_decl
                && global_decl != visible_decl
                && TREE_CODE (global_decl) == VAR_DECL
                && !TREE_PUBLIC (global_decl))
-             error ("variable previously declared 'static' redeclared "
-                    "'extern'");
+             error ("variable previously declared %<static%> redeclared "
+                    "%<extern%>");
          }
 
-       decl = build_decl (VAR_DECL, declarator, type);
+       decl = build_decl (VAR_DECL, declarator->u.id, type);
+       DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
 
-       if (inlinep)
-         pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
+       if (declspecs->inline_p)
+         pedwarn ("%Jvariable %qD declared %<inline%>", decl, decl);
 
        /* At file scope, an initialized extern declaration may follow
           a static declaration.  In that case, DECL_EXTERNAL will be
           reset later in start_decl.  */
-       DECL_EXTERNAL (decl) = !!(specbits & (1 << (int) RID_EXTERN));
+       DECL_EXTERNAL (decl) = (storage_class == csc_extern);
 
        /* At file scope, the presence of a `static' or `register' storage
           class specifier, or the absence of all storage class specifiers
@@ -4881,18 +4635,18 @@ grokdeclarator (tree declarator, tree declspecs,
           the absence of both `static' and `register' makes it public.  */
        if (current_scope == file_scope)
          {
-           TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
-                                              | (1 << (int) RID_REGISTER)));
+           TREE_PUBLIC (decl) = !(storage_class == csc_static
+                                  || storage_class == csc_register);
            TREE_STATIC (decl) = !extern_ref;
          }
        /* Not at file scope, only `static' makes a static definition.  */
        else
          {
-           TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
+           TREE_STATIC (decl) = (storage_class == csc_static);
            TREE_PUBLIC (decl) = extern_ref;
          }
 
-       if (specbits & 1 << (int) RID_THREAD)
+       if (threadp)
          {
            if (targetm.have_tls)
              DECL_THREAD_LOCAL (decl) = 1;
@@ -4906,7 +4660,7 @@ grokdeclarator (tree declarator, tree declspecs,
     /* Record `register' declaration for warnings on &
        and in case doing stupid register allocation.  */
 
-    if (specbits & (1 << (int) RID_REGISTER))
+    if (storage_class == csc_register)
       {
        C_DECL_REGISTER (decl) = 1;
        DECL_REGISTER (decl) = 1;
@@ -4930,12 +4684,9 @@ grokdeclarator (tree declarator, tree declspecs,
        C_DECL_REGISTER (decl) = was_reg;
       }
 
-#ifdef ENABLE_CHECKING
   /* This is the earliest point at which we might know the assembler
      name of a variable.  Thus, if it's known before this, die horribly.  */
-  if (DECL_ASSEMBLER_NAME_SET_P (decl))
-    abort ();
-#endif
+    gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
 
     decl_attributes (&decl, returned_attrs, 0);
 
@@ -4958,24 +4709,24 @@ grokdeclarator (tree declarator, tree declspecs,
    when FUNCDEF_FLAG is false.  */
 
 static tree
-grokparms (tree arg_info, bool funcdef_flag)
+grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
 {
-  tree arg_types = ARG_INFO_TYPES (arg_info);
+  tree arg_types = arg_info->types;
 
   if (warn_strict_prototypes && arg_types == 0 && !funcdef_flag
       && !in_system_header)
-    warning ("function declaration isn't a prototype");
+    warning (0, "function declaration isn%'t a prototype");
 
   if (arg_types == error_mark_node)
     return 0;  /* don't set TYPE_ARG_TYPES in this case */
 
   else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
     {
-      if (! funcdef_flag)
+      if (!funcdef_flag)
        pedwarn ("parameter names (without types) in function declaration");
 
-      ARG_INFO_PARMS (arg_info) = ARG_INFO_TYPES (arg_info);
-      ARG_INFO_TYPES (arg_info) = 0;
+      arg_info->parms = arg_info->types;
+      arg_info->types = 0;
       return 0;
     }
   else
@@ -4983,12 +4734,16 @@ grokparms (tree arg_info, bool funcdef_flag)
       tree parm, type, typelt;
       unsigned int parmno;
 
-      /* If the arg types are incomplete in a declaration, they must
-        include undefined tags.  These tags can never be defined in
-        the scope of the declaration, so the types can never be
-        completed, and no call can be compiled successfully.  */
+      /* If there is a parameter of incomplete type in a definition,
+        this is an error.  In a declaration this is valid, and a
+        struct or union type may be completed later, before any calls
+        or definition of the function.  In the case where the tag was
+        first declared within the parameter list, a warning has
+        already been given.  If a parameter has void type, then
+        however the function cannot be defined or called, so
+        warn.  */
 
-      for (parm = ARG_INFO_PARMS (arg_info), typelt = arg_types, parmno = 1;
+      for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
           parm;
           parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
        {
@@ -5001,7 +4756,7 @@ grokparms (tree arg_info, bool funcdef_flag)
              if (funcdef_flag)
                {
                  if (DECL_NAME (parm))
-                   error ("%Jparameter %u ('%D') has incomplete type",
+                   error ("%Jparameter %u (%qD) has incomplete type",
                           parm, parmno, parm);
                  else
                    error ("%Jparameter %u has incomplete type",
@@ -5010,13 +4765,13 @@ grokparms (tree arg_info, bool funcdef_flag)
                  TREE_VALUE (typelt) = error_mark_node;
                  TREE_TYPE (parm) = error_mark_node;
                }
-             else
+             else if (VOID_TYPE_P (type))
                {
                  if (DECL_NAME (parm))
-                   warning ("%Jparameter %u ('%D') has incomplete type",
+                   warning (0, "%Jparameter %u (%qD) has void type",
                             parm, parmno, parm);
                  else
-                   warning ("%Jparameter %u has incomplete type",
+                   warning (0, "%Jparameter %u has void type",
                             parm, parmno);
                }
            }
@@ -5025,26 +4780,20 @@ grokparms (tree arg_info, bool funcdef_flag)
     }
 }
 
-/* Take apart the current scope and return a tree_list node with info
-   on a parameter list just parsed.  This tree_list node should be
-   examined using the ARG_INFO_* macros, defined above:
-
-     ARG_INFO_PARMS:  a list of parameter decls.
-     ARG_INFO_TAGS:   a list of structure, union and enum tags defined.
-     ARG_INFO_TYPES:  a list of argument types to go in the FUNCTION_TYPE.
-     ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration
-                      constants) defined with the parameters.
+/* Take apart the current scope and return a c_arg_info structure with
+   info on a parameter list just parsed.
 
-   This tree_list node is later fed to 'grokparms' and 'store_parm_decls'.
+   This structure is later fed to 'grokparms' and 'store_parm_decls'.
 
    ELLIPSIS being true means the argument list ended in '...' so don't
    append a sentinel (void_list_node) to the end of the type-list.  */
 
-tree
+struct c_arg_info *
 get_parm_info (bool ellipsis)
 {
   struct c_binding *b = current_scope->bindings;
-  tree arg_info = make_node (TREE_LIST);
+  struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
+                                       struct c_arg_info);
   tree parms    = 0;
   tree tags     = 0;
   tree types    = 0;
@@ -5053,16 +4802,18 @@ get_parm_info (bool ellipsis)
   static bool explained_incomplete_types = false;
   bool gave_void_only_once_err = false;
 
+  arg_info->parms = 0;
+  arg_info->tags = 0;
+  arg_info->types = 0;
+  arg_info->others = 0;
+
   /* The bindings in this scope must not get put into a block.
      We will take care of deleting the binding nodes.  */
   current_scope->bindings = 0;
 
   /* This function is only called if there was *something* on the
      parameter list.  */
-#ifdef ENABLE_CHECKING
-  if (b == 0)
-    abort ();
-#endif
+  gcc_assert (b);
 
   /* A parameter list consisting solely of 'void' indicates that the
      function takes no arguments.  But if the 'void' is qualified
@@ -5077,13 +4828,13 @@ get_parm_info (bool ellipsis)
       if (TREE_THIS_VOLATILE (b->decl)
          || TREE_READONLY (b->decl)
          || C_DECL_REGISTER (b->decl))
-       error ("'void' as only parameter may not be qualified");
+       error ("%<void%> as only parameter may not be qualified");
 
       /* There cannot be an ellipsis.  */
       if (ellipsis)
-       error ("'void' must be the only parameter");
+       error ("%<void%> must be the only parameter");
 
-      ARG_INFO_TYPES (arg_info) = void_list_node;
+      arg_info->types = void_list_node;
       return arg_info;
     }
 
@@ -5103,22 +4854,20 @@ get_parm_info (bool ellipsis)
        case PARM_DECL:
          if (b->id)
            {
-#ifdef ENABLE_CHECKING
-             if (I_SYMBOL_BINDING (b->id) != b) abort ();
-#endif
+             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
              I_SYMBOL_BINDING (b->id) = b->shadowed;
            }
 
          /* Check for forward decls that never got their actual decl.  */
          if (TREE_ASM_WRITTEN (decl))
-           error ("%Jparameter '%D' has just a forward declaration",
+           error ("%Jparameter %qD has just a forward declaration",
                   decl, decl);
          /* Check for (..., void, ...) and issue an error.  */
          else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
            {
              if (!gave_void_only_once_err)
                {
-                 error ("'void' must be the only parameter");
+                 error ("%<void%> must be the only parameter");
                  gave_void_only_once_err = true;
                }
            }
@@ -5143,9 +4892,7 @@ get_parm_info (bool ellipsis)
             appears in the bindings list with b->id NULL.  */
          if (b->id)
            {
-#ifdef ENABLE_CHECKING
-             if (I_TAG_BINDING (b->id) != b) abort ();
-#endif
+             gcc_assert (I_TAG_BINDING (b->id) == b);
              I_TAG_BINDING (b->id) = b->shadowed;
            }
 
@@ -5159,16 +4906,16 @@ get_parm_info (bool ellipsis)
            {
              if (b->id)
                /* The %s will be one of 'struct', 'union', or 'enum'.  */
-               warning ("'%s %E' declared inside parameter list",
+               warning (0, "%<%s %E%> declared inside parameter list",
                         keyword, b->id);
              else
                /* The %s will be one of 'struct', 'union', or 'enum'.  */
-               warning ("anonymous %s declared inside parameter list",
+               warning (0, "anonymous %s declared inside parameter list",
                         keyword);
 
-             if (! explained_incomplete_types)
+             if (!explained_incomplete_types)
                {
-                 warning ("its scope is only this definition or declaration,"
+                 warning (0, "its scope is only this definition or declaration,"
                           " which is probably not what you want");
                  explained_incomplete_types = true;
                }
@@ -5179,10 +4926,13 @@ get_parm_info (bool ellipsis)
 
        case CONST_DECL:
        case TYPE_DECL:
+       case FUNCTION_DECL:
          /* CONST_DECLs appear here when we have an embedded enum,
             and TYPE_DECLs appear here when we have an embedded struct
             or union.  No warnings for this - we already warned about the
-            type itself.  */
+            type itself.  FUNCTION_DECLs appear when there is an implicit
+            function declaration in the parameter list.  */
+
          TREE_CHAIN (decl) = others;
          others = decl;
          /* fall through */
@@ -5192,37 +4942,36 @@ get_parm_info (bool ellipsis)
             variable.  Just throw it away.  */
          if (b->id)
            {
-#ifdef ENABLE_CHECKING
-             if (I_SYMBOL_BINDING (b->id) != b) abort ();
-#endif
+             gcc_assert (I_SYMBOL_BINDING (b->id) == b);
              I_SYMBOL_BINDING (b->id) = b->shadowed;
            }
          break;
 
          /* Other things that might be encountered.  */
        case LABEL_DECL:
-       case FUNCTION_DECL:
        case VAR_DECL:
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
       b = free_binding_and_advance (b);
     }
 
-  ARG_INFO_PARMS  (arg_info) = parms;
-  ARG_INFO_TAGS   (arg_info) = tags;
-  ARG_INFO_TYPES  (arg_info) = types;
-  ARG_INFO_OTHERS (arg_info) = others;
+  arg_info->parms = parms;
+  arg_info->tags = tags;
+  arg_info->types = types;
+  arg_info->others = others;
   return arg_info;
 }
 \f
 /* Get the struct, enum or union (CODE says which) with tag NAME.
-   Define the tag as a forward-reference if it is not defined.  */
+   Define the tag as a forward-reference if it is not defined.
+   Return a c_typespec structure for the type specifier.  */
 
-tree
-xref_tag (enum tree_code code, tree name)
+struct c_typespec
+parser_xref_tag (enum tree_code code, tree name)
 {
+  struct c_typespec ret;
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
@@ -5238,8 +4987,12 @@ xref_tag (enum tree_code code, tree name)
      this would not work properly if we return the reference found.
      (For example, with "struct foo" in an outer scope, "union foo;"
      must shadow that tag with a new one of union type.)  */
+  ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
   if (ref && TREE_CODE (ref) == code)
-    return ref;
+    {
+      ret.spec = ref;
+      return ret;
+    }
 
   /* If no such tag is yet defined, create a forward-reference node
      and record it as the "definition".
@@ -5262,7 +5015,18 @@ xref_tag (enum tree_code code, tree name)
 
   pushtag (name, ref);
 
-  return ref;
+  ret.spec = ref;
+  return ret;
+}
+
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+   Define the tag as a forward-reference if it is not defined.
+   Return a tree for the type.  */
+
+tree
+xref_tag (enum tree_code code, tree name)
+{
+  return parser_xref_tag (code, name).spec;
 }
 \f
 /* Make sure that the tag NAME is defined *in the current scope*
@@ -5281,12 +5045,19 @@ start_struct (enum tree_code code, tree name)
     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));
+           error ("redefinition of %<union %E%>", name);
+          else
+           error ("redefinition of %<struct %E%>", name);
+       }
+      else if (C_TYPE_BEING_DEFINED (ref))
+       {
+         if (code == UNION_TYPE)
+           error ("nested redefinition of %<union %E%>", name);
           else
-           error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
+           error ("nested redefinition of %<struct %E%>", name);
        }
     }
   else
@@ -5302,7 +5073,7 @@ start_struct (enum tree_code code, tree name)
   return ref;
 }
 
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
+/* Process the specs, declarator and width (NULL if omitted)
    of a structure component, returning a FIELD_DECL node.
    WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
 
@@ -5311,11 +5082,13 @@ start_struct (enum tree_code code, tree name)
    are ultimately passed to `build_struct' to make the RECORD_TYPE node.  */
 
 tree
-grokfield (tree declarator, tree declspecs, tree width)
+grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
+          tree width)
 {
   tree value;
 
-  if (declarator == NULL_TREE && width == NULL_TREE)
+  if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+      && width == NULL_TREE)
     {
       /* This is an unnamed decl.
 
@@ -5336,27 +5109,30 @@ grokfield (tree declarator, tree declspecs, tree width)
         took this from Plan 9 or if it was an accident of implementation
         that took root before someone noticed the bug...  */
 
-      tree type = TREE_VALUE (declspecs);
+      tree type = declspecs->type;
+      bool type_ok = (TREE_CODE (type) == RECORD_TYPE
+                     || TREE_CODE (type) == UNION_TYPE);
+      bool ok = false;
 
-      if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
-       type = TREE_TYPE (type);
-      if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
+      if (type_ok
+         && (flag_ms_extensions || !declspecs->typedef_p))
        {
          if (flag_ms_extensions)
-           ; /* ok */
+           ok = true;
          else if (flag_iso)
-           goto warn_unnamed_field;
+           ok = false;
          else if (TYPE_NAME (type) == NULL)
-           ; /* ok */
+           ok = true;
          else
-           goto warn_unnamed_field;
+           ok = false;
        }
-      else
+      if (!ok)
        {
-       warn_unnamed_field:
-         warning ("declaration does not declare anything");
+         pedwarn ("declaration does not declare anything");
          return NULL_TREE;
        }
+      if (pedantic)
+       pedwarn ("ISO C doesn%'t support unnamed structs/unions");
     }
 
   value = grokdeclarator (declarator, declspecs, FIELD, false,
@@ -5399,7 +5175,7 @@ detect_field_duplicates (tree fieldlist)
            for (y = fieldlist; y != x; y = TREE_CHAIN (y))
              if (DECL_NAME (y) == DECL_NAME (x))
                {
-                 error ("%Jduplicate member '%D'", x, x);
+                 error ("%Jduplicate member %qD", x, x);
                  DECL_NAME (x) = NULL_TREE;
                }
          }
@@ -5415,7 +5191,7 @@ detect_field_duplicates (tree fieldlist)
            slot = htab_find_slot (htab, y, INSERT);
            if (*slot)
              {
-               error ("%Jduplicate member '%D'", x, x);
+               error ("%Jduplicate member %qD", x, x);
                DECL_NAME (x) = NULL_TREE;
              }
            *slot = y;
@@ -5450,9 +5226,22 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          break;
 
       if (x == 0)
-       pedwarn ("%s has no %s",
-                TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
-                fieldlist ? _("named members") : _("members"));
+       {
+         if (TREE_CODE (t) == UNION_TYPE)
+           {
+             if (fieldlist)
+               pedwarn ("union has no named members");
+             else
+               pedwarn ("union has no members");
+           }
+         else
+           {
+             if (fieldlist)
+               pedwarn ("struct has no named members");
+             else
+               pedwarn ("struct has no members");
+           }
+       }
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
@@ -5491,11 +5280,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
       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 `%s'",
-              IDENTIFIER_POINTER (TYPE_NAME (t)));
-
       if (DECL_INITIAL (x))
        {
          unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
@@ -5520,7 +5304,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
              error ("%Jflexible array member not at end of struct", x);
              TREE_TYPE (x) = error_mark_node;
            }
-         else if (! saw_named_field)
+         else if (!saw_named_field)
            {
              error ("%Jflexible array member in otherwise empty struct", x);
              TREE_TYPE (x) = error_mark_node;
@@ -5555,8 +5339,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
            = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
          tree type = TREE_TYPE (*fieldlistp);
          if (width != TYPE_PRECISION (type))
-           TREE_TYPE (*fieldlistp)
-             = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+           {
+             TREE_TYPE (*fieldlistp)
+               = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+             DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+           }
          DECL_INITIAL (*fieldlistp) = 0;
        }
       else
@@ -5631,10 +5418,10 @@ finish_struct (tree t, tree fieldlist, tree attributes)
      make it one, warn and turn off the flag.  */
   if (TREE_CODE (t) == UNION_TYPE
       && TYPE_TRANSPARENT_UNION (t)
-      && TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t)))
+      && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
     {
       TYPE_TRANSPARENT_UNION (t) = 0;
-      warning ("union cannot be made transparent");
+      warning (0, "union cannot be made transparent");
     }
 
   /* If this structure or union completes the type of any previous
@@ -5652,7 +5439,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
          if (c_dialect_objc ())
            objc_check_decl (decl);
          rest_of_decl_compilation (decl, toplevel, 0);
-         if (! toplevel)
+         if (!toplevel)
            expand_decl (decl);
        }
     }
@@ -5661,6 +5448,12 @@ finish_struct (tree t, tree fieldlist, tree attributes)
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
 
+  /* If we're inside a function proper, i.e. not file-scope and not still
+     parsing parameters, then arrange for the size of a variable sized type
+     to be bound now.  */
+  if (cur_stmt_list && variably_modified_type_p (t, NULL))
+    add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
+
   return t;
 }
 
@@ -5698,12 +5491,15 @@ start_enum (tree name)
       pushtag (name, enumtype);
     }
 
+  if (C_TYPE_BEING_DEFINED (enumtype))
+    error ("nested redefinition of %<enum %E%>", name);
+
   C_TYPE_BEING_DEFINED (enumtype) = 1;
 
   if (TYPE_VALUES (enumtype) != 0)
     {
       /* This enum is a named one that has been declared already.  */
-      error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name));
+      error ("redeclaration of %<enum %E%>", name);
 
       /* Completely replace its old definition.
         The old enumerators remain defined, however.  */
@@ -5766,7 +5562,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
       tem = c_common_type_for_size (precision, unsign);
       if (tem == NULL)
        {
-         warning ("enumeration values exceed range of largest integer");
+         warning (0, "enumeration values exceed range of largest integer");
          tem = long_long_integer_type_node;
        }
     }
@@ -5870,19 +5666,16 @@ build_enumerator (tree name, tree value)
 
   /* Validate and default VALUE.  */
 
-  /* Remove no-op casts from the value.  */
-  if (value)
-    STRIP_TYPE_NOPS (value);
-
   if (value != 0)
     {
       /* Don't issue more errors for error_mark_node (i.e. an
         undeclared identifier) - just ignore the value expression.  */
       if (value == error_mark_node)
        value = 0;
-      else if (TREE_CODE (value) != INTEGER_CST)
+      else if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
+              || TREE_CODE (value) != INTEGER_CST)
        {
-         error ("enumerator value for '%E' is not an integer constant", name);
+         error ("enumerator value for %qE is not an integer constant", name);
          value = 0;
        }
       else
@@ -5902,9 +5695,9 @@ build_enumerator (tree name, tree value)
        error ("overflow in enumeration values");
     }
 
-  if (pedantic && ! int_fits_type_p (value, integer_type_node))
+  if (pedantic && !int_fits_type_p (value, integer_type_node))
     {
-      pedwarn ("ISO C restricts enumerator values to range of `int'");
+      pedwarn ("ISO C restricts enumerator values to range of %<int%>");
       /* XXX This causes -pedantic to change the meaning of the program.
         Remove?  -zw 2004-03-15  */
       value = convert (integer_type_node, value);
@@ -5944,10 +5737,13 @@ build_enumerator (tree name, tree value)
    yyparse to report a parse error.  */
 
 int
-start_function (tree declspecs, tree declarator, tree attributes)
+start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
+               tree attributes)
 {
   tree decl1, old_decl;
   tree restype, resdecl;
+  struct c_label_context_se *nstack_se;
+  struct c_label_context_vm *nstack_vm;
 
   current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
@@ -5956,6 +5752,19 @@ start_function (tree declspecs, tree declarator, tree attributes)
   current_extern_inline = 0;
   c_switch_stack = NULL;
 
+  nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
+  nstack_se->labels_def = NULL;
+  nstack_se->labels_used = NULL;
+  nstack_se->next = label_context_stack_se;
+  label_context_stack_se = nstack_se;
+
+  nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm);
+  nstack_vm->labels_def = NULL;
+  nstack_vm->labels_used = NULL;
+  nstack_vm->scope = 0;
+  nstack_vm->next = label_context_stack_vm;
+  label_context_stack_vm = nstack_vm;
+
   /* Indicate no valid break/continue context by setting these variables
      to some non-null, non-label value.  We'll notice and emit the proper
      error message in c_finish_bc_stmt.  */
@@ -5973,7 +5782,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
   if (DECL_DECLARED_INLINE_P (decl1)
       && DECL_UNINLINABLE (decl1)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
-    warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
+    warning (0, "%Jinline function %qD given attribute noinline", decl1, decl1);
 
   announce_function (decl1);
 
@@ -5987,57 +5796,100 @@ start_function (tree declspecs, tree declarator, tree attributes)
     }
 
   if (warn_about_return_type)
-    pedwarn_c99 ("return type defaults to `int'");
+    pedwarn_c99 ("return type defaults to %<int%>");
 
   /* Make the init_value nonzero so pushdecl knows this is not tentative.
      error_mark_node is replaced below (in pop_scope) with the BLOCK.  */
   DECL_INITIAL (decl1) = error_mark_node;
 
   /* If this definition isn't a prototype and we had a prototype declaration
-     before, copy the arg type info from that prototype.
-     But not if what we had before was a builtin function.  */
+     before, copy the arg type info from that prototype.  */
   old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
-  if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
-      && !DECL_BUILT_IN (old_decl)
-      && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
-                   TREE_TYPE (TREE_TYPE (old_decl)))
-      && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
-    {
-      TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
-                                         TREE_TYPE (decl1));
-      current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
+  current_function_prototype_locus = UNKNOWN_LOCATION;
+  current_function_prototype_built_in = false;
+  current_function_prototype_arg_types = NULL_TREE;
+  if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
+    {
+      if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
+         && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+                       TREE_TYPE (TREE_TYPE (old_decl))))
+       {
+         TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
+                                             TREE_TYPE (decl1));
+         current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
+         current_function_prototype_built_in
+           = C_DECL_BUILTIN_PROTOTYPE (old_decl);
+         current_function_prototype_arg_types
+           = TYPE_ARG_TYPES (TREE_TYPE (decl1));
+       }
+      if (TREE_PUBLIC (decl1))
+       {
+         /* If there is an external prototype declaration of this
+            function, record its location but do not copy information
+            to this decl.  This may be an invisible declaration
+            (built-in or in a scope which has finished) or simply
+            have more refined argument types than any declaration
+            found above.  */
+         struct c_binding *b;
+         for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed)
+           if (B_IN_SCOPE (b, external_scope))
+             break;
+         if (b)
+           {
+             tree ext_decl, ext_type;
+             ext_decl = b->decl;
+             ext_type = b->type ? b->type : TREE_TYPE (ext_decl);
+             if (TREE_CODE (ext_type) == FUNCTION_TYPE
+                 && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+                               TREE_TYPE (ext_type)))
+               {
+                 current_function_prototype_locus
+                   = DECL_SOURCE_LOCATION (ext_decl);
+                 current_function_prototype_built_in
+                   = C_DECL_BUILTIN_PROTOTYPE (ext_decl);
+                 current_function_prototype_arg_types
+                   = TYPE_ARG_TYPES (ext_type);
+               }
+           }
+       }
     }
 
   /* Optionally warn of old-fashioned def with no previous prototype.  */
   if (warn_strict_prototypes
+      && old_decl != error_mark_node
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
       && C_DECL_ISNT_PROTOTYPE (old_decl))
-    warning ("function declaration isn't a prototype");
+    warning (0, "function declaration isn%'t a prototype");
   /* Optionally warn of any global def with no previous prototype.  */
   else if (warn_missing_prototypes
+          && old_decl != error_mark_node
           && TREE_PUBLIC (decl1)
-          && ! MAIN_NAME_P (DECL_NAME (decl1))
+          && !MAIN_NAME_P (DECL_NAME (decl1))
           && C_DECL_ISNT_PROTOTYPE (old_decl))
-    warning ("%Jno previous prototype for '%D'", decl1, decl1);
+    warning (0, "%Jno previous prototype for %qD", decl1, decl1);
   /* Optionally warn of any def with no previous prototype
      if the function has already been used.  */
   else if (warn_missing_prototypes
-          && old_decl != 0 && TREE_USED (old_decl)
+          && old_decl != 0
+          && old_decl != error_mark_node
+          && TREE_USED (old_decl)
           && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
-    warning ("%J'%D' was used with no prototype before its definition",
+    warning (0, "%J%qD was used with no prototype before its definition",
             decl1, decl1);
   /* Optionally warn of any global def with no previous declaration.  */
   else if (warn_missing_declarations
           && TREE_PUBLIC (decl1)
           && old_decl == 0
-          && ! MAIN_NAME_P (DECL_NAME (decl1)))
-    warning ("%Jno previous declaration for '%D'", decl1, decl1);
+          && !MAIN_NAME_P (DECL_NAME (decl1)))
+    warning (0, "%Jno previous declaration for %qD", decl1, decl1);
   /* Optionally warn of any def with no previous declaration
      if the function has already been used.  */
   else if (warn_missing_declarations
-          && old_decl != 0 && TREE_USED (old_decl)
+          && old_decl != 0
+          && old_decl != error_mark_node
+          && TREE_USED (old_decl)
           && C_DECL_IMPLICIT (old_decl))
-    warning ("%J`%D' was used with no declaration before its definition",
+    warning (0, "%J%qD was used with no declaration before its definition",
             decl1, decl1);
 
   /* This is a definition, not a reference.
@@ -6054,12 +5906,9 @@ start_function (tree declspecs, tree declarator, tree attributes)
   if (current_function_decl != 0)
     TREE_PUBLIC (decl1) = 0;
 
-#ifdef ENABLE_CHECKING
   /* This is the earliest point at which we might know the assembler
      name of the function.  Thus, if it's set before this, die horribly.  */
-  if (DECL_ASSEMBLER_NAME_SET_P (decl1))
-    abort ();
-#endif
+  gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
 
   /* If #pragma weak was used, mark the decl weak now.  */
   if (current_scope == file_scope)
@@ -6073,7 +5922,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
 
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
          != integer_type_node)
-       pedwarn ("%Jreturn type of '%D' is not `int'", decl1, decl1);
+       pedwarn ("%Jreturn type of %qD is not %<int%>", decl1, decl1);
 
       for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
           args = TREE_CHAIN (args))
@@ -6088,7 +5937,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
            {
            case 1:
              if (TYPE_MAIN_VARIANT (type) != integer_type_node)
-               pedwarn ("%Jfirst argument of '%D' should be `int'",
+               pedwarn ("%Jfirst argument of %qD should be %<int%>",
                         decl1, decl1);
              break;
 
@@ -6097,7 +5946,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
                  || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
                  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                      != char_type_node))
-               pedwarn ("%Jsecond argument of '%D' should be 'char **'",
+               pedwarn ("%Jsecond argument of %qD should be %<char **%>",
                          decl1, decl1);
              break;
 
@@ -6106,8 +5955,8 @@ start_function (tree declspecs, tree declarator, tree attributes)
                  || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
                  || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                      != char_type_node))
-               pedwarn ("%Jthird argument of '%D' should probably be "
-                         "'char **'", decl1, decl1);
+               pedwarn ("%Jthird argument of %qD should probably be "
+                         "%<char **%>", decl1, decl1);
              break;
            }
        }
@@ -6116,10 +5965,10 @@ start_function (tree declspecs, tree declarator, tree attributes)
         argument because it's only mentioned in an appendix of the
         standard.  */
       if (argct > 0 && (argct < 2 || argct > 3))
-       pedwarn ("%J'%D' takes only zero or two arguments", decl1, decl1);
+       pedwarn ("%J%qD takes only zero or two arguments", decl1, decl1);
 
-      if (! TREE_PUBLIC (decl1))
-       pedwarn ("%J'%D' is normally a non-static function", decl1, decl1);
+      if (!TREE_PUBLIC (decl1))
+       pedwarn ("%J%qD is normally a non-static function", decl1, decl1);
     }
 
   /* Record the decl so that the function name is defined.
@@ -6158,13 +6007,10 @@ start_function (tree declspecs, tree declarator, tree attributes)
    definitions (prototype format). The parms already have decls, so we
    need only record them as in effect and complain if any redundant
    old-style parm decls were written.  */
-void
-store_parm_decls_newstyle (tree fndecl, tree arg_info)
+static void
+store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
 {
   tree decl;
-  tree parms  = ARG_INFO_PARMS  (arg_info);
-  tree tags   = ARG_INFO_TAGS   (arg_info);
-  tree others = ARG_INFO_OTHERS (arg_info);
 
   if (current_scope->bindings)
     {
@@ -6180,13 +6026,13 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
      (this happens when a function definition has just an ellipsis in
      its parameter list).  */
   else if (warn_traditional && !in_system_header && !current_function_scope
-          && ARG_INFO_TYPES (arg_info) != error_mark_node)
-    warning ("%Jtraditional C rejects ISO C style function definitions",
+          && arg_info->types != error_mark_node)
+    warning (0, "%Jtraditional C rejects ISO C style function definitions",
             fndecl);
 
   /* Now make all the parameter declarations visible in the function body.
      We can bypass most of the grunt work of pushdecl.  */
-  for (decl = parms; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
@@ -6197,10 +6043,10 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
     }
 
   /* Record the parameter list in the function declaration.  */
-  DECL_ARGUMENTS (fndecl) = parms;
+  DECL_ARGUMENTS (fndecl) = arg_info->parms;
 
   /* Now make all the ancillary declarations visible, likewise.  */
-  for (decl = others; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
     {
       DECL_CONTEXT (decl) = current_function_decl;
       if (DECL_NAME (decl))
@@ -6209,7 +6055,7 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
     }
 
   /* And all the tag declarations.  */
-  for (decl = tags; decl; decl = TREE_CHAIN (decl))
+  for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
     if (TREE_PURPOSE (decl))
       bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
            /*invisible=*/false, /*nested=*/false);
@@ -6219,22 +6065,21 @@ store_parm_decls_newstyle (tree fndecl, tree arg_info)
    definitions (separate parameter list and declarations).  */
 
 static void
-store_parm_decls_oldstyle (tree fndecl, tree arg_info)
+store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
 {
   struct c_binding *b;
   tree parm, decl, last;
-  tree parmids = ARG_INFO_PARMS (arg_info);
+  tree parmids = arg_info->parms;
 
   /* We use DECL_WEAK as a flag to show which parameters have been
      seen already, since it is not used on PARM_DECL.  */
 #ifdef ENABLE_CHECKING
   for (b = current_scope->bindings; b; b = b->prev)
-    if (TREE_CODE (b->decl) == PARM_DECL && DECL_WEAK (b->decl))
-      abort ();
+    gcc_assert (TREE_CODE (b->decl) != PARM_DECL || !DECL_WEAK (b->decl));
 #endif
 
-  if (warn_old_style_definition && !in_system_header)
-    warning ("%Jold-style function definition", fndecl);
+  if (!in_system_header)
+    warning (OPT_Wold_style_definition, "%Jold-style function definition", fndecl);
 
   /* Match each formal parameter name with its declaration.  Save each
      decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
@@ -6253,12 +6098,12 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
          decl = b->decl;
          /* If we got something other than a PARM_DECL it is an error.  */
          if (TREE_CODE (decl) != PARM_DECL)
-           error ("%J'%D' declared as a non-parameter", decl, decl);
+           error ("%J%qD declared as a non-parameter", decl, decl);
          /* If the declaration is already marked, we have a duplicate
             name.  Complain and ignore the duplicate.  */
          else if (DECL_WEAK (decl))
            {
-             error ("%Jmultiple parameters named '%D'", decl, decl);
+             error ("%Jmultiple parameters named %qD", decl, decl);
              TREE_PURPOSE (parm) = 0;
              continue;
            }
@@ -6266,7 +6111,7 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
             an int.  */
          else if (VOID_TYPE_P (TREE_TYPE (decl)))
            {
-             error ("%Jparameter '%D' declared with void type", decl, decl);
+             error ("%Jparameter %qD declared with void type", decl, decl);
              TREE_TYPE (decl) = integer_type_node;
              DECL_ARG_TYPE (decl) = integer_type_node;
              layout_decl (decl, 0);
@@ -6281,9 +6126,9 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
          pushdecl (decl);
 
          if (flag_isoc99)
-           pedwarn ("%Jtype of '%D' defaults to 'int'", decl, decl);
+           pedwarn ("%Jtype of %qD defaults to %<int%>", decl, decl);
          else if (extra_warnings)
-           warning ("%Jtype of '%D' defaults to 'int'", decl, decl);
+           warning (0, "%Jtype of %qD defaults to %<int%>", decl, decl);
        }
 
       TREE_PURPOSE (parm) = decl;
@@ -6299,15 +6144,16 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
       if (TREE_CODE (parm) != PARM_DECL)
        continue;
 
-      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
+      if (TREE_TYPE (parm) != error_mark_node
+         && !COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
-         error ("%Jparameter '%D' has incomplete type", parm, parm);
+         error ("%Jparameter %qD has incomplete type", parm, parm);
          TREE_TYPE (parm) = error_mark_node;
        }
 
-      if (! DECL_WEAK (parm))
+      if (!DECL_WEAK (parm))
        {
-         error ("%Jdeclaration for parameter '%D' but no such parameter",
+         error ("%Jdeclaration for parameter %qD but no such parameter",
                 parm, parm);
 
          /* Pretend the parameter was not missing.
@@ -6345,11 +6191,11 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
      set the DECL_ARG_TYPE of each argument according to
      the type previously specified, and report any mismatches.  */
 
-  if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+  if (current_function_prototype_arg_types)
     {
       tree type;
       for (parm = DECL_ARGUMENTS (fndecl),
-            type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+            type = current_function_prototype_arg_types;
           parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
                             != void_type_node));
           parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
@@ -6357,16 +6203,22 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
          if (parm == 0 || type == 0
              || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
            {
-             error ("number of arguments doesn't match prototype");
-             error ("%Hprototype declaration",
-                    &current_function_prototype_locus);
+             if (current_function_prototype_built_in)
+               warning (0, "number of arguments doesn%'t match "
+                        "built-in prototype");
+             else
+               {
+                 error ("number of arguments doesn%'t match prototype");
+                 error ("%Hprototype declaration",
+                        &current_function_prototype_locus);
+               }
              break;
            }
          /* Type for passing arg must be consistent with that
             declared for the arg.  ISO C says we take the unqualified
             type for parameters declared with qualified type.  */
-         if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
-                          TYPE_MAIN_VARIANT (TREE_VALUE (type))))
+         if (!comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+                         TYPE_MAIN_VARIANT (TREE_VALUE (type))))
            {
              if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
                  == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -6386,17 +6238,33 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
 
                  if (pedantic)
                    {
-                     pedwarn ("promoted argument '%D' "
-                              "doesn't match prototype", parm);
-                     pedwarn ("%Hprototype declaration",
-                              &current_function_prototype_locus);
+                     /* ??? Is it possible to get here with a
+                        built-in prototype or will it always have
+                        been diagnosed as conflicting with an
+                        old-style definition and discarded?  */
+                     if (current_function_prototype_built_in)
+                       warning (0, "promoted argument %qD "
+                                "doesn%'t match built-in prototype", parm);
+                     else
+                       {
+                         pedwarn ("promoted argument %qD "
+                                  "doesn%'t match prototype", parm);
+                         pedwarn ("%Hprototype declaration",
+                                  &current_function_prototype_locus);
+                       }
                    }
                }
              else
                {
-                 error ("argument '%D' doesn't match prototype", parm);
-                 error ("%Hprototype declaration",
-                        &current_function_prototype_locus);
+                 if (current_function_prototype_built_in)
+                   warning (0, "argument %qD doesn%'t match "
+                            "built-in prototype", parm);
+                 else
+                   {
+                     error ("argument %qD doesn%'t match prototype", parm);
+                     error ("%Hprototype declaration",
+                            &current_function_prototype_locus);
+                   }
                }
            }
        }
@@ -6438,6 +6306,16 @@ store_parm_decls_oldstyle (tree fndecl, tree arg_info)
     }
 }
 
+/* Store parameter declarations passed in ARG_INFO into the current
+   function declaration.  */
+
+void
+store_parm_decls_from (struct c_arg_info *arg_info)
+{
+  current_function_arg_info = arg_info;
+  store_parm_decls ();
+}
+
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
    digesting the body of the function.
@@ -6452,7 +6330,7 @@ store_parm_decls (void)
   bool proto;
 
   /* The argument information block for FNDECL.  */
-  tree arg_info = current_function_arg_info;
+  struct c_arg_info *arg_info = current_function_arg_info;
   current_function_arg_info = 0;
 
   /* True if this definition is written with a prototype.  Note:
@@ -6460,7 +6338,7 @@ store_parm_decls (void)
      list in a function definition as equivalent to (void) -- an
      empty argument list specifies the function has no parameters,
      but only (void) sets up a prototype for future calls.  */
-  proto = ARG_INFO_TYPES (arg_info) != 0;
+  proto = arg_info->types != 0;
 
   if (proto)
     store_parm_decls_newstyle (fndecl, arg_info);
@@ -6483,8 +6361,11 @@ store_parm_decls (void)
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
 
   /* ??? Insert the contents of the pending sizes list into the function
-     to be evaluated.  This just changes mis-behaviour until assign_parms
-     phase ordering problems are resolved.  */
+     to be evaluated.  The only reason left to have this is
+       void foo(int n, int array[n++])
+     because we throw away the array type in favor of a pointer type, and
+     thus won't naturally see the SAVE_EXPR containing the increment.  All
+     other pending sizes would be handled by gimplify_parameters.  */
   {
     tree t;
     for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
@@ -6498,30 +6379,21 @@ store_parm_decls (void)
   cfun->x_dont_save_pending_sizes_p = 1;
 }
 \f
-/* Give FNDECL and all its nested functions to cgraph for compilation.  */
+/* Handle attribute((warn_unused_result)) on FNDECL and all its nested
+   functions.  */
 
 static void
-c_finalize (tree fndecl)
+c_warn_unused_result_recursively (tree fndecl)
 {
   struct cgraph_node *cgn;
 
   /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
   c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
 
-  /* ??? Objc emits functions after finalizing the compilation unit.
-     This should be cleaned up later and this conditional removed.  */
-  if (cgraph_global_info_ready)
-    {
-      c_expand_body (fndecl);
-      return;
-    }
-
   /* Finalize all nested functions now.  */
   cgn = cgraph_node (fndecl);
   for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
-    c_finalize (cgn->decl);
-
-  cgraph_finalize_function (fndecl, false);
+    c_warn_unused_result_recursively (cgn->decl);
 }
 
 /* Finish up a function declaration and compile that function
@@ -6535,6 +6407,9 @@ finish_function (void)
 {
   tree fndecl = current_function_decl;
 
+  label_context_stack_se = label_context_stack_se->next;
+  label_context_stack_vm = label_context_stack_vm->next;
+
   if (TREE_CODE (fndecl) == FUNCTION_DECL
       && targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
     {
@@ -6564,12 +6439,28 @@ finish_function (void)
          /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
             If warn_main is -1 (-Wno-main) we don't want to be warned.  */
          if (!warn_main)
-           pedwarn ("%Jreturn type of '%D' is not `int'", fndecl, fndecl);
+           pedwarn ("%Jreturn type of %qD is not %<int%>", fndecl, fndecl);
        }
       else
        {
          if (flag_isoc99)
-           c_finish_return (integer_zero_node);
+           {
+             tree stmt = c_finish_return (integer_zero_node);
+#ifdef USE_MAPPED_LOCATION
+             /* Hack.  We don't want the middle-end to warn that this return
+                is unreachable, so we mark its location as special.  Using
+                UNKNOWN_LOCATION has the problem that it gets clobbered in
+                annotate_one_with_locus.  A cleaner solution might be to
+                ensure ! should_carry_locus_p (stmt), but that needs a flag.
+             */
+             SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION);
+#else
+             /* Hack.  We don't want the middle-end to warn that this
+                return is unreachable, so put the statement on the
+                special line 0.  */
+             annotate_with_file_line (stmt, input_filename, 0);
+#endif
+           }
        }
     }
 
@@ -6582,7 +6473,7 @@ finish_function (void)
   if (warn_return_type
       && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
       && !current_function_returns_value && !current_function_returns_null
-      /* Don't complain if we abort.  */
+      /* Don't complain if we are no-return.  */
       && !current_function_returns_abnormally
       /* Don't warn for main().  */
       && !MAIN_NAME_P (DECL_NAME (fndecl))
@@ -6591,14 +6482,17 @@ finish_function (void)
       /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
         inline function, as we might never be compiled separately.  */
       && DECL_INLINE (fndecl))
-    warning ("no return statement in function returning non-void");
+    {
+      warning (0, "no return statement in function returning non-void");
+      TREE_NO_WARNING (fndecl) = 1;
+    }
 
   /* With just -Wextra, complain only if function returns both with
      and without a value.  */
   if (extra_warnings
       && current_function_returns_value
       && current_function_returns_null)
-    warning ("this function may return with or without a value");
+    warning (0, "this function may return with or without a value");
 
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
@@ -6620,13 +6514,23 @@ finish_function (void)
      until their parent function is genericized.  Since finalizing
      requires GENERIC, delay that as well.  */
 
-  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
+  if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node
+      && !undef_nested_function)
     {
       if (!decl_function_context (fndecl))
         {
           c_genericize (fndecl);
-         lower_nested_functions (fndecl);
-          c_finalize (fndecl);
+          c_warn_unused_result_recursively (fndecl);
+
+         /* ??? Objc emits functions after finalizing the compilation unit.
+            This should be cleaned up later and this conditional removed.  */
+         if (cgraph_global_info_ready)
+           {
+             c_expand_body (fndecl);
+             return;
+           }
+
+         cgraph_finalize_function (fndecl, false);
         }
       else
         {
@@ -6637,6 +6541,9 @@ finish_function (void)
         }
     }
 
+  if (!decl_function_context (fndecl))
+    undef_nested_function = false;
+
   /* We're leaving the context of this function, so zap cfun.
      It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
      tree_rest_of_compilation.  */
@@ -6654,7 +6561,7 @@ c_expand_body (tree fndecl)
       || DECL_INITIAL (fndecl) == error_mark_node)
     return;
 
-  tree_rest_of_compilation (fndecl, false);
+  tree_rest_of_compilation (fndecl);
 
   if (DECL_STATIC_CONSTRUCTOR (fndecl)
       && targetm.have_ctors_dtors)
@@ -6678,7 +6585,7 @@ check_for_loop_decls (void)
       /* If we get here, declarations have been used in a for loop without
         the C99 for loop scope.  This doesn't make much sense, so don't
         allow it.  */
-      error ("'for' loop initial declaration used outside C99 mode");
+      error ("%<for%> loop initial declaration used outside C99 mode");
       return;
     }
   /* C99 subclause 6.8.5 paragraph 3:
@@ -6707,24 +6614,27 @@ check_for_loop_decls (void)
        {
        case VAR_DECL:
          if (TREE_STATIC (decl))
-           error ("%Jdeclaration of static variable '%D' in 'for' loop "
+           error ("%Jdeclaration of static variable %qD in %<for%> loop "
                   "initial declaration", decl, decl);
          else if (DECL_EXTERNAL (decl))
-           error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
+           error ("%Jdeclaration of %<extern%> variable %qD in %<for%> loop "
                   "initial declaration", decl, decl);
          break;
 
        case RECORD_TYPE:
-         error ("'struct %E' declared in 'for' loop initial declaration", id);
+         error ("%<struct %E%> declared in %<for%> loop initial declaration",
+                id);
          break;
        case UNION_TYPE:
-         error ("'union %E' declared in 'for' loop initial declaration", id);
+         error ("%<union %E%> declared in %<for%> loop initial declaration",
+                id);
          break;
        case ENUMERAL_TYPE:
-         error ("'enum %E' declared in 'for' loop initial declaration", id);
+         error ("%<enum %E%> declared in %<for%> loop initial declaration",
+                id);
          break;
        default:
-         error ("%Jdeclaration of non-variable '%D' in 'for' loop "
+         error ("%Jdeclaration of non-variable %qD in %<for%> loop "
                 "initial declaration", decl, decl);
        }
     }
@@ -6832,13 +6742,6 @@ anon_aggr_type_p (tree ARG_UNUSED (node))
   return 0;
 }
 
-/* Dummy function in place of callback used by C++.  */
-
-void
-extract_interface_info (void)
-{
-}
-
 /* Return the global value of T as a symbol.  */
 
 tree
@@ -6878,52 +6781,683 @@ build_void_list_node (void)
   return t;
 }
 
-/* Return a structure for a parameter with the given SPECS, ATTRS and
-   DECLARATOR.  */
+/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR.  */
 
-tree
-build_c_parm (tree specs, tree attrs, tree declarator)
+struct c_parm *
+build_c_parm (struct c_declspecs *specs, tree attrs,
+             struct c_declarator *declarator)
 {
-  return build_tree_list (build_tree_list (specs, declarator), attrs);
+  struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
+  ret->specs = specs;
+  ret->attrs = attrs;
+  ret->declarator = declarator;
+  return ret;
 }
 
 /* Return a declarator with nested attributes.  TARGET is the inner
    declarator to which these attributes apply.  ATTRS are the
    attributes.  */
 
-tree
-build_attrs_declarator (tree attrs, tree target)
+struct c_declarator *
+build_attrs_declarator (tree attrs, struct c_declarator *target)
 {
-  return tree_cons (attrs, target, NULL_TREE);
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_attrs;
+  ret->declarator = target;
+  ret->u.attrs = attrs;
+  return ret;
 }
 
 /* Return a declarator for a function with arguments specified by ARGS
    and return type specified by TARGET.  */
 
-tree
-build_function_declarator (tree args, tree target)
+struct c_declarator *
+build_function_declarator (struct c_arg_info *args,
+                          struct c_declarator *target)
+{
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_function;
+  ret->declarator = target;
+  ret->u.arg_info = args;
+  return ret;
+}
+
+/* Return a declarator for the identifier IDENT (which may be
+   NULL_TREE for an abstract declarator).  */
+
+struct c_declarator *
+build_id_declarator (tree ident)
 {
-  return build_nt (CALL_EXPR, target, args, NULL_TREE);
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  ret->kind = cdk_id;
+  ret->declarator = 0;
+  ret->u.id = ident;
+  /* Default value - may get reset to a more precise location. */
+  ret->id_loc = input_location;
+  return ret;
 }
 
 /* Return something to represent absolute declarators containing a *.
    TARGET is the absolute declarator that the * contains.
-   TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
-   to apply to the pointer type, represented as identifiers, possible mixed
-   with attributes.
+   TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes
+   to apply to the pointer type.  */
+
+struct c_declarator *
+make_pointer_declarator (struct c_declspecs *type_quals_attrs,
+                        struct c_declarator *target)
+{
+  tree attrs;
+  int quals = 0;
+  struct c_declarator *itarget = target;
+  struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+  if (type_quals_attrs)
+    {
+      attrs = type_quals_attrs->attrs;
+      quals = quals_from_declspecs (type_quals_attrs);
+      if (attrs != NULL_TREE)
+       itarget = build_attrs_declarator (attrs, target);
+    }
+  ret->kind = cdk_pointer;
+  ret->declarator = itarget;
+  ret->u.pointer_quals = quals;
+  return ret;
+}
 
-   We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
-   if attributes are present) and whose type is the modifier list.  */
+/* Return a pointer to a structure for an empty list of declaration
+   specifiers.  */
 
-tree
-make_pointer_declarator (tree type_quals_attrs, tree target)
+struct c_declspecs *
+build_null_declspecs (void)
+{
+  struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+  ret->type = 0;
+  ret->decl_attr = 0;
+  ret->attrs = 0;
+  ret->typespec_word = cts_none;
+  ret->storage_class = csc_none;
+  ret->declspecs_seen_p = false;
+  ret->type_seen_p = false;
+  ret->non_sc_seen_p = false;
+  ret->typedef_p = false;
+  ret->tag_defined_p = false;
+  ret->explicit_signed_p = false;
+  ret->deprecated_p = false;
+  ret->default_int_p = false;
+  ret->long_p = false;
+  ret->long_long_p = false;
+  ret->short_p = false;
+  ret->signed_p = false;
+  ret->unsigned_p = false;
+  ret->complex_p = false;
+  ret->inline_p = false;
+  ret->thread_p = false;
+  ret->const_p = false;
+  ret->volatile_p = false;
+  ret->restrict_p = false;
+  return ret;
+}
+
+/* Add the type qualifier QUAL to the declaration specifiers SPECS,
+   returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_qual (struct c_declspecs *specs, tree qual)
+{
+  enum rid i;
+  bool dupe = false;
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+  gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
+             && C_IS_RESERVED_WORD (qual));
+  i = C_RID_CODE (qual);
+  switch (i)
+    {
+    case RID_CONST:
+      dupe = specs->const_p;
+      specs->const_p = true;
+      break;
+    case RID_VOLATILE:
+      dupe = specs->volatile_p;
+      specs->volatile_p = true;
+      break;
+    case RID_RESTRICT:
+      dupe = specs->restrict_p;
+      specs->restrict_p = true;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (dupe && pedantic && !flag_isoc99)
+    pedwarn ("duplicate %qE", qual);
+  return specs;
+}
+
+/* Add the type specifier TYPE to the declaration specifiers SPECS,
+   returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
 {
-  tree quals, attrs;
-  tree itarget = target;
-  split_specs_attrs (type_quals_attrs, &quals, &attrs);
-  if (attrs != NULL_TREE)
-    itarget = build_attrs_declarator (attrs, target);
-  return build1 (INDIRECT_REF, quals, itarget);
+  tree type = spec.spec;
+  specs->non_sc_seen_p = true;
+  specs->declspecs_seen_p = true;
+  specs->type_seen_p = true;
+  if (TREE_DEPRECATED (type))
+    specs->deprecated_p = true;
+
+  /* Handle type specifier keywords.  */
+  if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type))
+    {
+      enum rid i = C_RID_CODE (type);
+      if (specs->type)
+       {
+         error ("two or more data types in declaration specifiers");
+         return specs;
+       }
+      if ((int) i <= (int) RID_LAST_MODIFIER)
+       {
+         /* "long", "short", "signed", "unsigned" or "_Complex".  */
+         bool dupe = false;
+         switch (i)
+           {
+           case RID_LONG:
+             if (specs->long_long_p)
+               {
+                 error ("%<long long long%> is too long for GCC");
+                 break;
+               }
+             if (specs->long_p)
+               {
+                 if (specs->typespec_word == cts_double)
+                   {
+                     error ("both %<long long%> and %<double%> in "
+                            "declaration specifiers");
+                     break;
+                   }
+                 if (pedantic && !flag_isoc99 && !in_system_header
+                     && warn_long_long)
+                   pedwarn ("ISO C90 does not support %<long long%>");
+                 specs->long_long_p = 1;
+                 break;
+               }
+             if (specs->short_p)
+               error ("both %<long%> and %<short%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_void)
+               error ("both %<long%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_bool)
+               error ("both %<long%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_char)
+               error ("both %<long%> and %<char%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_float)
+               error ("both %<long%> and %<float%> in "
+                      "declaration specifiers");
+             else
+               specs->long_p = true;
+             break;
+           case RID_SHORT:
+             dupe = specs->short_p;
+             if (specs->long_p)
+               error ("both %<long%> and %<short%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_void)
+               error ("both %<short%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_bool)
+               error ("both %<short%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_char)
+               error ("both %<short%> and %<char%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_float)
+               error ("both %<short%> and %<float%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_double)
+               error ("both %<short%> and %<double%> in "
+                      "declaration specifiers");
+             else
+               specs->short_p = true;
+             break;
+           case RID_SIGNED:
+             dupe = specs->signed_p;
+             if (specs->unsigned_p)
+               error ("both %<signed%> and %<unsigned%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_void)
+               error ("both %<signed%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_bool)
+               error ("both %<signed%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_float)
+               error ("both %<signed%> and %<float%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_double)
+               error ("both %<signed%> and %<double%> in "
+                      "declaration specifiers");
+             else
+               specs->signed_p = true;
+             break;
+           case RID_UNSIGNED:
+             dupe = specs->unsigned_p;
+             if (specs->signed_p)
+               error ("both %<signed%> and %<unsigned%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_void)
+               error ("both %<unsigned%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_bool)
+               error ("both %<unsigned%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_float)
+               error ("both %<unsigned%> and %<float%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_double)
+               error ("both %<unsigned%> and %<double%> in "
+                      "declaration specifiers");
+             else
+               specs->unsigned_p = true;
+             break;
+           case RID_COMPLEX:
+             dupe = specs->complex_p;
+             if (pedantic && !flag_isoc99 && !in_system_header)
+               pedwarn ("ISO C90 does not support complex types");
+             if (specs->typespec_word == cts_void)
+               error ("both %<complex%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->typespec_word == cts_bool)
+               error ("both %<complex%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else
+               specs->complex_p = true;
+             break;
+           default:
+             gcc_unreachable ();
+           }
+
+         if (dupe)
+           error ("duplicate %qE", type);
+
+         return specs;
+       }
+      else
+       {
+         /* "void", "_Bool", "char", "int", "float" or "double".  */
+         if (specs->typespec_word != cts_none)
+           {
+             error ("two or more data types in declaration specifiers");
+             return specs;
+           }
+         switch (i)
+           {
+           case RID_VOID:
+             if (specs->long_p)
+               error ("both %<long%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->short_p)
+               error ("both %<short%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->signed_p)
+               error ("both %<signed%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->unsigned_p)
+               error ("both %<unsigned%> and %<void%> in "
+                      "declaration specifiers");
+             else if (specs->complex_p)
+               error ("both %<complex%> and %<void%> in "
+                      "declaration specifiers");
+             else
+               specs->typespec_word = cts_void;
+             return specs;
+           case RID_BOOL:
+             if (specs->long_p)
+               error ("both %<long%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->short_p)
+               error ("both %<short%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->signed_p)
+               error ("both %<signed%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->unsigned_p)
+               error ("both %<unsigned%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else if (specs->complex_p)
+               error ("both %<complex%> and %<_Bool%> in "
+                      "declaration specifiers");
+             else
+               specs->typespec_word = cts_bool;
+             return specs;
+           case RID_CHAR:
+             if (specs->long_p)
+               error ("both %<long%> and %<char%> in "
+                      "declaration specifiers");
+             else if (specs->short_p)
+               error ("both %<short%> and %<char%> in "
+                      "declaration specifiers");
+             else
+               specs->typespec_word = cts_char;
+             return specs;
+           case RID_INT:
+             specs->typespec_word = cts_int;
+             return specs;
+           case RID_FLOAT:
+             if (specs->long_p)
+               error ("both %<long%> and %<float%> in "
+                      "declaration specifiers");
+             else if (specs->short_p)
+               error ("both %<short%> and %<float%> in "
+                      "declaration specifiers");
+             else if (specs->signed_p)
+               error ("both %<signed%> and %<float%> in "
+                      "declaration specifiers");
+             else if (specs->unsigned_p)
+               error ("both %<unsigned%> and %<float%> in "
+                      "declaration specifiers");
+             else
+               specs->typespec_word = cts_float;
+             return specs;
+           case RID_DOUBLE:
+             if (specs->long_long_p)
+               error ("both %<long long%> and %<double%> in "
+                      "declaration specifiers");
+             else if (specs->short_p)
+               error ("both %<short%> and %<double%> in "
+                      "declaration specifiers");
+             else if (specs->signed_p)
+               error ("both %<signed%> and %<double%> in "
+                      "declaration specifiers");
+             else if (specs->unsigned_p)
+               error ("both %<unsigned%> and %<double%> in "
+                      "declaration specifiers");
+             else
+               specs->typespec_word = cts_double;
+             return specs;
+           default:
+             /* ObjC reserved word "id", handled below.  */
+             break;
+           }
+       }
+    }
+
+  /* Now we have a typedef (a TYPE_DECL node), an identifier (some
+     form of ObjC type, cases such as "int" and "long" being handled
+     above), a TYPE (struct, union, enum and typeof specifiers) or an
+     ERROR_MARK.  In none of these cases may there have previously
+     been any type specifiers.  */
+  if (specs->type || specs->typespec_word != cts_none
+      || specs->long_p || specs->short_p || specs->signed_p
+      || specs->unsigned_p || specs->complex_p)
+    error ("two or more data types in declaration specifiers");
+  else if (TREE_CODE (type) == TYPE_DECL)
+    {
+      if (TREE_TYPE (type) == error_mark_node)
+       ; /* Allow the type to default to int to avoid cascading errors.  */
+      else
+       {
+         specs->type = TREE_TYPE (type);
+         specs->decl_attr = DECL_ATTRIBUTES (type);
+         specs->typedef_p = true;
+         specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+       }
+    }
+  else if (TREE_CODE (type) == IDENTIFIER_NODE)
+    {
+      tree t = lookup_name (type);
+      if (!t || TREE_CODE (t) != TYPE_DECL)
+       error ("%qE fails to be a typedef or built in type", type);
+      else if (TREE_TYPE (t) == error_mark_node)
+       ;
+      else
+       specs->type = TREE_TYPE (t);
+    }
+  else if (TREE_CODE (type) != ERROR_MARK)
+    {
+      if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
+       specs->tag_defined_p = true;
+      if (spec.kind == ctsk_typeof)
+       specs->typedef_p = true;
+      specs->type = type;
+    }
+
+  return specs;
+}
+
+/* Add the storage class specifier or function specifier SCSPEC to the
+   declaration specifiers SPECS, returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
+{
+  enum rid i;
+  enum c_storage_class n = csc_none;
+  bool dupe = false;
+  specs->declspecs_seen_p = true;
+  gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
+             && C_IS_RESERVED_WORD (scspec));
+  i = C_RID_CODE (scspec);
+  if (extra_warnings && specs->non_sc_seen_p)
+    warning (0, "%qE is not at beginning of declaration", scspec);
+  switch (i)
+    {
+    case RID_INLINE:
+      /* C99 permits duplicate inline.  Although of doubtful utility,
+        it seems simplest to permit it in gnu89 mode as well, as
+        there is also little utility in maintaining this as a
+        difference between gnu89 and C99 inline.  */
+      dupe = false;
+      specs->inline_p = true;
+      break;
+    case RID_THREAD:
+      dupe = specs->thread_p;
+      if (specs->storage_class == csc_auto)
+       error ("%<__thread%> used with %<auto%>");
+      else if (specs->storage_class == csc_register)
+       error ("%<__thread%> used with %<register%>");
+      else if (specs->storage_class == csc_typedef)
+       error ("%<__thread%> used with %<typedef%>");
+      else
+       specs->thread_p = true;
+      break;
+    case RID_AUTO:
+      n = csc_auto;
+      break;
+    case RID_EXTERN:
+      n = csc_extern;
+      /* Diagnose "__thread extern".  */
+      if (specs->thread_p)
+       error ("%<__thread%> before %<extern%>");
+      break;
+    case RID_REGISTER:
+      n = csc_register;
+      break;
+    case RID_STATIC:
+      n = csc_static;
+      /* Diagnose "__thread static".  */
+      if (specs->thread_p)
+       error ("%<__thread%> before %<static%>");
+      break;
+    case RID_TYPEDEF:
+      n = csc_typedef;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  if (n != csc_none && n == specs->storage_class)
+    dupe = true;
+  if (dupe)
+    error ("duplicate %qE", scspec);
+  if (n != csc_none)
+    {
+      if (specs->storage_class != csc_none && n != specs->storage_class)
+       {
+         error ("multiple storage classes in declaration specifiers");
+       }
+      else
+       {
+         specs->storage_class = n;
+         if (n != csc_extern && n != csc_static && specs->thread_p)
+           {
+             error ("%<__thread%> used with %qE", scspec);
+             specs->thread_p = false;
+           }
+       }
+    }
+  return specs;
+}
+
+/* Add the attributes ATTRS to the declaration specifiers SPECS,
+   returning SPECS.  */
+
+struct c_declspecs *
+declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+{
+  specs->attrs = chainon (attrs, specs->attrs);
+  specs->declspecs_seen_p = true;
+  return specs;
+}
+
+/* Combine "long", "short", "signed", "unsigned" and "_Complex" type
+   specifiers with any other type specifier to determine the resulting
+   type.  This is where ISO C checks on complex types are made, since
+   "_Complex long" is a prefix of the valid ISO C type "_Complex long
+   double".  */
+
+struct c_declspecs *
+finish_declspecs (struct c_declspecs *specs)
+{
+  /* If a type was specified as a whole, we have no modifiers and are
+     done.  */
+  if (specs->type != NULL_TREE)
+    {
+      gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p
+                 && !specs->complex_p);
+      return specs;
+    }
+
+  /* If none of "void", "_Bool", "char", "int", "float" or "double"
+     has been specified, treat it as "int" unless "_Complex" is
+     present and there are no other specifiers.  If we just have
+     "_Complex", it is equivalent to "_Complex double", but e.g.
+     "_Complex short" is equivalent to "_Complex short int".  */
+  if (specs->typespec_word == cts_none)
+    {
+      if (specs->long_p || specs->short_p
+         || specs->signed_p || specs->unsigned_p)
+       {
+         specs->typespec_word = cts_int;
+       }
+      else if (specs->complex_p)
+       {
+         specs->typespec_word = cts_double;
+         if (pedantic)
+           pedwarn ("ISO C does not support plain %<complex%> meaning "
+                    "%<double complex%>");
+       }
+      else
+       {
+         specs->typespec_word = cts_int;
+         specs->default_int_p = true;
+         /* We don't diagnose this here because grokdeclarator will
+            give more specific diagnostics according to whether it is
+            a function definition.  */
+       }
+    }
+
+  /* If "signed" was specified, record this to distinguish "int" and
+     "signed int" in the case of a bit-field with
+     -funsigned-bitfields.  */
+  specs->explicit_signed_p = specs->signed_p;
+
+  /* Now compute the actual type.  */
+  switch (specs->typespec_word)
+    {
+    case cts_void:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p
+                 && !specs->complex_p);
+      specs->type = void_type_node;
+      break;
+    case cts_bool:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p
+                 && !specs->complex_p);
+      specs->type = boolean_type_node;
+      break;
+    case cts_char:
+      gcc_assert (!specs->long_p && !specs->short_p);
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      if (specs->signed_p)
+       specs->type = signed_char_type_node;
+      else if (specs->unsigned_p)
+       specs->type = unsigned_char_type_node;
+      else
+       specs->type = char_type_node;
+      if (specs->complex_p)
+       {
+         if (pedantic)
+           pedwarn ("ISO C does not support complex integer types");
+         specs->type = build_complex_type (specs->type);
+       }
+      break;
+    case cts_int:
+      gcc_assert (!(specs->long_p && specs->short_p));
+      gcc_assert (!(specs->signed_p && specs->unsigned_p));
+      if (specs->long_long_p)
+       specs->type = (specs->unsigned_p
+                      ? long_long_unsigned_type_node
+                      : long_long_integer_type_node);
+      else if (specs->long_p)
+       specs->type = (specs->unsigned_p
+                      ? long_unsigned_type_node
+                      : long_integer_type_node);
+      else if (specs->short_p)
+       specs->type = (specs->unsigned_p
+                      ? short_unsigned_type_node
+                      : short_integer_type_node);
+      else
+       specs->type = (specs->unsigned_p
+                      ? unsigned_type_node
+                      : integer_type_node);
+      if (specs->complex_p)
+       {
+         if (pedantic)
+           pedwarn ("ISO C does not support complex integer types");
+         specs->type = build_complex_type (specs->type);
+       }
+      break;
+    case cts_float:
+      gcc_assert (!specs->long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p);
+      specs->type = (specs->complex_p
+                    ? complex_float_type_node
+                    : float_type_node);
+      break;
+    case cts_double:
+      gcc_assert (!specs->long_long_p && !specs->short_p
+                 && !specs->signed_p && !specs->unsigned_p);
+      if (specs->long_p)
+       {
+         specs->type = (specs->complex_p
+                        ? complex_long_double_type_node
+                        : long_double_type_node);
+       }
+      else
+       {
+         specs->type = (specs->complex_p
+                        ? complex_double_type_node
+                        : double_type_node);
+       }
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return specs;
 }
 
 /* Synthesize a function which calls all the global ctors or global
@@ -6956,7 +7490,21 @@ c_write_global_declarations_1 (tree globals)
 
   /* Process the decls in the order they were written.  */
   for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
-    vec[i] = decl;
+    {
+      vec[i] = decl;
+      /* Check for used but undefined static functions using the C
+        standard's definition of "used", and set TREE_NO_WARNING so
+        that check_global_declarations doesn't repeat the check.  */
+      if (TREE_CODE (decl) == FUNCTION_DECL
+         && DECL_INITIAL (decl) == 0
+         && DECL_EXTERNAL (decl)
+         && !TREE_PUBLIC (decl)
+         && C_DECL_USED (decl))
+       {
+         pedwarn ("%J%qF used but never defined", decl, decl);
+         TREE_NO_WARNING (decl) = 1;
+       }
+    }
 
   wrapup_global_declarations (vec, len);
   check_global_declarations (vec, len);
@@ -6981,8 +7529,7 @@ c_write_global_declarations (void)
   /* Close the external scope.  */
   ext_block = pop_scope ();
   external_scope = 0;
-  if (current_scope)
-    abort ();
+  gcc_assert (!current_scope);
 
   /* Process all file scopes in this compilation, and the external_scope,
      through wrapup_global_declarations and check_global_declarations.  */
@@ -6999,11 +7546,6 @@ c_write_global_declarations (void)
   /* We're done parsing; proceed to optimize and emit assembly.
      FIXME: shouldn't be the front end's responsibility to call this.  */
   cgraph_optimize ();
-
-  /* Presently this has to happen after cgraph_optimize.
-     FIXME: shouldn't be the front end's responsibility to call this.  */
-  if (flag_mudflap)
-    mudflap_finish_file ();
 }
 
 #include "gt-c-decl.h"