OSDN Git Service

Index: gcc/ChangeLog
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 06bbbef..2d21a43 100644 (file)
@@ -1,23 +1,23 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001 Free Software Foundation, Inc.
+   2001, 2002 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 /* Process declarations and symbol lookup for C front end.
    Also constructs types; the standard scalar types at initialization,
@@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "intl.h"
 #include "tree.h"
+#include "tree-inline.h"
 #include "rtl.h"
 #include "flags.h"
 #include "function.h"
@@ -38,10 +39,13 @@ Boston, MA 02111-1307, USA.  */
 #include "c-tree.h"
 #include "c-lex.h"
 #include "toplev.h"
-#include "defaults.h"
 #include "ggc.h"
 #include "tm_p.h"
 #include "cpplib.h"
+#include "target.h"
+#include "debug.h"
+#include "timevar.h"
+#include "c-common.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -105,11 +109,6 @@ static struct stmt_tree_s c_stmt_tree;
 
 static tree c_scope_stmt_stack;
 
-/* Nonzero if __FUNCTION__ and its ilk have been declared in this
-   function.  */
-
-static int c_function_name_declared_p;
-
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
    that have names.  Here so we can clear out their names' definitions
    at the end of the function.  */
@@ -280,13 +279,14 @@ static tree grokdeclarator                PARAMS ((tree, tree, enum decl_context,
                                                 int));
 static tree grokparms                  PARAMS ((tree, int));
 static void layout_array_type          PARAMS ((tree));
-static tree c_make_fname_decl           PARAMS ((tree, const char *, int));
-static void c_expand_body               PARAMS ((tree, int));
+static tree c_make_fname_decl           PARAMS ((tree, int));
+static void c_expand_body               PARAMS ((tree, int, int));
+static void warn_if_shadowing          PARAMS ((tree, tree));
 \f
 /* C-specific option variables.  */
 
 /* Nonzero means allow type mismatches in conditional expressions;
-   just make their values `void'.   */
+   just make their values `void'.  */
 
 int flag_cond_mismatch;
 
@@ -432,10 +432,6 @@ int warn_float_equal = 0;
 
 int warn_multichar = 1;
 
-/* The variant of the C language being processed.  */
-
-c_language_kind c_language = clk_c;
-
 /* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
@@ -443,6 +439,18 @@ c_language_kind c_language = clk_c;
 #endif
 int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+   
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
+
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
 /* Decode the string P as a language-specific option for C.
    Return the number of strings consumed.  Should not complain
    if it does not recognise the option.  */
@@ -453,13 +461,13 @@ c_decode_option (argc, argv)
      char **argv;
 {
   int strings_processed;
-  const char *option_value = NULL;
   char *p = argv[0];
 
   strings_processed = cpp_handle_option (parse_in, argc, argv);
 
   if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
     {
+      warning ("-traditional is deprecated and may be removed");
       flag_traditional = 1;
       flag_writable_strings = 1;
     }
@@ -495,7 +503,7 @@ c_decode_option (argc, argv)
         -std=gnu89             default, iso9899:1990 + gnu extensions
         -std=gnu99             iso9899:1999 + gnu extensions
       */
-      const char *argstart = &p[5];
+      const char *const argstart = &p[5];
 
       if (!strcmp (argstart, "iso9899:1990")
          || !strcmp (argstart, "c89"))
@@ -599,14 +607,10 @@ c_decode_option (argc, argv)
     flag_no_builtin = 0;
   else if (!strcmp (p, "-fno-builtin"))
     flag_no_builtin = 1;
-  else if ((option_value
-           = skip_leading_substring (p, "-fdump-translation-unit-")))
-    {
-      if (p[22] == '\0')
-       error ("no file specified with -fdump-translation-unit");
-      else
-       flag_dump_translation_unit = option_value;
-    }
+  else if (!strncmp (p, "-fno-builtin-", strlen ("-fno-builtin-")))
+    disable_builtin_function (p + strlen ("-fno-builtin-"));
+  else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
+    ;
   else if (!strcmp (p, "-ansi"))
     goto iso_1990;
   else if (!strcmp (p, "-Werror-implicit-function-declaration"))
@@ -759,6 +763,10 @@ c_decode_option (argc, argv)
     warn_multichar = 1;
   else if (!strcmp (p, "-Wno-multichar"))
     warn_multichar = 0;
+  else if (!strcmp (p, "-Wdiv-by-zero"))
+    warn_div_by_zero = 1;
+  else if (!strcmp (p, "-Wno-div-by-zero"))
+    warn_div_by_zero = 0;
   else if (!strcmp (p, "-Wunknown-pragmas"))
     /* Set to greater than 1, so that even unknown pragmas in system
        headers will be warned about.  */
@@ -794,26 +802,8 @@ c_decode_option (argc, argv)
   return 1;
 }
 
-/* Hooks for print_node.  */
-
-void
-print_lang_decl (file, node, indent)
-     FILE *file ATTRIBUTE_UNUSED;
-     tree node ATTRIBUTE_UNUSED;
-     int indent ATTRIBUTE_UNUSED;
-{
-}
-
 void
-print_lang_type (file, node, indent)
-     FILE *file ATTRIBUTE_UNUSED;
-     tree node ATTRIBUTE_UNUSED;
-     int indent ATTRIBUTE_UNUSED;
-{
-}
-
-void
-print_lang_identifier (file, node, indent)
+c_print_identifier (file, node, indent)
      FILE *file;
      tree node;
      int indent;
@@ -922,7 +912,7 @@ void
 pushlevel (tag_transparent)
      int tag_transparent;
 {
-  register struct binding_level *newlevel = NULL_BINDING_LEVEL;
+  struct binding_level *newlevel = NULL_BINDING_LEVEL;
 
   /* If this is the top level of a function,
      just make sure that NAMED_LABELS is 0.  */
@@ -998,7 +988,7 @@ poplevel (keep, reverse, functionbody)
      int reverse;
      int functionbody;
 {
-  register tree link;
+  tree link;
   /* The chain of decls was accumulated in reverse order.
      Put it into forward order, just for cleanliness.  */
   tree decls;
@@ -1141,7 +1131,7 @@ poplevel (keep, reverse, functionbody)
 
       for (link = named_labels; link; link = TREE_CHAIN (link))
        {
-         register tree label = TREE_VALUE (link);
+         tree label = TREE_VALUE (link);
 
          if (DECL_INITIAL (label) == 0)
            {
@@ -1164,7 +1154,7 @@ poplevel (keep, reverse, functionbody)
   /* Pop the current level, and free the structure for reuse.  */
 
   {
-    register struct binding_level *level = current_binding_level;
+    struct binding_level *level = current_binding_level;
     current_binding_level = current_binding_level->level_chain;
 
     level->level_chain = free_binding_level;
@@ -1216,30 +1206,6 @@ poplevel (keep, reverse, functionbody)
   return block;
 }
 
-/* Delete the node BLOCK from the current binding level.
-   This is used for the block inside a stmt expr ({...})
-   so that the block can be reinserted where appropriate.  */
-
-void
-delete_block (block)
-     tree block;
-{
-  tree t;
-  if (current_binding_level->blocks == block)
-    current_binding_level->blocks = TREE_CHAIN (block);
-  for (t = current_binding_level->blocks; t;)
-    {
-      if (TREE_CHAIN (t) == block)
-       TREE_CHAIN (t) = TREE_CHAIN (block);
-      else
-       t = TREE_CHAIN (t);
-    }
-  TREE_CHAIN (block) = NULL;
-  /* Clear TREE_USED which is always set by poplevel.
-     The flag is set again if insert_block is called.  */
-  TREE_USED (block) = 0;
-}
-
 /* Insert BLOCK at the end of the list of subblocks of the
    current binding level.  This is used when a BIND_EXPR is expanded,
    to handle the BLOCK node inside the BIND_EXPR.  */
@@ -1258,15 +1224,19 @@ insert_block (block)
 
 void
 set_block (block)
-     register tree block;
+     tree block;
 {
   current_binding_level->this_block = block;
+  current_binding_level->names = chainon (current_binding_level->names,
+                                         BLOCK_VARS (block));
+  current_binding_level->blocks = chainon (current_binding_level->blocks,
+                                          BLOCK_SUBBLOCKS (block));
 }
 \f
 void
 push_label_level ()
 {
-  register struct binding_level *newlevel;
+  struct binding_level *newlevel;
 
   /* Reuse or create a struct for this binding level.  */
 
@@ -1294,7 +1264,7 @@ push_label_level ()
 void
 pop_label_level ()
 {
-  register struct binding_level *level = label_level_chain;
+  struct binding_level *level = label_level_chain;
   tree link, prev;
 
   /* Clear out the definitions of the declared labels in this level.
@@ -1356,7 +1326,7 @@ void
 pushtag (name, type)
      tree name, type;
 {
-  register struct binding_level *b;
+  struct binding_level *b;
 
   /* Find the proper binding level for this type tag.  */
 
@@ -1400,7 +1370,7 @@ pushtag (name, type)
 
 static int
 duplicate_decls (newdecl, olddecl, different_binding_level)
-     register tree newdecl, olddecl;
+     tree newdecl, olddecl;
      int different_binding_level;
 {
   int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
@@ -1411,8 +1381,43 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   int errmsg = 0;
 
   if (DECL_P (olddecl))
-    DECL_MACHINE_ATTRIBUTES (newdecl)
-      = merge_machine_decl_attributes (olddecl, newdecl);
+    {
+      if (TREE_CODE (newdecl) == FUNCTION_DECL
+         && TREE_CODE (olddecl) == FUNCTION_DECL
+         && (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
+       {
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             && DECL_UNINLINABLE (newdecl)
+             && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+           /* Already warned elsewhere.  */;
+         else if (DECL_DECLARED_INLINE_P (olddecl)
+                  && DECL_UNINLINABLE (olddecl)
+                  && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+           /* Already warned.  */;
+         else if (DECL_DECLARED_INLINE_P (newdecl)
+                  && ! DECL_DECLARED_INLINE_P (olddecl)
+                  && DECL_UNINLINABLE (olddecl)
+                  && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+           {
+             warning_with_decl (newdecl,
+                                "function `%s' redeclared as inline");
+             warning_with_decl (olddecl,
+                                "previous declaration of function `%s' with attribute noinline");
+           }
+         else if (DECL_DECLARED_INLINE_P (olddecl)
+                  && DECL_UNINLINABLE (newdecl)
+                  && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+           {
+             warning_with_decl (newdecl,
+                                "function `%s' redeclared with attribute noinline");
+             warning_with_decl (olddecl,
+                                "previous declaration of function `%s' was inline");
+           }
+       }
+
+      DECL_ATTRIBUTES (newdecl)
+       = (*targetm.merge_decl_attributes) (olddecl, newdecl);
+    }
 
   if (TREE_CODE (newtype) == ERROR_MARK
       || TREE_CODE (oldtype) == ERROR_MARK)
@@ -1505,6 +1510,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              tree trytype
                = build_function_type (newreturntype,
                                       TYPE_ARG_TYPES (oldtype));
+             trytype = build_type_attribute_variant (trytype,
+                                                     TYPE_ATTRIBUTES (oldtype));
 
               types_match = comptypes (newtype, trytype);
              if (types_match)
@@ -1526,6 +1533,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                                       tree_cons (NULL_TREE,
                                                  TREE_VALUE (TYPE_ARG_TYPES (newtype)),
                                                  TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
+             trytype = build_type_attribute_variant (trytype,
+                                                     TYPE_ATTRIBUTES (oldtype));
 
              types_match = comptypes (newtype, trytype);
              if (types_match)
@@ -1612,23 +1621,23 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
               && DECL_INITIAL (newdecl) == 0)))
        {
          /* Classify the problem further.  */
-         register tree t = TYPE_ARG_TYPES (oldtype);
+         tree t = TYPE_ARG_TYPES (oldtype);
          if (t == 0)
            t = TYPE_ARG_TYPES (newtype);
          for (; t; t = TREE_CHAIN (t))
            {
-             register tree type = TREE_VALUE (t);
+             tree type = TREE_VALUE (t);
 
              if (TREE_CHAIN (t) == 0
                  && TYPE_MAIN_VARIANT (type) != void_type_node)
                {
-                 error ("A parameter list with an ellipsis can't match an empty parameter name list declaration.");
+                 error ("a parameter list with an ellipsis can't match an empty parameter name list declaration");
                  break;
                }
 
              if (simple_type_promotes_to (type) != NULL_TREE)
                {
-                 error ("An argument type that has a default promotion can't match an empty parameter name list declaration.");
+                 error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
                  break;
                }
            }
@@ -1679,8 +1688,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
               && TYPE_ARG_TYPES (newtype) != 0
               && TYPE_ACTUAL_ARG_TYPES (oldtype) != 0)
        {
-         register tree type, parm;
-         register int nargs;
+         tree type, parm;
+         int nargs;
          /* Prototype decl follows defn w/o prototype.  */
 
          for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
@@ -1729,12 +1738,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          /* Warn if function is now inline
             but was previously declared not inline and has been called.  */
          if (TREE_CODE (olddecl) == FUNCTION_DECL
-             && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl)
+             && ! DECL_DECLARED_INLINE_P (olddecl)
+             && DECL_DECLARED_INLINE_P (newdecl)
              && TREE_USED (olddecl))
            warning_with_decl (newdecl,
                               "`%s' declared inline after being called");
          if (TREE_CODE (olddecl) == FUNCTION_DECL
-             && ! DECL_INLINE (olddecl) && DECL_INLINE (newdecl)
+             && ! DECL_DECLARED_INLINE_P (olddecl)
+             && DECL_DECLARED_INLINE_P (newdecl)
              && DECL_INITIAL (olddecl) != 0)
            warning_with_decl (newdecl,
                               "`%s' declared inline after its definition");
@@ -1842,7 +1853,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
        }
 
       /* Keep the old rtl since we can safely use it.  */
-      DECL_RTL (newdecl) = DECL_RTL (olddecl);
+      COPY_DECL_RTL (olddecl, newdecl);
 
       /* Merge the type qualifiers.  */
       if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1899,19 +1910,15 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
       /* Copy the assembler name.
         Currently, it can only be defined in the prototype.  */
-      DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
+      COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
 
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
        {
          DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
          DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
-
+         DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
-         DECL_NO_CHECK_MEMORY_USAGE (newdecl)
-           |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
-         DECL_NO_LIMIT_STACK (newdecl)
-           |= DECL_NO_LIMIT_STACK (olddecl);
        }
     }
   /* If cannot merge, then use the new type and qualifiers,
@@ -1962,12 +1969,29 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
-      /* If either decl says `inline', this fn is inline,
-        unless its definition was passed already.  */
-      if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
-       DECL_INLINE (olddecl) = 1;
+      /* If we're redefining a function previously defined as extern
+        inline, make sure we emit debug info for the inline before we
+        throw it away, in case it was inlined into a function that hasn't
+        been written out yet.  */
+      if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
+       {
+         (*debug_hooks->outlining_inline_function) (olddecl);
 
-      DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+         /* The new defn must not be inline.  */
+         DECL_INLINE (newdecl) = 0;
+         DECL_UNINLINABLE (newdecl) = 1;
+       }
+      else
+       {
+         /* If either decl says `inline', this fn is inline,
+            unless its definition was passed already.  */
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             || DECL_DECLARED_INLINE_P (olddecl))
+           DECL_DECLARED_INLINE_P (newdecl) = 1;
+
+         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+       }
 
       if (DECL_BUILT_IN (olddecl))
        {
@@ -1989,9 +2013,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
            }
        }
+
       /* Also preserve various other info from the definition.  */
-      else if (! new_is_definition)
-       DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
       if (! new_is_definition)
        {
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2001,9 +2024,28 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          if (! different_binding_level)
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
+         DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+         DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-         if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ABSTRACT_ORIGIN (olddecl);
+
+         /* Set DECL_INLINE on the declaration if we've got a body
+            from which to instantiate.  */
+         if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+           {
+             DECL_INLINE (newdecl) = 1;
+             DECL_ABSTRACT_ORIGIN (newdecl)
+               = (different_binding_level
+                  ? DECL_ORIGIN (olddecl)
+                  : DECL_ABSTRACT_ORIGIN (olddecl));
+           }
+       }
+      else
+       {
+         /* If a previous declaration said inline, mark the
+            definition as inlinable.  */
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             && ! DECL_UNINLINABLE (newdecl))
+           DECL_INLINE (newdecl) = 1;
        }
     }
   if (different_binding_level)
@@ -2012,7 +2054,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
      But preserve OLDDECL's DECL_UID.  */
   {
-    register unsigned olddecl_uid = DECL_UID (olddecl);
+    unsigned olddecl_uid = DECL_UID (olddecl);
 
     memcpy ((char *) olddecl + sizeof (struct tree_common),
            (char *) newdecl + sizeof (struct tree_common),
@@ -2022,11 +2064,71 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
   /* NEWDECL contains the merged attribute lists.
      Update OLDDECL to be the same.  */
-  DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+  DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
 
   return 1;
 }
 
+/* Check whether decl-node X shadows an existing declaration.
+   OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X,
+   which might be a NULL_TREE.  */
+static void
+warn_if_shadowing (x, oldlocal)
+     tree x, oldlocal;
+{
+  tree name;
+
+  if (DECL_EXTERNAL (x))
+    return;
+
+  name = DECL_NAME (x);
+
+  /* Warn if shadowing an argument at the top level of the body.  */
+  if (oldlocal != 0
+      /* This warning doesn't apply to the parms of a nested fcn.  */
+      && ! current_binding_level->parm_flag
+      /* Check that this is one level down from the parms.  */
+      && current_binding_level->level_chain->parm_flag
+      /* Check that the decl being shadowed
+        comes from the parm level, one level up.  */
+      && chain_member (oldlocal, current_binding_level->level_chain->names))
+    {
+      if (TREE_CODE (oldlocal) == PARM_DECL)
+       pedwarn ("declaration of `%s' shadows a parameter",
+                IDENTIFIER_POINTER (name));
+      else
+       pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
+                IDENTIFIER_POINTER (name));
+    }
+  /* Maybe warn if shadowing something else.  */
+  else if (warn_shadow
+          /* No shadow warnings for internally generated vars.  */
+          && DECL_SOURCE_LINE (x) != 0
+          /* No shadow warnings for vars made for inlining.  */
+          && ! DECL_FROM_INLINE (x))
+    {
+      if (TREE_CODE (x) == PARM_DECL
+         && current_binding_level->level_chain->parm_flag)
+       /* Don't warn about the parm names in function declarator
+          within a function declarator.
+          It would be nice to avoid warning in any function
+          declarator in a declaration, as opposed to a definition,
+          but there is no way to tell it's not a definition.  */
+       ;
+      else if (oldlocal)
+       {
+         if (TREE_CODE (oldlocal) == PARM_DECL)
+           shadow_warning ("a parameter", name, oldlocal);
+         else
+           shadow_warning ("a previous local", name, oldlocal);
+       }
+      else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
+              && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
+       shadow_warning ("a global declaration", name,
+                       IDENTIFIER_GLOBAL_VALUE (name));
+    }
+}
+
 /* Record a decl-node X as belonging to the current lexical scope.
    Check for errors (such as an incompatible declaration for the same
    name already seen in the same scope).
@@ -2039,9 +2141,14 @@ tree
 pushdecl (x)
      tree x;
 {
-  register tree t;
-  register tree name = DECL_NAME (x);
-  register struct binding_level *b = current_binding_level;
+  tree t;
+  tree name = DECL_NAME (x);
+  struct binding_level *b = current_binding_level;
+
+  /* Functions need the lang_decl data.  */
+  if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
+    DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
+      ggc_alloc_cleared (sizeof (struct lang_decl));
 
   DECL_CONTEXT (x) = current_function_decl;
   /* A local extern declaration for a function doesn't constitute nesting.
@@ -2051,25 +2158,26 @@ pushdecl (x)
       && DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
     DECL_CONTEXT (x) = 0;
 
-  if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
-      && x != IDENTIFIER_IMPLICIT_DECL (name)
-      /* Don't print error messages for __FUNCTION__ and __PRETTY_FUNCTION__ */
-      && !DECL_IN_SYSTEM_HEADER (x))
-    warning ("nested extern declaration of `%s'", IDENTIFIER_POINTER (name));
-
   if (name)
     {
-      const char *file;
-      int line;
       int different_binding_level = 0;
 
+      if (warn_nested_externs
+         && DECL_EXTERNAL (x)
+         && b != global_binding_level
+         && x != IDENTIFIER_IMPLICIT_DECL (name)
+         /* No error messages for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+         && !DECL_IN_SYSTEM_HEADER (x))
+       warning ("nested extern declaration of `%s'",
+                IDENTIFIER_POINTER (name));
+
       t = lookup_name_current_level (name);
       /* Don't type check externs here when -traditional.  This is so that
         code with conflicting declarations inside blocks will get warnings
         not errors.  X11 for instance depends on this.  */
       if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
        {
-         t = IDENTIFIER_GLOBAL_VALUE (name);
+         t = lookup_name (name);
          /* Type decls at global scope don't conflict with externs declared
             inside lexical blocks.  */
          if (t && TREE_CODE (t) == TYPE_DECL)
@@ -2083,12 +2191,6 @@ pushdecl (x)
          error_with_decl (x, "`%s' used prior to declaration");
        }
 
-      if (t != 0)
-       {
-         file = DECL_SOURCE_FILE (t);
-         line = DECL_SOURCE_LINE (t);
-       }
-
       /* If this decl is `static' and an implicit decl was seen previously,
         warn.  But don't complain if -traditional,
         since traditional compilers don't complain.  */
@@ -2338,7 +2440,8 @@ pushdecl (x)
              && oldglobal != 0
              && TREE_CODE (x) == FUNCTION_DECL
              && TREE_CODE (oldglobal) == FUNCTION_DECL
-             && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
+             && DECL_EXTERNAL (x)
+             && ! DECL_DECLARED_INLINE_P (x))
            {
              /* We have one.  Their types must agree.  */
              if (! comptypes (TREE_TYPE (x),
@@ -2348,13 +2451,15 @@ pushdecl (x)
                {
                  /* Inner extern decl is inline if global one is.
                     Copy enough to really inline it.  */
-                 if (DECL_INLINE (oldglobal))
+                 if (DECL_DECLARED_INLINE_P (oldglobal))
                    {
+                     DECL_DECLARED_INLINE_P (x)
+                       = DECL_DECLARED_INLINE_P (oldglobal);
                      DECL_INLINE (x) = DECL_INLINE (oldglobal);
                      DECL_INITIAL (x) = (current_function_decl == oldglobal
                                          ? 0 : DECL_INITIAL (oldglobal));
                      DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
-                     DECL_FRAME_SIZE (x) = DECL_FRAME_SIZE (oldglobal);
+                     DECL_NUM_STMTS (x) = DECL_NUM_STMTS (oldglobal);
                      DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
                      DECL_RESULT (x) = DECL_RESULT (oldglobal);
                      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
@@ -2408,49 +2513,7 @@ pushdecl (x)
                IDENTIFIER_LIMBO_VALUE (name) = x;
            }
 
-         /* Warn if shadowing an argument at the top level of the body.  */
-         if (oldlocal != 0 && !DECL_EXTERNAL (x)
-             /* This warning doesn't apply to the parms of a nested fcn.  */
-             && ! current_binding_level->parm_flag
-             /* Check that this is one level down from the parms.  */
-             && current_binding_level->level_chain->parm_flag
-             /* Check that the decl being shadowed
-                comes from the parm level, one level up.  */
-             && chain_member (oldlocal, current_binding_level->level_chain->names))
-           {
-             if (TREE_CODE (oldlocal) == PARM_DECL)
-               pedwarn ("declaration of `%s' shadows a parameter",
-                        IDENTIFIER_POINTER (name));
-             else
-               pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
-                        IDENTIFIER_POINTER (name));
-           }
-
-         /* Maybe warn if shadowing something else.  */
-         else if (warn_shadow && !DECL_EXTERNAL (x)
-                  /* No shadow warnings for internally generated vars.  */
-                  && DECL_SOURCE_LINE (x) != 0
-                  /* No shadow warnings for vars made for inlining.  */
-                  && ! DECL_FROM_INLINE (x))
-           {
-             const char *id = IDENTIFIER_POINTER (name);
-
-             if (TREE_CODE (x) == PARM_DECL
-                 && current_binding_level->level_chain->parm_flag)
-               /* Don't warn about the parm names in function declarator
-                  within a function declarator.
-                  It would be nice to avoid warning in any function
-                  declarator in a declaration, as opposed to a definition,
-                  but there is no way to tell it's not a definition.  */
-               ;
-             else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
-               warning ("declaration of `%s' shadows a parameter", id);
-             else if (oldlocal != 0)
-               warning ("declaration of `%s' shadows previous local", id);
-             else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
-                      && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-               warning ("declaration of `%s' shadows global declaration", id);
-           }
+         warn_if_shadowing (x, oldlocal);
 
          /* If storing a local value, there may already be one (inherited).
             If so, record it for restoration when this binding level ends.  */
@@ -2464,7 +2527,15 @@ pushdecl (x)
         incomplete type.  */
       if (TREE_TYPE (x) != error_mark_node
          && !COMPLETE_TYPE_P (TREE_TYPE (x)))
-       ++b->n_incomplete;
+       {
+         tree element = TREE_TYPE (x);
+
+         while (TREE_CODE (element) == ARRAY_TYPE)
+           element = TREE_TYPE (element);
+         if (TREE_CODE (element) == RECORD_TYPE
+             || TREE_CODE (element) == UNION_TYPE)
+           ++b->n_incomplete;
+       }
     }
 
   /* Put decls on list in reverse order.
@@ -2481,8 +2552,8 @@ tree
 pushdecl_top_level (x)
      tree x;
 {
-  register tree t;
-  register struct binding_level *b = current_binding_level;
+  tree t;
+  struct binding_level *b = current_binding_level;
 
   current_binding_level = global_binding_level;
   t = pushdecl (x);
@@ -2497,7 +2568,7 @@ tree
 implicitly_declare (functionid)
      tree functionid;
 {
-  register tree decl;
+  tree decl;
   int traditional_warning = 0;
   /* Only one "implicit declaration" warning per identifier.  */
   int implicit_warning;
@@ -2534,7 +2605,7 @@ implicitly_declare (functionid)
   /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
   maybe_objc_check_decl (decl);
 
-  rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
+  rest_of_decl_compilation (decl, NULL, 0, 0);
 
   if (implicit_warning)
     implicit_decl_warning (functionid);
@@ -2547,6 +2618,9 @@ implicitly_declare (functionid)
 
   gen_aux_info_record (decl, 0, 1, 0);
 
+  /* Possibly apply some default attributes to this implicit declaration.  */
+  decl_attributes (&decl, NULL_TREE, 0);
+
   return decl;
 }
 
@@ -2597,8 +2671,9 @@ redeclaration_error_message (newdecl, olddecl)
       if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
          /* However, defining once as extern inline and a second
             time in another way is ok.  */
-         && ! (DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
-              && ! (DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
+         && ! (DECL_DECLARED_INLINE_P (olddecl) && DECL_EXTERNAL (olddecl)
+              && ! (DECL_DECLARED_INLINE_P (newdecl)
+                    && DECL_EXTERNAL (newdecl))))
        return 1;
       return 0;
     }
@@ -2641,7 +2716,7 @@ tree
 lookup_label (id)
      tree id;
 {
-  register tree decl = IDENTIFIER_LABEL_VALUE (id);
+  tree decl = IDENTIFIER_LABEL_VALUE (id);
 
   if (current_function_decl == 0)
     {
@@ -2691,11 +2766,11 @@ tree
 shadow_label (name)
      tree name;
 {
-  register tree decl = IDENTIFIER_LABEL_VALUE (name);
+  tree decl = IDENTIFIER_LABEL_VALUE (name);
 
   if (decl != 0)
     {
-      register tree dup;
+      tree dup;
 
       /* Check to make sure that the label hasn't already been declared
         at this label scope */
@@ -2815,11 +2890,12 @@ lookup_tag (code, name, binding_level, thislevel_only)
      tree name;
      int thislevel_only;
 {
-  register struct binding_level *level;
+  struct binding_level *level;
+  int thislevel = 1;
 
   for (level = binding_level; level; level = level->level_chain)
     {
-      register tree tail;
+      tree tail;
       for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
        {
          if (TREE_PURPOSE (tail) == name)
@@ -2830,12 +2906,22 @@ lookup_tag (code, name, binding_level, thislevel_only)
                  pending_invalid_xref = name;
                  pending_invalid_xref_file = input_filename;
                  pending_invalid_xref_line = lineno;
+                 /* If in the same binding level as a declaration as a tag
+                    of a different type, this must not be allowed to
+                    shadow that tag, so give the error immediately.
+                    (For example, "struct foo; union foo;" is invalid.)  */
+                 if (thislevel)
+                   pending_xref_error ();
                }
              return TREE_VALUE (tail);
            }
        }
-      if (thislevel_only && ! level->tag_transparent)
-       return NULL_TREE;
+      if (! level->tag_transparent)
+       {
+         if (thislevel_only)
+           return NULL_TREE;
+         thislevel = 0;
+       }
     }
   return NULL_TREE;
 }
@@ -2863,11 +2949,11 @@ static tree
 lookup_tag_reverse (type)
      tree type;
 {
-  register struct binding_level *level;
+  struct binding_level *level;
 
   for (level = current_binding_level; level; level = level->level_chain)
     {
-      register tree tail;
+      tree tail;
       for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
        {
          if (TREE_VALUE (tail) == type)
@@ -2886,7 +2972,7 @@ tree
 lookup_name (name)
      tree name;
 {
-  register tree val;
+  tree val;
 
   if (current_binding_level != global_binding_level
       && IDENTIFIER_LOCAL_VALUE (name))
@@ -2902,7 +2988,7 @@ tree
 lookup_name_current_level (name)
      tree name;
 {
-  register tree t;
+  tree t;
 
   if (current_binding_level == global_binding_level)
     return IDENTIFIER_GLOBAL_VALUE (name);
@@ -2942,11 +3028,14 @@ mark_binding_level (arg)
    Make definitions for built-in primitive functions.  */
 
 void
-init_decl_processing ()
+c_init_decl_processing ()
 {
-  register tree endlink;
+  tree endlink;
   tree ptr_ftype_void, ptr_ftype_ptr;
 
+  /* Adds some ggc roots, and reserved words for c-parse.in.  */
+  c_parse_init ();
+
   current_function_decl = NULL;
   named_labels = NULL;
   current_binding_level = NULL_BINDING_LEVEL;
@@ -3032,51 +3121,10 @@ init_decl_processing ()
                            g77_ulongint_type_node));
     }
 
-  builtin_function ("__builtin_aggregate_incoming_address",
-                   build_function_type (ptr_type_node, NULL_TREE),
-                   BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
-                   BUILT_IN_NORMAL, NULL_PTR);
-
-  /* Hooks for the DWARF 2 __throw routine.  */
-  builtin_function ("__builtin_unwind_init",
-                   build_function_type (void_type_node, endlink),
-                   BUILT_IN_UNWIND_INIT, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
-                   BUILT_IN_DWARF_CFA, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function ("__builtin_dwarf_fp_regnum",
-                   build_function_type (unsigned_type_node, endlink),
-                   BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
-                   BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
-                   BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
-                   BUILT_IN_EXTRACT_RETURN_ADDR, BUILT_IN_NORMAL, NULL_PTR);
-  builtin_function
-    ("__builtin_eh_return",
-     build_function_type (void_type_node,
-                         tree_cons (NULL_TREE, ptr_type_node,
-                                    tree_cons (NULL_TREE,
-                                               type_for_mode (ptr_mode, 0),
-                                               tree_cons (NULL_TREE,
-                                                          ptr_type_node,
-                                                          endlink)))),
-     BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL_PTR);
-
   pedantic_lvalues = pedantic;
 
-  /* Create the global bindings for __FUNCTION__, __PRETTY_FUNCTION__,
-     and __func__.  */
-  function_id_node = get_identifier ("__FUNCTION__");
-  pretty_function_id_node = get_identifier ("__PRETTY_FUNCTION__");
-  func_id_node = get_identifier ("__func__");
   make_fname_decl = c_make_fname_decl;
-  declare_function_name ();
-
-  start_identifier_warnings ();
-
-  /* Prepare to check format strings against argument lists.  */
-  init_function_format_info ();
+  start_fname_decls ();
 
   incomplete_decl_finalize_hook = finish_incomplete_decl;
 
@@ -3104,30 +3152,33 @@ init_decl_processing ()
    are string merging candidates, which is wrong for C99's __func__.  FIXME.  */
 
 static tree
-c_make_fname_decl (id, name, type_dep)
+c_make_fname_decl (id, type_dep)
      tree id;
-     const char *name;
-     int type_dep ATTRIBUTE_UNUSED;
+     int type_dep;
 {
+  const char *name = fname_as_string (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 (build_int_2 (length, 0)));
+          build_index_type (size_int (length)));
 
   decl = build_decl (VAR_DECL, id, type);
+  /* We don't push the decl, so have to set its context here.  */
+  DECL_CONTEXT (decl) = current_function_decl;
+  
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
-  TREE_ASM_WRITTEN (decl) = 1;
-  DECL_SOURCE_LINE (decl) = 0;
   DECL_ARTIFICIAL (decl) = 1;
-  DECL_IN_SYSTEM_HEADER (decl) = 1;
-  DECL_IGNORED_P (decl) = 1;
+  
   init = build_string (length + 1, name);
   TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
-  finish_decl (pushdecl (decl), init, NULL_TREE);
+
+  TREE_USED (decl) = 1;
+  
+  finish_decl (decl, init, NULL_TREE);
 
   return decl;
 }
@@ -3157,8 +3208,8 @@ builtin_function (name, type, function_code, class, library_name)
   if (flag_traditional && name[0] != '_')
     DECL_BUILT_IN_NONANSI (decl) = 1;
   if (library_name)
-    DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
-  make_decl_rtl (decl, NULL_PTR);
+    SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
+  make_decl_rtl (decl, NULL);
   pushdecl (decl);
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = function_code;
@@ -3168,8 +3219,23 @@ builtin_function (name, type, function_code, class, library_name)
   if (name[0] != '_' || name[1] != '_')
     C_DECL_ANTICIPATED (decl) = 1;
 
+  /* Possibly apply some default attributes to this built-in function.  */
+  decl_attributes (&decl, NULL_TREE, 0);
+
   return decl;
 }
+
+/* Apply default attributes to a function, if a system function with default
+   attributes.  */
+
+void
+insert_default_attributes (decl)
+     tree decl;
+{
+  if (!TREE_PUBLIC (decl))
+    return;
+  c_common_insert_default_attributes (decl);
+}
 \f
 /* Called when a declaration is seen that contains no names to declare.
    If its type is a reference to a structure, union or enum inherited
@@ -3194,7 +3260,7 @@ shadow_tag_warned (declspecs, warned)
        no pedwarn.  */
 {
   int found_tag = 0;
-  register tree link;
+  tree link;
   tree specs, attrs;
 
   pending_invalid_xref = 0;
@@ -3205,15 +3271,15 @@ shadow_tag_warned (declspecs, warned)
 
   for (link = specs; link; link = TREE_CHAIN (link))
     {
-      register tree value = TREE_VALUE (link);
-      register enum tree_code code = TREE_CODE (value);
+      tree value = TREE_VALUE (link);
+      enum tree_code code = TREE_CODE (value);
 
       if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
        /* Used to test also that TYPE_SIZE (value) != 0.
           That caused warning for `struct foo;' at top level in the file.  */
        {
-         register tree name = lookup_tag_reverse (value);
-         register tree t;
+         tree name = lookup_tag_reverse (value);
+         tree t;
 
          found_tag++;
 
@@ -3257,17 +3323,79 @@ shadow_tag_warned (declspecs, warned)
     }
 }
 \f
+/* 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
+   non-zero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
+   is non-zero is the array is [*], a VLA of unspecified length which is
+   nevertheless a complete type (not currently implemented by GCC),
+   zero 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_type) and operand 1
+   is the expression inside; whose TREE_TYPE is the type qualifiers and
+   which has TREE_STATIC set if "static" is used.  */
+
+tree
+build_array_declarator (expr, quals, static_p, vla_unspec_p)
+     tree expr;
+     tree quals;
+     int static_p;
+     int vla_unspec_p;
+{
+  tree decl;
+  decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+  TREE_TYPE (decl) = quals;
+  TREE_STATIC (decl) = (static_p ? 1 : 0);
+  if (pedantic && !flag_isoc99)
+    {
+      if (static_p || quals != NULL_TREE)
+       pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+      if (vla_unspec_p)
+       pedwarn ("ISO C89 does not support `[*]' array declarators");
+    }
+  if (vla_unspec_p)
+    warning ("GCC does not yet properly implement `[*]' array declarators");
+  return decl;
+}
+
+/* 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 non-zero if it is an
+   abstract declarator, zero otherwise; this is used to reject static and
+   type qualifiers in abstract declarators, where they are not in the
+   C99 grammar.  */
+
+tree
+set_array_declarator_type (decl, type, abstract_p)
+     tree decl;
+     tree type;
+     int abstract_p;
+{
+  TREE_OPERAND (decl, 0) = type;
+  if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+    error ("static or type qualifiers in abstract declarator");
+  return decl;
+}
+\f
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
 groktypename (typename)
      tree typename;
 {
+  tree specs, attrs;
+
   if (TREE_CODE (typename) != TREE_LIST)
     return typename;
-  return grokdeclarator (TREE_VALUE (typename),
-                        TREE_PURPOSE (typename),
-                        TYPENAME, 0);
+
+  split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+
+  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
+
+  /* Apply attributes.  */
+  decl_attributes (&typename, attrs, 0);
+
+  return typename;
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
@@ -3299,14 +3427,23 @@ groktypename_in_parm_context (typename)
    grokfield and not through here.  */
 
 tree
-start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
+start_decl (declarator, declspecs, initialized, attributes)
      tree declarator, declspecs;
      int initialized;
-     tree attributes, prefix_attributes;
+     tree attributes;
 {
-  register tree decl = grokdeclarator (declarator, declspecs,
-                                      NORMAL, initialized);
-  register tree tem;
+  tree decl;
+  tree tem;
+  
+  /* An object declared as __attribute__((deprecated)) suppresses
+     warnings of uses of other deprecated items.  */
+  if (lookup_attribute ("deprecated", attributes))
+    deprecated_state = DEPRECATED_SUPPRESS;
+
+  decl = grokdeclarator (declarator, declspecs,
+                        NORMAL, initialized);
+  
+  deprecated_state = DEPRECATED_NORMAL;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
       && MAIN_NAME_P (DECL_NAME (decl)))
@@ -3410,12 +3547,15 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   if (! flag_no_common || ! TREE_PUBLIC (decl))
     DECL_COMMON (decl) = 1;
 
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
-  SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
-#endif
-
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
-  decl_attributes (decl, attributes, prefix_attributes);
+  decl_attributes (&decl, attributes, 0);
+
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_DECLARED_INLINE_P (decl)
+      && DECL_UNINLINABLE (decl)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
+    warning_with_decl (decl,
+                      "inline function `%s' given attribute noinline");
 
   /* Add this decl to the current binding level.
      TEM may equal DECL or it may be a previous decl of the same name.  */
@@ -3426,7 +3566,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       /* But not if this is a duplicate decl
         and we preserved the rtl from the previous one
         (which may or may not happen).  */
-      && DECL_RTL (tem) == 0
+      && !DECL_RTL_SET_P (tem)
       && !DECL_CONTEXT (tem))
     {
       if (TREE_TYPE (tem) != error_mark_node
@@ -3450,18 +3590,18 @@ finish_decl (decl, init, asmspec_tree)
      tree decl, init;
      tree asmspec_tree;
 {
-  register tree type = TREE_TYPE (decl);
+  tree type = TREE_TYPE (decl);
   int was_incomplete = (DECL_SIZE (decl) == 0);
   const char *asmspec = 0;
 
-  /* If a name was specified, get the string.   */
+  /* If a name was specified, get the string.  */
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
-
   if (init != 0 && DECL_INITIAL (decl) == 0)
     init = 0;
+  
   /* Don't crash if parm is initialized.  */
   if (TREE_CODE (decl) == PARM_DECL)
     init = 0;
@@ -3479,7 +3619,6 @@ finish_decl (decl, init, asmspec_tree)
     }
 
   /* Deduce size of array from initialization, if not already known */
-
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == 0
       && TREE_CODE (decl) != TYPE_DECL)
@@ -3569,8 +3708,8 @@ finish_decl (decl, init, asmspec_tree)
   if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
     {
       DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
-      DECL_RTL (decl) = 0;
-      DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
+      SET_DECL_RTL (decl, NULL_RTX);
+      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
     }
 
   /* Output the assembler code and/or RTL code for variables and functions,
@@ -3583,17 +3722,45 @@ finish_decl (decl, init, asmspec_tree)
       maybe_objc_check_decl (decl);
 
       if (!DECL_CONTEXT (decl))
-       rest_of_decl_compilation (decl, asmspec,
-                                 (DECL_CONTEXT (decl) == 0
-                                  || TREE_ASM_WRITTEN (decl)), 0);
+       {
+         if (DECL_INITIAL (decl) == NULL_TREE
+             || DECL_INITIAL (decl) == error_mark_node)
+           /* Don't output anything
+              when a tentative file-scope definition is seen.
+              But at end of compilation, do output code for them.  */
+           DECL_DEFER_OUTPUT (decl) = 1;
+         rest_of_decl_compilation (decl, asmspec,
+                                   (DECL_CONTEXT (decl) == 0
+                                    || TREE_ASM_WRITTEN (decl)), 0);
+       }
       else
        {
+         /* This is a local variable.  If there is an ASMSPEC, the
+            user has requested that we handle it specially.  */
          if (asmspec)
            {
-             DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-             DECL_C_HARD_REGISTER (decl) = 1;
+             /* In conjunction with an ASMSPEC, the `register'
+                keyword indicates that we should place the variable
+                in a particular register.  */
+             if (DECL_REGISTER (decl))
+               DECL_C_HARD_REGISTER (decl) = 1;
+
+             /* If this is not a static variable, issue a warning.
+                It doesn't make any sense to give an ASMSPEC for an
+                ordinary, non-register local variable.  Historically,
+                GCC has accepted -- but ignored -- the ASMSPEC in
+                this case.  */
+             if (TREE_CODE (decl) == VAR_DECL 
+                 && !DECL_REGISTER (decl)
+                 && !TREE_STATIC (decl))
+               warning_with_decl (decl,
+                                  "ignoring asm-specifier for non-static local variable `%s'");
+             else
+               SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
            }
-         add_decl_stmt (decl);
+
+         if (TREE_CODE (decl) != FUNCTION_DECL)
+           add_decl_stmt (decl);
        }
 
       if (DECL_CONTEXT (decl) != 0)
@@ -3616,7 +3783,7 @@ finish_decl (decl, init, asmspec_tree)
     {
       /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
       maybe_objc_check_decl (decl);
-      rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0, 0);
+      rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
     }
 
   /* At the end of a declaration, throw away any variable type sizes
@@ -3653,8 +3820,7 @@ push_parm_decl (parm)
 
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
                         TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
-  decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
-                  TREE_PURPOSE (TREE_VALUE (parm)));
+  decl_attributes (&decl, TREE_VALUE (parm), 0);
 
 #if 0
   if (DECL_NAME (decl))
@@ -3663,7 +3829,7 @@ push_parm_decl (parm)
       olddecl = lookup_name (DECL_NAME (decl));
       if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
        pedwarn_with_decl (decl,
-                          "ANSI C forbids parameter `%s' shadowing typedef");
+                          "ISO C forbids parameter `%s' shadowing typedef");
     }
 #endif
 
@@ -3688,6 +3854,61 @@ clear_parm_order ()
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+/* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
+   literal, which may be an incomplete array type completed by the
+   initializer; INIT is a CONSTRUCTOR that initializes the compound
+   literal.  */
+
+tree
+build_compound_literal (type, init)
+     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_STMT.  */
+  tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+  tree complit;
+  tree stmt;
+  DECL_EXTERNAL (decl) = 0;
+  TREE_PUBLIC (decl) = 0;
+  TREE_STATIC (decl) = (current_binding_level == global_binding_level);
+  DECL_CONTEXT (decl) = current_function_decl;
+  TREE_USED (decl) = 1;
+  TREE_TYPE (decl) = type;
+  store_init_value (decl, init);
+
+  if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+    {
+      int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
+      if (failure)
+       abort ();
+    }
+
+  type = TREE_TYPE (decl);
+  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+    return error_mark_node;
+
+  stmt = build_stmt (DECL_STMT, decl);
+  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+  TREE_SIDE_EFFECTS (complit) = 1;
+
+  layout_decl (decl, 0);
+
+  if (TREE_STATIC (decl))
+    {
+      /* This decl needs a name for the assembler output.  We also need
+        a unique suffix to be added to the name, for which DECL_CONTEXT
+        must be set.  */
+      DECL_NAME (decl) = get_identifier ("__compound_literal");
+      DECL_CONTEXT (decl) = complit;
+      rest_of_decl_compilation (decl, NULL, 1, 0);
+      DECL_CONTEXT (decl) = NULL_TREE;
+    }
+
+  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).  */
@@ -3698,7 +3919,7 @@ complete_array_type (type, initial_value, do_default)
      tree initial_value;
      int do_default;
 {
-  register tree maxindex = NULL_TREE;
+  tree maxindex = NULL_TREE;
   int value = 0;
 
   if (initial_value)
@@ -3813,7 +4034,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   enum tree_code innermost_code = ERROR_MARK;
   int bitfield = 0;
   int size_varies = 0;
-  tree decl_machine_attr = NULL_TREE;
+  tree decl_attr = NULL_TREE;
+  tree array_ptr_quals = NULL_TREE;
+  int array_parm_static = 0;
+  tree returned_attrs = NULL_TREE;
 
   if (decl_context == BITFIELD)
     bitfield = 1, decl_context = FIELD;
@@ -3824,7 +4048,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   {
-    register tree decl = declarator;
+    tree decl = declarator;
     name = 0;
 
     while (decl)
@@ -3837,6 +4061,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          decl = TREE_OPERAND (decl, 0);
          break;
 
+       case TREE_LIST:
+         decl = TREE_VALUE (decl);
+         break;
+
        case IDENTIFIER_NODE:
          name = IDENTIFIER_POINTER (decl);
          decl = 0;
@@ -3882,7 +4110,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
     {
-      register tree id = TREE_VALUE (spec);
+      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;
@@ -3892,9 +4128,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
        {
          enum rid i = C_RID_CODE (id);
-         if (i <= RID_LAST_MODIFIER)
+         if ((int) i <= (int) RID_LAST_MODIFIER)
            {
-             if (i == RID_LONG && specbits & (1<<i))
+             if (i == RID_LONG && (specbits & (1 << (int) i)))
                {
                  if (longlong)
                    error ("`long long long' is too long for GCC");
@@ -3906,9 +4142,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                      longlong = 1;
                    }
                }
-             else if (specbits & (1 << i))
+             else if (specbits & (1 << (int) i))
                pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
-             specbits |= 1 << i;
+             specbits |= 1 << (int) i;
              goto found;
            }
        }
@@ -3918,13 +4154,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (TREE_CODE (id) == TYPE_DECL)
        {
          type = TREE_TYPE (id);
-         decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+         decl_attr = DECL_ATTRIBUTES (id);
          typedef_decl = id;
        }
       /* Built-in types come as identifiers.  */
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
        {
-         register tree t = lookup_name (id);
+         tree t = lookup_name (id);
          if (TREE_TYPE (t) == error_mark_node)
            ;
          else if (!t || TREE_CODE (t) != TYPE_DECL)
@@ -3963,7 +4199,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          /* 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) && funcdef_flag)
+         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'",
@@ -4230,6 +4467,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* 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
         where the name was omitted).
@@ -4241,13 +4479,49 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
         array or function or pointer, and DECLARATOR has had its
         outermost layer removed.  */
 
-      if (TREE_CODE (declarator) == ARRAY_REF)
+      if (array_ptr_quals != 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_parm_static = 0;
+       }
+
+      if (TREE_CODE (declarator) == TREE_LIST)
+       {
+         /* 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;
+         if (TREE_CODE (inner_decl) == CALL_EXPR)
+           attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+         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)
        {
-         register tree itype = NULL_TREE;
-         register tree size = TREE_OPERAND (declarator, 1);
+         tree itype = NULL_TREE;
+         tree size = TREE_OPERAND (declarator, 1);
          /* The index is a signed object `sizetype' bits wide.  */
          tree index_type = 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.  */
@@ -4279,8 +4553,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
              STRIP_TYPE_NOPS (size);
 
-             if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
-                 && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+             if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
                {
                  error ("size of array `%s' has non-integer type", name);
                  size = integer_one_node;
@@ -4374,7 +4647,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             Functions aren't allowed as array elements.  */
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
              && (constp || volatilep))
-           pedwarn ("ANSI C forbids const or volatile function types");
+           pedwarn ("ISO C forbids const or volatile function types");
 #endif
 
          /* Build the array type itself, then merge any constancy or
@@ -4397,6 +4670,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              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)
        {
@@ -4471,7 +4751,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             the FUNCTION_TYPE node itself.  */
 
          {
-           register tree link;
+           tree link;
 
            for (link = last_function_parm_tags;
                 link;
@@ -4499,7 +4779,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
          if (TREE_TYPE (declarator))
            {
-             register tree typemodlist;
+             tree typemodlist;
              int erred = 0;
 
              constp = 0;
@@ -4555,7 +4835,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       && TREE_OVERFLOW (TYPE_SIZE (type)))
     {
       error ("size of array `%s' is too large", name);
-      /* If we proceed with the array type as it is, we'll eventully
+      /* If we proceed with the array type as it is, we'll eventually
         crash in tree_low_cst().  */
       type = error_mark_node;
     }
@@ -4576,6 +4856,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       if ((specbits & (1 << (int) RID_SIGNED))
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
+      decl_attributes (&decl, returned_attrs, 0);
       return decl;
     }
 
@@ -4606,6 +4887,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        pedwarn ("ISO C forbids const or volatile function types");
       if (type_quals)
        type = c_build_qualified_type (type, type_quals);
+      decl_attributes (&type, returned_attrs, 0);
       return type;
     }
 
@@ -4630,11 +4912,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
      or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE.  */
 
   {
-    register tree decl;
+    tree decl;
 
     if (decl_context == PARM)
       {
-       tree type_as_written = type;
+       tree type_as_written;
        tree promoted_type;
 
        /* A parameter declared as an array of T is really a pointer to T.
@@ -4648,6 +4930,44 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              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);
+
+                   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");
+
+               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)
@@ -4659,6 +4979,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = build_pointer_type (type);
            type_quals = TYPE_UNQUALIFIED;
          }
+       else if (type_quals)
+         type = c_build_qualified_type (type, type_quals);
+         
+       type_as_written = type;
 
        decl = build_decl (PARM_DECL, declarator, type);
        if (size_varies)
@@ -4737,7 +5061,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn ("invalid storage class for function `%s'", name);
 
        decl = build_decl (FUNCTION_DECL, declarator, type);
-       decl = build_decl_attribute_variant (decl, decl_machine_attr);
+       decl = build_decl_attribute_variant (decl, decl_attr);
+
+       DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
+         ggc_alloc_cleared (sizeof (struct lang_decl));
 
        if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ISO C forbids qualified function types");
@@ -4755,16 +5082,34 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
 
        /* Record presence of `inline', if it is reasonable.  */
-       if (inlinep)
+       if (MAIN_NAME_P (declarator))
          {
-           if (MAIN_NAME_P (declarator))
+           if (inlinep)
              warning ("cannot inline function `main'");
-           else
-             /* Assume that otherwise the function can be inlined.  */
-             DECL_INLINE (decl) = 1;
-
-           if (specbits & (1 << (int) RID_EXTERN))
-             current_extern_inline = 1;
+         }
+       else if (inlinep)
+         {
+           /* Assume that otherwise the function can be inlined.  */
+           DECL_DECLARED_INLINE_P (decl) = 1;
+
+           /* Do not mark bare declarations as DECL_INLINE.  Doing so
+              in the presence of multiple declarations can result in
+              the abstract origin pointing between the declarations,
+              which will confuse dwarf2out.  */
+           if (initialized)
+             {
+               DECL_INLINE (decl) = 1;
+               if (specbits & (1 << (int) RID_EXTERN))
+                 current_extern_inline = 1;
+             }
+         }
+       /* If -finline-functions, assume it can be inlined.  This does
+          two things: let the function be deferred until it is actually
+          needed, and let dwarf2 know that the function is inlinable.  */
+       else if (flag_inline_trees == 2 && initialized)
+         {
+           DECL_INLINE (decl) = 1;
+           DECL_DECLARED_INLINE_P (decl) = 0;
          }
       }
     else
@@ -4785,7 +5130,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type_quals = TYPE_UNQUALIFIED;
 #endif
          }
-
+       else if (type_quals)
+         type = c_build_qualified_type (type, type_quals);
+         
        decl = build_decl (VAR_DECL, declarator, type);
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -4828,6 +5175,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
       mark_addressable (decl);
 
+    decl_attributes (&decl, returned_attrs, 0);
+
     return decl;
   }
 }
@@ -4951,8 +5300,8 @@ tree
 get_parm_info (void_at_end)
      int void_at_end;
 {
-  register tree decl, t;
-  register tree types = 0;
+  tree decl, t;
+  tree types = 0;
   int erred = 0;
   tree tags = gettags ();
   tree parms = getdecls ();
@@ -5025,8 +5374,7 @@ get_parm_info (void_at_end)
        tree type = TREE_TYPE (decl);
        DECL_ARG_TYPE (decl) = type;
        if (PROMOTE_PROTOTYPES
-           && (TREE_CODE (type) == INTEGER_TYPE
-               || TREE_CODE (type) == ENUMERAL_TYPE)
+           && INTEGRAL_TYPE_P (type)
            && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
          DECL_ARG_TYPE (decl) = integer_type_node;
 
@@ -5063,14 +5411,20 @@ parmlist_tags_warning ()
       if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
        continue;
       if (TREE_PURPOSE (elt) != 0)
-       warning ("`%s %s' declared inside parameter list",
-                (code == RECORD_TYPE ? "struct"
-                 : code == UNION_TYPE ? "union"
-                 : "enum"),
-                IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+        {
+          if (code == RECORD_TYPE)
+            warning ("`struct %s' declared inside parameter list",
+                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+          else if (code == UNION_TYPE)
+            warning ("`union %s' declared inside parameter list",
+                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+          else
+            warning ("`enum %s' declared inside parameter list",
+                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
+        }
       else
        {
-         /* For translation these need to be seperate warnings */
+         /* For translation these need to be separate warnings */
          if (code == RECORD_TYPE)
            warning ("anonymous struct declared inside parameter list");
          else if (code == UNION_TYPE)
@@ -5080,7 +5434,7 @@ parmlist_tags_warning ()
        }
       if (! already)
        {
-         warning ("its scope is only this definition or declaration, which is probably not what you want.");
+         warning ("its scope is only this definition or declaration, which is probably not what you want");
          already = 1;
        }
     }
@@ -5097,12 +5451,19 @@ xref_tag (code, name)
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
-  register tree ref = lookup_tag (code, name, current_binding_level, 0);
-  /* Even if this is the wrong type of tag, return what we found.
-     There will be an error message anyway, from pending_xref_error.
-     If we create an empty xref just for an invalid use of the type,
-     the main result is to create lots of superfluous error messages.  */
-  if (ref)
+  tree ref = lookup_tag (code, name, current_binding_level, 0);
+  /* If this is the right type of tag, return what we found.
+     (This reference will be shadowed by shadow_tag later if appropriate.)
+     If this is the wrong type of tag, do not return it.  If it was the
+     wrong type in the same binding level, we will have had an error
+     message already; if in a different binding level and declaring
+     a name, pending_xref_error will give an error message; but if in a
+     different binding level and not declaring a name, this tag should
+     shadow the previous declaration of a different type of tag, and
+     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.)  */
+  if (ref && TREE_CODE (ref) == code)
     return ref;
 
   /* If no such tag is yet defined, create a forward-reference node
@@ -5113,9 +5474,6 @@ xref_tag (code, name)
   ref = make_node (code);
   if (code == ENUMERAL_TYPE)
     {
-      /* (In ANSI, Enums can be referred to only if already defined.)  */
-      if (pedantic)
-       pedwarn ("ISO C forbids forward references to `enum' types");
       /* Give the type a default layout like unsigned int
         to avoid crashing if it does not get defined.  */
       TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
@@ -5144,7 +5502,7 @@ start_struct (code, name)
   /* If there is already a tag defined at this binding level
      (as a forward reference), just return it.  */
 
-  register tree ref = 0;
+  tree ref = 0;
 
   if (name != 0)
     ref = lookup_tag (code, name, current_binding_level, 1);
@@ -5153,9 +5511,14 @@ start_struct (code, name)
       C_TYPE_BEING_DEFINED (ref) = 1;
       TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
-       error ("redefinition of `%s %s'",
-              code == UNION_TYPE ? "union" : "struct",
-              IDENTIFIER_POINTER (name));
+        {
+         if (code == UNION_TYPE)
+           error ("redefinition of `union %s'",
+                  IDENTIFIER_POINTER (name));
+          else
+           error ("redefinition of `struct %s'",
+                  IDENTIFIER_POINTER (name));
+       }  
 
       return ref;
     }
@@ -5185,6 +5548,18 @@ grokfield (filename, line, declarator, declspecs, width)
 {
   tree value;
 
+  if (declarator == NULL_TREE && width == NULL_TREE)
+    {
+      /* This is an unnamed decl.  We only support unnamed
+        structs/unions, so check for other things and refuse them.  */
+      if (TREE_CODE (TREE_VALUE (declspecs)) != RECORD_TYPE
+         && TREE_CODE (TREE_VALUE (declspecs)) != UNION_TYPE)
+       {
+         error ("unnamed fields of type other than struct or union are not allowed");
+         return NULL_TREE;
+       }
+    }
+
   value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
@@ -5204,7 +5579,7 @@ finish_struct (t, fieldlist, attributes)
      tree fieldlist;
      tree attributes;
 {
-  register tree x;
+  tree x;
   int toplevel = global_binding_level == current_binding_level;
   int saw_named_field;
 
@@ -5213,7 +5588,7 @@ finish_struct (t, fieldlist, attributes)
 
   TYPE_SIZE (t) = 0;
 
-  decl_attributes (t, attributes, NULL_TREE);
+  decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
   /* Nameless union parm types are useful as GCC extension.  */
   if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
@@ -5318,11 +5693,10 @@ finish_struct (t, fieldlist, attributes)
         field widths.  */
       if (DECL_INITIAL (x))
        {
-         int max_width;
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node)
-           max_width = CHAR_TYPE_SIZE;
-         else
-           max_width = TYPE_PRECISION (TREE_TYPE (x));
+         int max_width
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
+              ? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
+
          if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
            error_with_decl (x, "negative width in bit-field `%s'");
          else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
@@ -5333,7 +5707,7 @@ finish_struct (t, fieldlist, attributes)
            {
              /* The test above has assured us that TREE_INT_CST_HIGH is 0.  */
              unsigned HOST_WIDE_INT width
-               = TREE_INT_CST_LOW (DECL_INITIAL (x));
+               = tree_low_cst (DECL_INITIAL (x), 1);
 
              if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
                  && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
@@ -5404,7 +5778,7 @@ finish_struct (t, fieldlist, attributes)
       x = TREE_CHAIN (x);
     else
       {
-       register tree y = fieldlist;
+       tree y = fieldlist;
 
        while (1)
          {
@@ -5477,10 +5851,11 @@ finish_struct (t, fieldlist, attributes)
              layout_decl (decl, 0);
              /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
              maybe_objc_check_decl (decl);
-             rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
+             rest_of_decl_compilation (decl, NULL, toplevel, 0);
              if (! toplevel)
                expand_decl (decl);
-             --current_binding_level->n_incomplete;
+             if (--current_binding_level->n_incomplete == 0)
+               break;
            }
          else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
                   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
@@ -5489,7 +5864,19 @@ finish_struct (t, fieldlist, attributes)
              while (TREE_CODE (element) == ARRAY_TYPE)
                element = TREE_TYPE (element);
              if (element == t)
-               layout_array_type (TREE_TYPE (decl));
+               {
+                 layout_array_type (TREE_TYPE (decl));
+                 if (TREE_CODE (decl) != TYPE_DECL)
+                   {
+                     layout_decl (decl, 0);
+                     maybe_objc_check_decl (decl);
+                     rest_of_decl_compilation (decl, NULL, toplevel, 0);
+                     if (! toplevel)
+                       expand_decl (decl);
+                   }
+                 if (--current_binding_level->n_incomplete == 0)
+                   break;
+               }
            }
        }
     }
@@ -5521,7 +5908,7 @@ tree
 start_enum (name)
      tree name;
 {
-  register tree enumtype = 0;
+  tree enumtype = 0;
 
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
@@ -5569,7 +5956,7 @@ finish_enum (enumtype, values, attributes)
      tree values;
      tree attributes;
 {
-  register tree pair, tem;
+  tree pair, tem;
   tree minnode = 0, maxnode = 0, enum_value_type;
   int precision, unsign;
   int toplevel = (global_binding_level == current_binding_level);
@@ -5577,7 +5964,7 @@ finish_enum (enumtype, values, attributes)
   if (in_parm_level_p ())
     warning ("enum defined inside parms");
 
-  decl_attributes (enumtype, attributes, NULL_TREE);
+  decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
   /* Calculate the maximum value of any enumerator in this type.  */
 
@@ -5603,13 +5990,19 @@ finish_enum (enumtype, values, attributes)
   unsign = (tree_int_cst_sgn (minnode) >= 0);
   precision = MAX (min_precision (minnode, unsign),
                   min_precision (maxnode, unsign));
-  if (!TYPE_PACKED (enumtype))
-    precision = MAX (precision, TYPE_PRECISION (integer_type_node));
-  if (type_for_size (precision, unsign) == 0)
+  if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
     {
-      warning ("enumeration values exceed range of largest integer");
-      precision = TYPE_PRECISION (long_long_integer_type_node);
+      tree narrowest = type_for_size (precision, unsign);
+      if (narrowest == 0)
+       {
+         warning ("enumeration values exceed range of largest integer");
+         narrowest = long_long_integer_type_node;
+       }
+
+      precision = TYPE_PRECISION (narrowest);
     }
+  else
+    precision = TYPE_PRECISION (integer_type_node);
 
   if (precision == TYPE_PRECISION (integer_type_node))
     enum_value_type = type_for_size (precision, 0);
@@ -5694,7 +6087,7 @@ tree
 build_enumerator (name, value)
      tree name, value;
 {
-  register tree decl, type;
+  tree decl, type;
 
   /* Validate and default VALUE.  */
 
@@ -5755,7 +6148,7 @@ build_enumerator (name, value)
 
 \f
 /* Create the FUNCTION_DECL for a function definition.
-   DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
+   DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
    the declaration; they describe the function's name and the type it returns,
    but twisted together in a fashion that parallels the syntax of C.
 
@@ -5767,8 +6160,8 @@ build_enumerator (name, value)
    yyparse to report a parse error.  */
 
 int
-start_function (declspecs, declarator, prefix_attributes, attributes)
-     tree declarator, declspecs, prefix_attributes, attributes;
+start_function (declspecs, declarator, attributes)
+     tree declarator, declspecs, attributes;
 {
   tree decl1, old_decl;
   tree restype;
@@ -5795,7 +6188,13 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
       return 0;
     }
 
-  decl_attributes (decl1, prefix_attributes, attributes);
+  decl_attributes (&decl1, attributes, 0);
+
+  if (DECL_DECLARED_INLINE_P (decl1)
+      && DECL_UNINLINABLE (decl1)
+      && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
+    warning_with_decl (decl1,
+                      "inline function `%s' given attribute noinline");
 
   announce_function (decl1);
 
@@ -5884,10 +6283,6 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
      except for defining how to inline.  So set DECL_EXTERNAL in that case.  */
   DECL_EXTERNAL (decl1) = current_extern_inline;
 
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
-  SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
-#endif
-
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
@@ -5967,7 +6362,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
 
   restype = TREE_TYPE (TREE_TYPE (current_function_decl));
   /* Promote the value to int before returning it.  */
-  if (C_PROMOTING_INTEGER_TYPE_P (restype))
+  if (c_promoting_integer_type_p (restype))
     {
       /* It retains unsignedness if traditional
         or if not really getting wider.  */
@@ -5989,6 +6384,8 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
 
   immediate_size_expand = old_immediate_size_expand;
 
+  start_fname_decls ();
+  
   return 1;
 }
 
@@ -6012,8 +6409,8 @@ c_mark_varargs ()
 void
 store_parm_decls ()
 {
-  register tree fndecl = current_function_decl;
-  register tree parm;
+  tree fndecl = current_function_decl;
+  tree parm;
 
   /* This is either a chain of PARM_DECLs (if a prototype was used)
      or a list of IDENTIFIER_NODEs (for an old-fashioned C definition).  */
@@ -6023,16 +6420,24 @@ store_parm_decls ()
   tree parmtags = current_function_parm_tags;
 
   /* This is a chain of PARM_DECLs from old-style parm declarations.  */
-  register tree parmdecls = getdecls ();
+  tree parmdecls = getdecls ();
 
   /* This is a chain of any other decls that came in among the parm
      declarations.  If a parm is declared with  enum {foo, bar} x;
      then CONST_DECLs for foo and bar are put here.  */
   tree nonparms = 0;
 
+  /* The function containing FNDECL, if any.  */
+  tree context = decl_function_context (fndecl);
+
   /* Nonzero if this definition is written with a prototype.  */
   int prototype = 0;
 
+  int saved_warn_shadow = warn_shadow;
+
+  /* Don't re-emit shadow warnings.  */
+  warn_shadow = 0;
+
   if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
     {
       /* This case is when the function was defined with an ANSI prototype.
@@ -6040,7 +6445,7 @@ store_parm_decls ()
         except record them as in effect
         and complain if any redundant old-style parm decls were written.  */
 
-      register tree next;
+      tree next;
       tree others = 0;
 
       prototype = 1;
@@ -6146,7 +6551,7 @@ store_parm_decls ()
 
       for (parm = specparms; parm; parm = TREE_CHAIN (parm))
        {
-         register tree tail, found = NULL;
+         tree tail, found = NULL;
 
          if (TREE_VALUE (parm) == 0)
            {
@@ -6167,7 +6572,7 @@ store_parm_decls ()
              }
 
          /* If declaration already marked, we have a duplicate name.
-            Complain, and don't use this decl twice.   */
+            Complain, and don't use this decl twice.  */
          if (found && DECL_WEAK (found))
            {
              error_with_decl (found, "multiple parameters named `%s'");
@@ -6258,7 +6663,7 @@ store_parm_decls ()
       parm = specparms;
       DECL_ARGUMENTS (fndecl) = 0;
       {
-       register tree last;
+       tree last;
        for (last = 0; parm; parm = TREE_CHAIN (parm))
          if (TREE_PURPOSE (parm))
            {
@@ -6277,7 +6682,7 @@ store_parm_decls ()
 
       if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
        {
-         register tree type;
+         tree type;
          for (parm = DECL_ARGUMENTS (fndecl),
               type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
               parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
@@ -6293,9 +6698,11 @@ store_parm_decls ()
                                            "prototype declaration");
                  break;
                }
-             /* Type for passing arg must be consistent
-                with that declared for the arg.  */
-             if (! comptypes (DECL_ARG_TYPE (parm), TREE_VALUE (type)))
+             /* 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 (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
                      == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -6308,8 +6715,7 @@ store_parm_decls ()
                      DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
 
                      if (PROMOTE_PROTOTYPES
-                         && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
-                             || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
+                         && INTEGRAL_TYPE_P (TREE_TYPE (parm))
                          && TYPE_PRECISION (TREE_TYPE (parm))
                          < TYPE_PRECISION (integer_type_node))
                        DECL_ARG_TYPE (parm) = integer_type_node;
@@ -6401,14 +6807,26 @@ store_parm_decls ()
   gen_aux_info_record (fndecl, 1, 0, prototype);
 
   /* Initialize the RTL code for the function.  */
-
   init_function_start (fndecl, input_filename, lineno);
 
   /* Begin the statement tree for this function.  */
-  DECL_LANG_SPECIFIC (current_function_decl)
-    =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
   begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
 
+  /* If this is a nested function, save away the sizes of any
+     variable-size types so that we can expand them when generating
+     RTL.  */
+  if (context)
+    {
+      tree t;
+
+      DECL_LANG_SPECIFIC (fndecl)->pending_sizes 
+       = nreverse (get_pending_sizes ());
+      for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
+          t;
+          t = TREE_CHAIN (t))
+       SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
+    }
+
   /* This function is being processed in whole-function mode.  */
   cfun->x_whole_function_mode_p = 1;
 
@@ -6418,149 +6836,8 @@ store_parm_decls ()
      not safe to try to expand expressions involving them.  */
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
-}
-\f
-/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
-   each with a parm name as the TREE_VALUE.  A null pointer as TREE_VALUE
-   stands for an ellipsis in the identifier list.
-
-   PARMLIST is the data returned by get_parm_info for the
-   parmlist that follows the semicolon.
-
-   We return a value of the same sort that get_parm_info returns,
-   except that it describes the combination of identifiers and parmlist.  */
-
-tree
-combine_parm_decls (specparms, parmlist, void_at_end)
-     tree specparms, parmlist;
-     int void_at_end;
-{
-  register tree fndecl = current_function_decl;
-  register tree parm;
-
-  tree parmdecls = TREE_PURPOSE (parmlist);
-
-  /* This is a chain of any other decls that came in among the parm
-     declarations.  They were separated already by get_parm_info,
-     so we just need to keep them separate.  */
-  tree nonparms = TREE_VALUE (parmlist);
 
-  tree types = 0;
-
-  for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-    DECL_WEAK (parm) = 0;
-
-  for (parm = specparms; parm; parm = TREE_CHAIN (parm))
-    {
-      register tree tail, found = NULL;
-
-      /* See if any of the parmdecls specifies this parm by name.  */
-      for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
-       if (DECL_NAME (tail) == TREE_VALUE (parm))
-         {
-           found = tail;
-           break;
-         }
-
-      /* If declaration already marked, we have a duplicate name.
-        Complain, and don't use this decl twice.   */
-      if (found && DECL_WEAK (found))
-       {
-         error_with_decl (found, "multiple parameters named `%s'");
-         found = 0;
-       }
-
-      /* If the declaration says "void", complain and ignore it.  */
-      if (found && VOID_TYPE_P (TREE_TYPE (found)))
-       {
-         error_with_decl (found, "parameter `%s' declared void");
-         TREE_TYPE (found) = integer_type_node;
-         DECL_ARG_TYPE (found) = integer_type_node;
-         layout_decl (found, 0);
-       }
-
-      /* Traditionally, a parm declared float is actually a double.  */
-      if (found && flag_traditional
-         && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
-       {
-         TREE_TYPE (found) = double_type_node;
-         DECL_ARG_TYPE (found) = double_type_node;
-         layout_decl (found, 0);
-       }
-
-      /* If no declaration found, default to int.  */
-      if (!found)
-       {
-         found = build_decl (PARM_DECL, TREE_VALUE (parm),
-                             integer_type_node);
-         DECL_ARG_TYPE (found) = TREE_TYPE (found);
-         DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
-         DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
-         error_with_decl (found, "type of parameter `%s' is not declared");
-         pushdecl (found);
-       }
-
-      TREE_PURPOSE (parm) = found;
-
-      /* Mark this decl as "already found".  */
-      DECL_WEAK (found) = 1;
-    }
-
-  /* Complain about any actual PARM_DECLs not matched with any names.  */
-
-  for (parm = parmdecls; parm;)
-    {
-      tree next = TREE_CHAIN (parm);
-      TREE_CHAIN (parm) = 0;
-
-      /* Complain about args with incomplete types.  */
-      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
-       {
-         error_with_decl (parm, "parameter `%s' has incomplete type");
-         TREE_TYPE (parm) = error_mark_node;
-       }
-
-      if (! DECL_WEAK (parm))
-       {
-         error_with_decl (parm,
-                          "declaration for parameter `%s' but no such parameter");
-         /* Pretend the parameter was not missing.
-            This gets us to a standard state and minimizes
-            further error messages.  */
-         specparms
-           = chainon (specparms,
-                      tree_cons (parm, NULL_TREE, NULL_TREE));
-       }
-
-      parm = next;
-    }
-
-  /* Chain the declarations together in the order of the list of names.
-     At the same time, build up a list of their types, in reverse order.  */
-
-  parm = specparms;
-  parmdecls = 0;
-  {
-    register tree last;
-    for (last = 0; parm; parm = TREE_CHAIN (parm))
-      if (TREE_PURPOSE (parm))
-       {
-         if (last == 0)
-           parmdecls = TREE_PURPOSE (parm);
-         else
-           TREE_CHAIN (last) = TREE_PURPOSE (parm);
-         last = TREE_PURPOSE (parm);
-         TREE_CHAIN (last) = 0;
-
-         types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
-       }
-  }
-
-  if (void_at_end)
-    return tree_cons (parmdecls, nonparms,
-                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
-
-  return tree_cons (parmdecls, nonparms, nreverse (types));
+  warn_shadow = saved_warn_shadow;
 }
 \f
 /* Finish up a function declaration and compile that function
@@ -6575,7 +6852,7 @@ void
 finish_function (nested)
      int nested;
 {
-  register tree fndecl = current_function_decl;
+  tree fndecl = current_function_decl;
 
 /*  TREE_READONLY (fndecl) = 1;
     This caused &foo to be of type ptr-to-const-function
@@ -6616,6 +6893,8 @@ finish_function (nested)
 #endif
        }
     }
+  
+  finish_fname_decls ();
 
   /* Tie off the statement tree for this function.  */
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
@@ -6629,32 +6908,81 @@ finish_function (nested)
   if (! nested)
     {
       /* Generate RTL for the body of this function.  */
-      c_expand_body (fndecl, nested);
+      c_expand_body (fndecl, nested, 1);
       /* Let the error reporting routines know that we're outside a
         function.  For a nested function, this value is used in
         pop_c_function_context and then reset via pop_function_context.  */
       current_function_decl = NULL;
-      c_function_name_declared_p = 0;
+    }
+}
+
+/* Generate the RTL for a deferred function FNDECL.  */
+
+void
+c_expand_deferred_function (fndecl)
+     tree fndecl;
+{
+  /* DECL_INLINE or DECL_RESULT might got cleared after the inline
+     function was deferred, e.g. in duplicate_decls.  */
+  if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
+    {
+      c_expand_body (fndecl, 0, 0);
+      current_function_decl = NULL;
     }
 }
 
 /* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
    then we are already in the process of generating RTL for another
-   function.  */
+   function.  If can_defer_p is zero, we won't attempt to defer the
+   generation of RTL.  */
 
 static void
-c_expand_body (fndecl, nested_p)
+c_expand_body (fndecl, nested_p, can_defer_p)
      tree fndecl;
-     int nested_p;
+     int nested_p, can_defer_p;
 {
+  int uninlinable = 1;
+
   /* There's no reason to do any of the work here if we're only doing
      semantic analysis; this code just generates RTL.  */
   if (flag_syntax_only)
     return;
 
-  /* Squirrel away our current state.  */
+  if (flag_inline_trees)
+    {
+      /* First, cache whether the current function is inlinable.  Some
+         predicates depend on cfun and current_function_decl to
+         function completely.  */
+      timevar_push (TV_INTEGRATION);
+      uninlinable = ! tree_inlinable_function_p (fndecl);
+      
+      if (! uninlinable && can_defer_p
+         /* Save function tree for inlining.  Should return 0 if the
+             language does not support function deferring or the
+             function could not be deferred.  */
+         && defer_fn (fndecl))
+       {
+         /* Let the back-end know that this function exists.  */
+         (*debug_hooks->deferred_inline_function) (fndecl);
+          timevar_pop (TV_INTEGRATION);
+         return;
+       }
+      
+      /* Then, inline any functions called in it.  */
+      optimize_inline_calls (fndecl);
+      timevar_pop (TV_INTEGRATION);
+    }
+
+  timevar_push (TV_EXPAND);
+
   if (nested_p)
-    push_function_context ();
+    {
+      /* Make sure that we will evaluate variable-sized types involved
+        in our function's type.  */
+      expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
+      /* Squirrel away our current state.  */
+      push_function_context ();
+    }
 
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
@@ -6686,10 +7014,13 @@ c_expand_body (fndecl, nested_p)
 
   /* Generate the RTL for this function.  */
   expand_stmt (DECL_SAVED_TREE (fndecl));
-  /* Allow the body of the function to be garbage collected.  */
-  DECL_SAVED_TREE (fndecl) = NULL_TREE;
+  if (uninlinable)
+    {
+      /* Allow the body of the function to be garbage collected.  */
+      DECL_SAVED_TREE (fndecl) = NULL_TREE;
+    }
 
-  /* We hard-wired immediate_size_expand to zero in start_function.
+  /* We hard-wired immediate_size_expand to zero above.
      expand_function_end will decrement this variable.  So, we set the
      variable to one here, so that after the decrement it will remain
      zero.  */
@@ -6729,7 +7060,8 @@ c_expand_body (fndecl, nested_p)
     {
       tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
 
-      if (ret_type && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
+      if (ret_type && TYPE_SIZE_UNIT (ret_type)
+         && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
          && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
                                   larger_than_size))
        {
@@ -6747,7 +7079,8 @@ c_expand_body (fndecl, nested_p)
        }
     }
 
-  if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p)
+  if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p
+      && ! flag_inline_trees)
     {
       /* Stop pointing to the local nodes about to be freed.
         But DECL_INITIAL must remain nonzero so we know this
@@ -6762,38 +7095,26 @@ c_expand_body (fndecl, nested_p)
 
   if (DECL_STATIC_CONSTRUCTOR (fndecl))
     {
-#ifndef ASM_OUTPUT_CONSTRUCTOR
-      if (! flag_gnu_linker)
-       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+      if (targetm.have_ctors_dtors)
+       (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+                                        DEFAULT_INIT_PRIORITY);
       else
-#endif
-       assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
-
+       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
     }
+
   if (DECL_STATIC_DESTRUCTOR (fndecl))
     {
-#ifndef ASM_OUTPUT_DESTRUCTOR
-      if (! flag_gnu_linker)
-       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
+      if (targetm.have_ctors_dtors)
+       (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
+                                       DEFAULT_INIT_PRIORITY);
       else
-#endif
-       assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
+       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
     }
 
   if (nested_p)
-    {
-      /* Return to the enclosing function.  */
-      pop_function_context ();
-      /* If the nested function was inline, write it out if that is
-        necessary.  */
-      if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
-       {
-         push_function_context ();
-         output_inline_function (fndecl);
-         pop_function_context ();
-       }
-    }
-
+    /* Return to the enclosing function.  */
+    pop_function_context ();
+  timevar_pop (TV_EXPAND);
 }
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
@@ -6828,12 +7149,21 @@ check_for_loop_decls ()
   for (t = gettags (); t; t = TREE_CHAIN (t))
     {
       if (TREE_PURPOSE (t) != 0)
-       error ("`%s %s' declared in `for' loop initial declaration",
-              (TREE_CODE (TREE_VALUE (t)) == RECORD_TYPE ? "struct"
-               : TREE_CODE (TREE_VALUE (t)) == UNION_TYPE ? "union"
-               : "enum"),
-              IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+        {
+          enum tree_code code = TREE_CODE (TREE_VALUE (t));
+         
+          if (code == RECORD_TYPE)
+            error ("`struct %s' declared in `for' loop initial declaration",
+                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+          else if (code == UNION_TYPE)
+            error ("`union %s' declared in `for' loop initial declaration",
+                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+          else
+            error ("`enum %s' declared in `for' loop initial declaration",
+                   IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+        }
     }
+
   for (t = getdecls (); t; t = TREE_CHAIN (t))
     {
       if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
@@ -6875,7 +7205,6 @@ push_c_function_context (f)
 
   p->base.x_stmt_tree = c_stmt_tree;
   p->base.x_scope_stmt_stack = c_scope_stmt_stack;
-  p->base.x_function_name_declared_p = c_function_name_declared_p;
   p->named_labels = named_labels;
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
@@ -6913,7 +7242,6 @@ pop_c_function_context (f)
 
   c_stmt_tree = p->base.x_stmt_tree;
   c_scope_stmt_stack = p->base.x_scope_stmt_stack;
-  c_function_name_declared_p = p->base.x_function_name_declared_p;
   named_labels = p->named_labels;
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
@@ -6944,7 +7272,7 @@ mark_c_function_context (f)
   mark_binding_level (&p->binding_level);
 }
 
-/* Copy the DECL_LANG_SEPECIFIC data associated with NODE.  */
+/* Copy the DECL_LANG_SPECIFIC data associated with NODE.  */
 
 void
 copy_lang_decl (decl)
@@ -6983,6 +7311,7 @@ lang_mark_tree (t)
     {
       ggc_mark (DECL_LANG_SPECIFIC (t));
       c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+      ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
     }
 }
 
@@ -7046,13 +7375,6 @@ c_begin_compound_stmt ()
 
   /* Create the COMPOUND_STMT.  */
   stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
-  /* If we haven't already declared __FUNCTION__ and its ilk then this
-     is the opening curly brace of the function.  Declare them now.  */
-  if (!c_function_name_declared_p)
-    {
-      c_function_name_declared_p = 1;
-      declare_function_name ();
-    }
 
   return stmt;
 }
@@ -7070,7 +7392,7 @@ c_expand_decl_stmt (t)
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_CONTEXT (decl) == current_function_decl
       && DECL_SAVED_TREE (decl))
-    c_expand_body (decl, /*nested_p=*/1);
+    c_expand_body (decl, /*nested_p=*/1, /*can_defer_p=*/0);
 }
 
 /* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since