OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 850ac6d..1f773d9 100644 (file)
@@ -1,5 +1,6 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -28,15 +29,19 @@ Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "intl.h"
 #include "tree.h"
+#include "rtl.h"
 #include "flags.h"
 #include "function.h"
 #include "output.h"
+#include "expr.h"
 #include "c-tree.h"
 #include "c-lex.h"
 #include "toplev.h"
 #include "defaults.h"
 #include "ggc.h"
+#include "tm_p.h"
 
 #if USE_CPPLIB
 #include "cpplib.h"
@@ -69,6 +74,10 @@ enum decl_context
 #ifndef WCHAR_TYPE
 #define WCHAR_TYPE "int"
 #endif
+
+#ifndef WINT_TYPE
+#define WINT_TYPE "unsigned int"
+#endif
 \f
 /* Do GC.  */
 int ggc_p = 1;
@@ -78,7 +87,7 @@ int ggc_p = 1;
 
 tree pending_invalid_xref;
 /* File and line to appear in the eventual error message.  */
-char *pending_invalid_xref_file;
+const char *pending_invalid_xref_file;
 int pending_invalid_xref_line;
 
 /* While defining an enum type, this is 1 plus the last enumerator
@@ -114,7 +123,7 @@ static tree current_function_parm_tags;
 
 /* Similar, for the file and line that the prototype came from if this is
    an old-style definition.  */
-static char *current_function_prototype_file;
+static const char *current_function_prototype_file;
 static int current_function_prototype_line;
 
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
@@ -132,10 +141,6 @@ static tree shadowed_labels;
 
 static int c_function_varargs;
 
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 /* Set to 0 at beginning of a function definition, set to 1 if
    a return statement that specifies a return value is seen.  */
 
@@ -277,20 +282,21 @@ tree static_ctors, static_dtors;
 
 /* Forward declarations.  */
 
-static struct binding_level * make_binding_level       PROTO((void));
-static void mark_binding_level         PROTO((void *));
-static void clear_limbo_values         PROTO((tree));
-static int duplicate_decls             PROTO((tree, tree, int));
-static int redeclaration_error_message PROTO((tree, tree));
-static void storedecls                 PROTO((tree));
-static void storetags                  PROTO((tree));
-static tree lookup_tag                 PROTO((enum tree_code, tree,
-                                              struct binding_level *, int));
-static tree lookup_tag_reverse         PROTO((tree));
-static tree grokdeclarator             PROTO((tree, tree, enum decl_context,
-                                              int));
-static tree grokparms                  PROTO((tree, int));
-static void layout_array_type          PROTO((tree));
+static struct binding_level * make_binding_level       PARAMS ((void));
+static void mark_binding_level         PARAMS ((void *));
+static void clear_limbo_values         PARAMS ((tree));
+static int duplicate_decls             PARAMS ((tree, tree, int));
+static int redeclaration_error_message PARAMS ((tree, tree));
+static void storedecls                 PARAMS ((tree));
+static void storetags                  PARAMS ((tree));
+static tree lookup_tag                 PARAMS ((enum tree_code, tree,
+                                                struct binding_level *, int));
+static tree lookup_tag_reverse         PARAMS ((tree));
+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));
 \f
 /* C-specific option variables.  */
 
@@ -324,9 +330,17 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
-/* Nonzero means use the ISO C9x dialect of C.  */
+/* Nonzero means enable C89 Amendment 1 features, other than digraphs.  */
+
+int flag_isoc94 = 0;
 
-int flag_isoc9x = 0;
+/* Nonzero means use the ISO C99 dialect of C.  */
+
+int flag_isoc99 = 0;
+
+/* Nonzero means accept digraphs.  */
+
+int flag_digraphs = 1;
 
 /* Nonzero means that we have builtin functions, and main is an int */
 
@@ -352,7 +366,7 @@ int warn_long_long = 1;
 /* Nonzero means message about use of implicit function declarations;
  1 means warning; 2 means error. */
 
-int mesg_implicit_function_declaration;
+int mesg_implicit_function_declaration = -1;
 
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
@@ -453,6 +467,14 @@ int warn_float_equal = 0;
 
 int warn_multichar = 1;
 
+/* Wrapper since C and C++ expand_expr_stmt are different. */
+
+expand_expr_stmt_fn lang_expand_expr_stmt = c_expand_expr_stmt;
+
+/* 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
@@ -481,6 +503,7 @@ c_decode_option (argc, argv)
     {
       flag_traditional = 1;
       flag_writable_strings = 1;
+      flag_digraphs = 0;
     }
   else if (!strcmp (p, "-fallow-single-precision"))
     flag_allow_single_precision = 1;
@@ -501,6 +524,7 @@ c_decode_option (argc, argv)
     {
       flag_traditional = 0;
       flag_writable_strings = 0;
+      flag_digraphs = 1;
     }
   else if (!strncmp (p, "-std=", 5))
     {
@@ -508,11 +532,11 @@ c_decode_option (argc, argv)
         recognize:
         -std=iso9899:1990      same as -ansi
         -std=iso9899:199409    ISO C as modified in amend. 1
-        -std=iso9899:199x      ISO C 9x
+        -std=iso9899:1999      ISO C 99
         -std=c89               same as -std=iso9899:1990
-        -std=c9x               same as -std=iso9899:199x
+        -std=c99               same as -std=iso9899:1999
         -std=gnu89             default, iso9899:1990 + gnu extensions
-        -std=gnu9x             iso9899:199x + gnu extensions
+        -std=gnu99             iso9899:1999 + gnu extensions
       */
       const char *argstart = &p[5];
 
@@ -520,25 +544,33 @@ c_decode_option (argc, argv)
          || !strcmp (argstart, "c89"))
        {
        iso_1990:
+         flag_digraphs = 0;
+         flag_isoc94 = 0;
+       iso_1990_digraphs:
          flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 1;
          flag_no_nonansi_builtin = 1;
-         flag_isoc9x = 0;
+         flag_isoc99 = 0;
        }
       else if (!strcmp (argstart, "iso9899:199409"))
        {
-         /* ??? The changes since ISO C 1990 are not supported.  */
-         goto iso_1990;
+         flag_digraphs = 1;
+         flag_isoc94 = 1;
+         goto iso_1990_digraphs;
        }
       else if (!strcmp (argstart, "iso9899:199x")
-              || !strcmp (argstart, "c9x"))
+              || !strcmp (argstart, "iso9899:1999")
+              || !strcmp (argstart, "c9x")
+              || !strcmp (argstart, "c99"))
        {
          flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 1;
          flag_no_nonansi_builtin = 1;
-         flag_isoc9x = 1;
+         flag_isoc99 = 1;
+         flag_digraphs = 1;
+         flag_isoc94 = 1;
        }
       else if (!strcmp (argstart, "gnu89"))
        {
@@ -546,15 +578,19 @@ c_decode_option (argc, argv)
          flag_writable_strings = 0;
          flag_no_asm = 0;
          flag_no_nonansi_builtin = 0;
-         flag_isoc9x = 0;
+         flag_isoc99 = 0;
+         flag_digraphs = 1;
+         flag_isoc94 = 0;
        }
-      else if (!strcmp (argstart, "gnu9x"))
+      else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
        {
          flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 0;
          flag_no_nonansi_builtin = 0;
-         flag_isoc9x = 1;
+         flag_isoc99 = 1;
+         flag_digraphs = 1;
+         flag_isoc94 = 1;
        }
       else
        error ("unknown C standard `%s'", argstart);
@@ -675,6 +711,8 @@ c_decode_option (argc, argv)
     warn_traditional = 1;
   else if (!strcmp (p, "-Wno-traditional"))
     warn_traditional = 0;
+  else if (!strncmp (p, "-Wformat=", 9))
+    warn_format = atol (p + 9);
   else if (!strcmp (p, "-Wformat"))
     warn_format = 1;
   else if (!strcmp (p, "-Wno-format"))
@@ -751,7 +789,7 @@ c_decode_option (argc, argv)
       warn_implicit_int = 1;
       mesg_implicit_function_declaration = 1;
       warn_return_type = 1;
-      warn_unused = 1;
+      set_Wunused (1);
       warn_switch = 1;
       warn_format = 1;
       warn_char_subscripts = 1;
@@ -983,7 +1021,7 @@ poplevel (keep, reverse, functionbody)
 #if 0
   /* Warn about incomplete structure types in this level.  */
   for (link = tags; link; link = TREE_CHAIN (link))
-    if (TYPE_SIZE (TREE_VALUE (link)) == 0)
+    if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
       {
        tree type = TREE_VALUE (link);
        tree type_name = TYPE_NAME (type);
@@ -1118,7 +1156,7 @@ poplevel (keep, reverse, functionbody)
              define_label (input_filename, lineno,
                            DECL_NAME (label));
            }
-         else if (warn_unused && !TREE_USED (label))
+         else if (warn_unused_label && !TREE_USED (label))
            warning_with_decl (label, "label `%s' defined but not used");
          IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
 
@@ -1279,7 +1317,7 @@ pop_label_level ()
              define_label (input_filename, lineno,
                            DECL_NAME (TREE_VALUE (link)));
            }
-         else if (warn_unused && !TREE_USED (TREE_VALUE (link)))
+         else if (warn_unused_label && !TREE_USED (TREE_VALUE (link)))
            warning_with_decl (TREE_VALUE (link), 
                               "label `%s' defined but not used");
          IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) = 0;
@@ -1339,10 +1377,7 @@ pushtag (name, type)
        TYPE_NAME (type) = name;
     }
 
-  if (b == global_binding_level)
-    b->tags = perm_tree_cons (name, type, b->tags);
-  else
-    b->tags = saveable_tree_cons (name, type, b->tags);
+  b->tags = tree_cons (name, type, b->tags);
 
   /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
      tagged type we just added to the current binding level.  This fake
@@ -1381,7 +1416,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   tree newtype = TREE_TYPE (newdecl);
   int errmsg = 0;
 
-  if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
+  if (DECL_P (olddecl))
     DECL_MACHINE_ATTRIBUTES (newdecl)
       =  merge_machine_decl_attributes (olddecl, newdecl);
 
@@ -1469,17 +1504,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          tree oldreturntype = TREE_TYPE (oldtype);
          tree newreturntype = TREE_TYPE (newtype);
 
-         /* Make sure we put the new type in the same obstack as the old ones.
-            If the old types are not both in the same obstack, use the
-            permanent one.  */
-         if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
-           push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
-         else
-           {
-             push_obstacks_nochange ();
-             end_temporary_allocation ();
-           }
-
           if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
             {
              /* Function types may be shared, so we can't just modify
@@ -1515,8 +1539,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            }
          if (! different_binding_level)
            TREE_TYPE (olddecl) = oldtype;
-
-         pop_obstacks ();
        }
       if (!types_match)
        {
@@ -1779,17 +1801,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         different_binding_level is true.  */
       tree write_olddecl = different_binding_level ? newdecl : olddecl;
 
-      /* Make sure we put the new type in the same obstack as the old ones.
-        If the old types are not both in the same obstack, use the permanent
-        one.  */
-      if (TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
-       push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
-      else
-       {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-       }
-                      
       /* Merge the data types specified in the two decls.  */
       if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
        {
@@ -1819,25 +1830,39 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
        {
          /* Since the type is OLDDECL's, make OLDDECL's size go with.  */
          DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
+         DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
          DECL_MODE (newdecl) = DECL_MODE (olddecl);
          if (TREE_CODE (olddecl) != FUNCTION_DECL)
            if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
-             DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+             {
+               DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
+               DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
+             }
        }
 
       /* Keep the old rtl since we can safely use it.  */
       DECL_RTL (newdecl) = DECL_RTL (olddecl);
 
       /* Merge the type qualifiers.  */
-      if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
-         && !TREE_THIS_VOLATILE (newdecl))
+      if (TREE_CODE (olddecl) == FUNCTION_DECL
+         && DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
+         && ! TREE_THIS_VOLATILE (newdecl))
        TREE_THIS_VOLATILE (write_olddecl) = 0;
+
       if (TREE_READONLY (newdecl))
        TREE_READONLY (write_olddecl) = 1;
+
       if (TREE_THIS_VOLATILE (newdecl))
        {
          TREE_THIS_VOLATILE (write_olddecl) = 1;
-         if (TREE_CODE (newdecl) == VAR_DECL)
+         if (TREE_CODE (newdecl) == VAR_DECL
+             /* If an automatic variable is re-declared in the same
+                function scope, but the old declaration was not
+                volatile, make_var_volatile() would crash because the
+                variable would have been assigned to a pseudo, not a
+                MEM.  Since this duplicate declaration is invalid
+                anyway, we just skip the call.  */
+             && errmsg == 0)
            make_var_volatile (newdecl);
        }
 
@@ -1887,8 +1912,6 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          DECL_NO_LIMIT_STACK (newdecl)
            |= DECL_NO_LIMIT_STACK (olddecl);
        }
-
-      pop_obstacks ();
     }
   /* If cannot merge, then use the new type and qualifiers,
      and don't preserve the old rtl.  */
@@ -1930,14 +1953,15 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
     }
 
-  /* 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;
-  DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
   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;
+
+      DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
+
       if (DECL_BUILT_IN (olddecl))
        {
          /* Get rid of any built-in function if new arg types don't match it
@@ -1972,7 +1996,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
          if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
+           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ABSTRACT_ORIGIN (olddecl);
        }
     }
   if (different_binding_level)
@@ -2040,7 +2064,7 @@ pushdecl (x)
 
   if (name)
     {
-      char *file;
+      const char *file;
       int line;
       int different_binding_level = 0;
 
@@ -2161,6 +2185,7 @@ pushdecl (x)
              DECL_ORIGINAL_TYPE (x) = tt;
               tt = build_type_copy (tt);
               TYPE_NAME (tt) = x;
+             TREE_USED (tt) = TREE_USED (x);
               TREE_TYPE (x) = tt;
             }
         }
@@ -2171,7 +2196,8 @@ pushdecl (x)
 
         We get warnings about inline functions where they are defined.
         Avoid duplicate warnings where they are used.  */
-      if (TREE_PUBLIC (x) && ! DECL_INLINE (x))
+      if (TREE_PUBLIC (x)
+         && ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
        {
          tree decl;
 
@@ -2221,7 +2247,7 @@ pushdecl (x)
            {
              if (type == error_mark_node)
                break;
-             if (TYPE_CONTEXT (type))
+             if (TYPE_CONTEXT (type))
                {
                  warning_with_decl (x, "type of external `%s' is not global");
                  /* By exiting the loop early, we leave TYPE nonzero,
@@ -2308,15 +2334,16 @@ pushdecl (x)
          /* Here to install a non-global value.  */
          tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
          tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
+
          IDENTIFIER_LOCAL_VALUE (name) = x;
 
          /* If this is an extern function declaration, see if we
             have a global definition or declaration for the function.  */
          if (oldlocal == 0
-             && DECL_EXTERNAL (x) && !DECL_INLINE (x)
              && oldglobal != 0
              && TREE_CODE (x) == FUNCTION_DECL
-             && TREE_CODE (oldglobal) == FUNCTION_DECL)
+             && TREE_CODE (oldglobal) == FUNCTION_DECL
+             && DECL_EXTERNAL (x) && ! DECL_INLINE (x))
            {
              /* We have one.  Their types must agree.  */
              if (! comptypes (TREE_TYPE (x),
@@ -2434,8 +2461,12 @@ pushdecl (x)
            b->shadowed = tree_cons (name, oldlocal, b->shadowed);
        }
 
-      /* Keep count of variables in this level with incomplete type.  */
-      if (TYPE_SIZE (TREE_TYPE (x)) == 0)
+      /* Keep count of variables in this level with incomplete type.
+        If the input is erroneous, we can have error_mark in the type
+        slot (e.g. "f(void a, ...)") - that doesn't count as an
+        incomplete type.  */
+      if (TREE_TYPE (x) != error_mark_node
+         && !COMPLETE_TYPE_P (TREE_TYPE (x)))
        ++b->n_incomplete;
     }
 
@@ -2474,10 +2505,6 @@ implicitly_declare (functionid)
   /* Only one "implicit declaration" warning per identifier.  */
   int implicit_warning;
 
-  /* Save the decl permanently so we can warn if definition follows.  */
-  push_obstacks_nochange ();
-  end_temporary_allocation ();
-
   /* We used to reuse an old implicit decl here,
      but this loses with inline functions because it can clobber
      the saved decl chains.  */
@@ -2510,15 +2537,8 @@ implicitly_declare (functionid)
 
   rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
 
-  if (mesg_implicit_function_declaration && implicit_warning)
-    {
-      if (mesg_implicit_function_declaration == 2)
-        error ("implicit declaration of function `%s'",
-                 IDENTIFIER_POINTER (functionid));
-      else
-        warning ("implicit declaration of function `%s'",
-                 IDENTIFIER_POINTER (functionid));
-    }
+  if (implicit_warning)
+    implicit_decl_warning (functionid);
   else if (warn_traditional && traditional_warning)
     warning ("function `%s' was previously declared within a block",
             IDENTIFIER_POINTER (functionid));
@@ -2528,11 +2548,20 @@ implicitly_declare (functionid)
 
   gen_aux_info_record (decl, 0, 1, 0);
 
-  pop_obstacks ();
-
   return decl;
 }
 
+void
+implicit_decl_warning (id)
+     tree id;
+{
+  char *name = IDENTIFIER_POINTER (id);
+  if (mesg_implicit_function_declaration == 2)
+    error ("implicit declaration of function `%s'", name);
+  else if (mesg_implicit_function_declaration == 1)
+    warning ("implicit declaration of function `%s'", name);
+}
+
 /* Return zero if the declaration NEWDECL is valid
    when the declaration OLDDECL (assumed to be for the same name)
    has already been seen.
@@ -2569,8 +2598,8 @@ 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_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
+              && ! (DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
        return 1;
       return 0;
     }
@@ -2698,7 +2727,7 @@ shadow_label (name)
 
 tree
 define_label (filename, line, name)
-     char *filename;
+     const char *filename;
      int line;
      tree name;
 {
@@ -2712,6 +2741,10 @@ define_label (filename, line, name)
       decl = lookup_label (name);
     }
 
+  if (warn_traditional && lookup_name (name))
+    warning ("traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
+            IDENTIFIER_POINTER (name));
+  
   if (DECL_INITIAL (decl) != 0)
     {
       error ("duplicate label `%s'", IDENTIFIER_POINTER (name));
@@ -2886,13 +2919,14 @@ lookup_name_current_level (name)
 }
 \f
 /* Mark ARG for GC.  */
+
 static void 
 mark_binding_level (arg)
      void *arg;
 {
   struct binding_level *level = *(struct binding_level **) arg;
 
-  while (level)
+  for (; level != 0; level = level->level_chain)
     {
       ggc_mark_tree (level->names);
       ggc_mark_tree (level->tags);
@@ -2900,7 +2934,6 @@ mark_binding_level (arg)
       ggc_mark_tree (level->blocks);
       ggc_mark_tree (level->this_block);
       ggc_mark_tree (level->parm_order);
-      level = level->level_chain;
     }
 }
 
@@ -2916,6 +2949,7 @@ init_decl_processing ()
   tree ptr_ftype_void, ptr_ftype_ptr;
   int wchar_type_size;
   tree array_domain_type;
+  tree t;
 
   current_function_decl = NULL;
   named_labels = NULL;
@@ -2968,14 +3002,18 @@ init_decl_processing ()
      Traditionally, use a signed type.
      Note that stddef.h uses `unsigned long',
      and this must agree, even if long and int are the same size.  */
-  set_sizetype
-    (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
-  if (flag_traditional && TREE_UNSIGNED (sizetype))
-    set_sizetype (signed_type (sizetype));
+  t = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+  signed_size_type_node = signed_type (t);
+  if (flag_traditional && TREE_UNSIGNED (t))
+    t = signed_type (t);
+    
+  set_sizetype (t);
 
   /* Create the widest literal types. */
-  widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
-  widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+  widest_integer_literal_type_node
+    = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+  widest_unsigned_literal_type_node
+    = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
                        widest_integer_literal_type_node));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
@@ -3012,6 +3050,8 @@ init_decl_processing ()
   signed_wchar_type_node = signed_type (wchar_type_node);
   unsigned_wchar_type_node = unsigned_type (wchar_type_node);
 
+  wint_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WINT_TYPE)));
+
   boolean_type_node = integer_type_node;
   boolean_true_node = integer_one_node;
   boolean_false_node = integer_zero_node;
@@ -3032,9 +3072,11 @@ init_decl_processing ()
      array type.  */
   char_array_type_node
     = build_array_type (char_type_node, array_domain_type);
+
   /* Likewise for arrays of ints.  */
   int_array_type_node
     = build_array_type (integer_type_node, array_domain_type);
+
   /* This is for wide string constants.  */
   wchar_array_type_node
     = build_array_type (wchar_type_node, array_domain_type);
@@ -3045,6 +3087,7 @@ init_decl_processing ()
     = build_function_type (integer_type_node, NULL_TREE);
   ptrdiff_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
+  unsigned_ptrdiff_type_node = unsigned_type (ptrdiff_type_node);
 
   c_common_nodes_and_builtins (0, flag_no_builtin, flag_no_nonansi_builtin);
 
@@ -3054,6 +3097,55 @@ init_decl_processing ()
     = build_function_type (ptr_type_node,
                           tree_cons (NULL_TREE, ptr_type_node, endlink));
 
+  /* Types which are common to the fortran compiler and libf2c.  When
+     changing these, you also need to be concerned with f/com.h. */
+
+  if (TYPE_PRECISION (float_type_node)
+      == TYPE_PRECISION (long_integer_type_node))
+    {
+      g77_integer_type_node = long_integer_type_node;
+      g77_uinteger_type_node = long_unsigned_type_node;
+    }
+  else if (TYPE_PRECISION (float_type_node)
+          == TYPE_PRECISION (integer_type_node))
+    {
+      g77_integer_type_node = integer_type_node;
+      g77_uinteger_type_node = unsigned_type_node;
+    }
+  else
+    g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
+
+  if (g77_integer_type_node != NULL_TREE)
+    {
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_integer"),
+                           g77_integer_type_node));
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_uinteger"),
+                           g77_uinteger_type_node));
+    }
+
+  if (TYPE_PRECISION (float_type_node) * 2
+      == TYPE_PRECISION (long_integer_type_node))
+    {
+      g77_longint_type_node = long_integer_type_node;
+      g77_ulongint_type_node = long_unsigned_type_node;
+    }
+  else if (TYPE_PRECISION (float_type_node) * 2
+          == TYPE_PRECISION (long_long_integer_type_node))
+    {
+      g77_longint_type_node = long_long_integer_type_node;
+      g77_ulongint_type_node = long_long_unsigned_type_node;
+    }
+  else
+    g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
+
+  if (g77_longint_type_node != NULL_TREE)
+    {
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_longint"),
+                           g77_longint_type_node));
+      pushdecl (build_decl (TYPE_DECL, get_identifier ("__g77_ulongint"),
+                           g77_ulongint_type_node));
+    }
+
   builtin_function ("__builtin_aggregate_incoming_address",
                    build_function_type (ptr_type_node, NULL_TREE),
                    BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
@@ -3088,6 +3180,7 @@ init_decl_processing ()
   pedantic_lvalues = pedantic;
 
   /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+  make_fname_decl = c_make_fname_decl;
   declare_function_name ();
 
   start_identifier_warnings ();
@@ -3099,12 +3192,9 @@ init_decl_processing ()
 
   incomplete_decl_finalize_hook = finish_incomplete_decl;
 
-  lang_get_alias_set = c_get_alias_set;
-
   /* Record our roots.  */
 
   ggc_add_tree_root (c_global_trees, CTI_MAX);
-  ggc_add_tree_root (&current_function_decl, 1);
   ggc_add_tree_root (&named_labels, 1);
   ggc_add_tree_root (&shadowed_labels, 1);
   ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
@@ -3115,6 +3205,43 @@ init_decl_processing ()
   ggc_add_tree_root (&static_dtors, 1);
 }
 
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
+   decl, NAME is the initialization string and TYPE_DEP indicates whether
+   NAME depended on the type of the function.  As we don't yet implement
+   delayed emission of static data, we mark the decl as emitted
+   so it is not placed in the output.  Anything using it must therefore pull
+   out the STRING_CST initializer directly.  This does mean that these names
+   are string merging candidates, which C99 does not permit.  */
+
+static tree
+c_make_fname_decl (id, name, type_dep)
+     tree id;
+     const char *name;
+     int type_dep ATTRIBUTE_UNUSED;
+{
+  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)));
+
+  decl = build_decl (VAR_DECL, id, type);
+  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);
+  
+  return decl;
+}
+
 /* Return a definition for a builtin function named NAME and whose data type
    is TYPE.  TYPE should be a function type with argument types.
    FUNCTION_CODE tells later passes how to compile calls to this function.
@@ -3281,10 +3408,6 @@ groktypename_in_parm_context (typename)
    do go through here.  Structure field declarations are done by
    grokfield and not through here.  */
 
-/* Set this to zero to debug not using the temporary obstack
-   to parse initializers.  */
-int debug_temp_inits = 1;
-
 tree
 start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
      tree declarator, declspecs;
@@ -3294,10 +3417,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   register tree decl = grokdeclarator (declarator, declspecs,
                                       NORMAL, initialized);
   register tree tem;
-  int init_written = initialized;
-
-  /* The corresponding pop_obstacks is in finish_decl.  */
-  push_obstacks_nochange ();
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL 
       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
@@ -3337,7 +3456,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       default:
        /* Don't allow initializations for incomplete types
           except for arrays which might be completed by the initialization.  */
-       if (TYPE_SIZE (TREE_TYPE (decl)) != 0)
+       if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
          {
            /* A complete type is ok if size is fixed.  */
 
@@ -3354,7 +3473,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
                   IDENTIFIER_POINTER (DECL_NAME (decl)));
            initialized = 0;
          }
-       else if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))) == 0)
+       else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          {
            error ("elements of array `%s' have incomplete type",
                   IDENTIFIER_POINTER (DECL_NAME (decl)));
@@ -3413,21 +3532,13 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
         (which may or may not happen).  */
       && DECL_RTL (tem) == 0)
     {
-      if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
+      if (COMPLETE_TYPE_P (TREE_TYPE (tem)))
        expand_decl (tem);
       else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
               && DECL_INITIAL (tem) != 0)
        expand_decl (tem);
     }
 
-  if (init_written)
-    {
-      /* When parsing and digesting the initializer,
-        use temporary storage.  Do this even if we will ignore the value.  */
-      if (current_binding_level == global_binding_level && debug_temp_inits)
-       temporary_allocation ();
-    }
-
   return tem;
 }
 
@@ -3443,7 +3554,6 @@ finish_decl (decl, init, asmspec_tree)
 {
   register tree type = TREE_TYPE (decl);
   int was_incomplete = (DECL_SIZE (decl) == 0);
-  int temporary = allocation_temporary_p ();
   char *asmspec = 0;
 
   /* If a name was specified, get the string.   */
@@ -3478,16 +3588,6 @@ finish_decl (decl, init, asmspec_tree)
        }
     }
 
-  /* Pop back to the obstack that is current for this binding level.
-     This is because MAXINDEX, rtl, etc. to be made below
-     must go in the permanent obstack.  But don't discard the
-     temporary data yet.  */
-  pop_obstacks ();
-#if 0 /* pop_obstacks was near the end; this is what was here.  */
-  if (current_binding_level == global_binding_level && temporary)
-    end_temporary_allocation ();
-#endif
-
   /* Deduce size of array from initialization, if not already known */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -3535,8 +3635,7 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == VAR_DECL)
     {
-      if (DECL_SIZE (decl) == 0
-         && TYPE_SIZE (TREE_TYPE (decl)) != 0)
+      if (DECL_SIZE (decl) == 0 && COMPLETE_TYPE_P (TREE_TYPE (decl)))
        layout_decl (decl, 0);
 
       if (DECL_SIZE (decl) == 0
@@ -3590,28 +3689,12 @@ finish_decl (decl, init, asmspec_tree)
 
   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
     {
-      if ((flag_traditional || TREE_PERMANENT (decl))
-         && allocation_temporary_p ())
-       {
-         push_obstacks_nochange ();
-         end_temporary_allocation ();
-         /* 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, asmspec,
-                                   (DECL_CONTEXT (decl) == 0
-                                    || TREE_ASM_WRITTEN (decl)),
-                                   0);
-         pop_obstacks ();
-       }
-      else
-       {
-         /* 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, asmspec,
-                                   (DECL_CONTEXT (decl) == 0
-                                    || TREE_ASM_WRITTEN (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, asmspec,
+                               (DECL_CONTEXT (decl) == 0
+                                || TREE_ASM_WRITTEN (decl)), 0);
+
       if (DECL_CONTEXT (decl) != 0)
        {
          /* Recompute the RTL of a local array now
@@ -3636,82 +3719,9 @@ 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);
-    }
-
-  /* ??? After 2.3, test (init != 0) instead of TREE_CODE.  */
-  /* This test used to include TREE_PERMANENT, however, we have the same
-     problem with initializers at the function level.  Such initializers get
-     saved until the end of the function on the momentary_obstack.  */
-  if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
-      && temporary
-      /* DECL_INITIAL is not defined in PARM_DECLs, since it shares
-        space with DECL_ARG_TYPE.  */
-      && TREE_CODE (decl) != PARM_DECL)
-    {
-      /* We need to remember that this array HAD an initialization,
-        but discard the actual temporary nodes,
-        since we can't have a permanent node keep pointing to them.  */
-      /* We make an exception for inline functions, since it's
-        normal for a local extern redeclaration of an inline function
-        to have a copy of the top-level decl's DECL_INLINE.  */
-      if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
-       {
-         /* If this is a const variable, then preserve the
-            initializer instead of discarding it so that we can optimize
-            references to it.  */
-         /* This test used to include TREE_STATIC, but this won't be set
-            for function level initializers.  */
-         if (TREE_READONLY (decl) || ITERATOR_P (decl))
-           {
-             preserve_initializer ();
-             /* Hack?  Set the permanent bit for something that is permanent,
-                but not on the permanent obstack, so as to convince
-                output_constant_def to make its rtl on the permanent
-                obstack.  */
-             TREE_PERMANENT (DECL_INITIAL (decl)) = 1;
-
-             /* The initializer and DECL must have the same (or equivalent
-                types), but if the initializer is a STRING_CST, its type
-                might not be on the right obstack, so copy the type
-                of DECL.  */
-             TREE_TYPE (DECL_INITIAL (decl)) = type;
-           }
-         else
-           DECL_INITIAL (decl) = error_mark_node;
-       }
-    }
-
-  /* If requested, warn about definitions of large data objects.  */
-
-  if (warn_larger_than
-      && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
-      && !DECL_EXTERNAL (decl))
-    {
-      register tree decl_size = DECL_SIZE (decl);
-
-      if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
-       {
-          unsigned units = TREE_INT_CST_LOW(decl_size) / BITS_PER_UNIT;
-
-         if (units > larger_than_size)
-           warning_with_decl (decl, "size of `%s' is %u bytes", units);
-       }
+      rest_of_decl_compilation (decl, NULL_PTR, DECL_CONTEXT (decl) == 0, 0);
     }
 
-#if 0
-  /* Resume permanent allocation, if not within a function.  */
-  /* The corresponding push_obstacks_nochange is in start_decl,
-     and in push_parm_decl and in grokfield.  */
-  pop_obstacks ();
-#endif
-
-  /* If we have gone back from temporary to permanent allocation,
-     actually free the temporary space that we no longer need.  */
-  if (temporary && !allocation_temporary_p ())
-    permanent_allocation (0);
-
   /* At the end of a declaration, throw away any variable type sizes
      of types defined inside that declaration.  There is no use
      computing them in the following function definition.  */
@@ -3744,9 +3754,6 @@ push_parm_decl (parm)
   /* Don't try computing parm sizes now -- wait till fn is called.  */
   immediate_size_expand = 0;
 
-  /* The corresponding pop_obstacks is in finish_decl.  */
-  push_obstacks_nochange ();
-
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
                         TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
   decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
@@ -3810,13 +3817,14 @@ complete_array_type (type, initial_value, do_default)
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
          tree elts = CONSTRUCTOR_ELTS (initial_value);
-         maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+         maxindex = build_int_2 (-1, -1);
          for (; elts; elts = TREE_CHAIN (elts))
            {
              if (TREE_PURPOSE (elts))
                maxindex = TREE_PURPOSE (elts);
              else
-               maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+               maxindex = fold (build (PLUS_EXPR, integer_type_node,
+                                       maxindex, integer_one_node));
            }
          maxindex = copy_node (maxindex);
        }
@@ -3915,11 +3923,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
 
-  push_obstacks_nochange ();
-
-  if (flag_traditional && allocation_temporary_p ())
-    end_temporary_allocation ();
-
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   {
@@ -4000,7 +4003,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                      error ("`long long long' is too long for GCC");
                    else
                      {
-                       if (pedantic && ! in_system_header && warn_long_long)
+                       if (pedantic && !flag_isoc99 && ! in_system_header
+                           && warn_long_long)
                          pedwarn ("ANSI C does not support `long long'");
                        longlong = 1;
                      }
@@ -4055,15 +4059,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                          | (1 << (int) RID_UNSIGNED))))
          /* Don't warn about typedef foo = bar.  */
          && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
-         && ! (in_system_header && ! allocation_temporary_p ()))
+         && ! in_system_header)
        {
-         /* Issue a warning if this is an ISO C 9x program or if -Wreturn-type
+         /* 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)
            warn_about_return_type = 1;
-         else if (warn_implicit_int || flag_isoc9x)
-           warning ("type defaults to `int' in declaration of `%s'", name);
+         else if (warn_implicit_int || flag_isoc99)
+           pedwarn_c99 ("type defaults to `int' in declaration of `%s'", name);
        }
 
       defaulted_int = 1;
@@ -4213,11 +4217,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
   volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
   inlinep = !! (specbits & (1 << (int) RID_INLINE));
-  if (constp > 1)
+  if (constp > 1 && ! flag_isoc99)
     pedwarn ("duplicate `const'");
-  if (restrictp > 1)
+  if (restrictp > 1 && ! flag_isoc99)
     pedwarn ("duplicate `restrict'");
-  if (volatilep > 1)
+  if (volatilep > 1 && ! flag_isoc99)
     pedwarn ("duplicate `volatile'");
   if (! flag_gen_aux_info && (TYPE_QUALS (type)))
     type = TYPE_MAIN_VARIANT (type);
@@ -4339,8 +4343,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        {
          register tree itype = NULL_TREE;
          register tree size = TREE_OPERAND (declarator, 1);
-         /* An uninitialized decl with `extern' is a reference.  */
-         int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
          /* The index is a signed object `sizetype' bits wide.  */
          tree index_type = signed_type (sizetype);
 
@@ -4348,7 +4350,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
          /* Check for some types that there cannot be arrays of.  */
 
-         if (TYPE_MAIN_VARIANT (type) == void_type_node)
+         if (VOID_TYPE_P (type))
            {
              error ("declaration of `%s' as array of voids", name);
              type = error_mark_node;
@@ -4366,12 +4368,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          if (type == error_mark_node)
            continue;
 
-         /* If this is a block level extern, it must live past the end
-            of the function so that we can check it against other extern
-            declarations (IDENTIFIER_LIMBO_VALUE).  */
-         if (extern_ref && allocation_temporary_p ())
-           end_temporary_allocation ();
-
          /* If size was specified, set ITYPE to a range-type for that size.
             Otherwise, ITYPE remains null.  finish_decl may figure it out
             from an initial value.  */
@@ -4442,7 +4438,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
         union incomplete (*foo)[4];  */
          /* Complain about arrays of incomplete types, except in typedefs.  */
 
-         if (TYPE_SIZE (type) == 0
+         if (!COMPLETE_TYPE_P (type)
              /* Avoid multiple warnings for nested array types.  */
              && TREE_CODE (type) != ARRAY_TYPE
              && !(specbits & (1 << (int) RID_TYPEDEF))
@@ -4476,8 +4472,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        }
       else if (TREE_CODE (declarator) == CALL_EXPR)
        {
-         int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
-                           || current_binding_level == global_binding_level);
          tree arg_types;
 
          /* Declaring a function type.
@@ -4507,12 +4501,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = double_type_node;
 #endif /* TRADITIONAL_RETURN_FLOAT */
 
-         /* If this is a block level extern, it must live past the end
-            of the function so that we can check it against other extern
-            declarations (IDENTIFIER_LIMBO_VALUE).  */
-         if (extern_ref && allocation_temporary_p ())
-           end_temporary_allocation ();
-
          /* Construct the function type and go to the next
             inner layer of declarator.  */
 
@@ -4522,17 +4510,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                    only for the CALL_EXPR
                                    closest to the identifier.  */
                                 && TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
-#if 0 /* This seems to be false.  We turn off temporary allocation
-        above in this function if -traditional.
-        And this code caused inconsistent results with prototypes:
-        callers would ignore them, and pass arguments wrong.  */
-
-         /* Omit the arg types if -traditional, since the arg types
-            and the list links might not be permanent.  */
-         type = build_function_type (type,
-                                     flag_traditional 
-                                     ? NULL_TREE : arg_types);
-#endif
          /* Type qualifiers before the return type of the function
             qualify the return type, not the function type.  */
          if (type_quals)
@@ -4598,11 +4575,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                      error ("invalid type modifier within pointer declarator");
                    }
                }
-             if (constp > 1)
+             if (constp > 1 && ! flag_isoc99)
                pedwarn ("duplicate `const'");
-             if (volatilep > 1)
+             if (volatilep > 1 && ! flag_isoc99)
                pedwarn ("duplicate `volatile'");
-             if (restrictp > 1)
+             if (restrictp > 1 && ! flag_isoc99)
                pedwarn ("duplicate `restrict'");
 
              type_quals = ((constp ? TYPE_QUAL_CONST : 0)
@@ -4622,7 +4599,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
-      && TYPE_SIZE (type)
+      && COMPLETE_TYPE_P (type)
       && TREE_OVERFLOW (TYPE_SIZE (type)))
     error ("size of array `%s' is too large", name);
 
@@ -4642,7 +4619,6 @@ 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;
-      pop_obstacks ();
       return decl;
     }
 
@@ -4673,7 +4649,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        pedwarn ("ANSI C forbids const or volatile function types");
       if (type_quals)
        type = c_build_qualified_type (type, type_quals);
-      pop_obstacks ();
       return type;
     }
 
@@ -4683,7 +4658,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
      We don't complain about parms either, but that is because
      a better error message can be made later.  */
 
-  if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM
+  if (VOID_TYPE_P (type) && decl_context != PARM
       && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
            && ((specbits & (1 << (int) RID_EXTERN))
                || (current_binding_level == global_binding_level
@@ -4758,7 +4733,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            error ("field `%s' declared as a function", name);
            type = build_pointer_type (type);
          }
-       else if (TREE_CODE (type) != ERROR_MARK && TYPE_SIZE (type) == 0)
+       else if (TREE_CODE (type) != ERROR_MARK
+                && !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
          {
            error ("field `%s' has incomplete type", name);
            type = error_mark_node;
@@ -4774,6 +4750,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 #endif
          }
        decl = build_decl (FIELD_DECL, declarator, type);
+       DECL_NONADDRESSABLE_P (decl) = bitfield;
+
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
       }
@@ -4800,12 +4778,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            && pedantic)
          pedwarn ("invalid storage class for function `%s'", name);
 
-       /* If this is a block level extern, it must live past the end
-          of the function so that we can check it against other
-          extern declarations (IDENTIFIER_LIMBO_VALUE).  */
-       if (extern_ref && allocation_temporary_p ())
-         end_temporary_allocation ();
-
        decl = build_decl (FUNCTION_DECL, declarator, type);
        decl = build_decl_attribute_variant (decl, decl_machine_attr);
 
@@ -4813,7 +4785,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn ("ANSI C forbids qualified function types");
 
        if (pedantic
-           && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
+           && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
            && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
            && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ANSI C forbids qualified void function return type");
@@ -4821,7 +4793,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        /* GNU C interprets a `volatile void' return type to indicate
           that the function does not return.  */
        if ((type_quals & TYPE_QUAL_VOLATILE)
-           && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
+           && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
          warning ("`noreturn' function returns non-void value");
 
        if (extern_ref)
@@ -4860,12 +4832,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 #endif
          }
 
-       /* If this is a block level extern, it must live past the end
-          of the function so that we can check it against other
-          extern declarations (IDENTIFIER_LIMBO_VALUE).  */
-       if (extern_ref && allocation_temporary_p ())
-         end_temporary_allocation ();
-
        decl = build_decl (VAR_DECL, declarator, type);
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -4911,8 +4877,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
       mark_addressable (decl);
 
-    pop_obstacks ();
-
     return decl;
   }
 }
@@ -4980,7 +4944,7 @@ grokparms (parms_info, funcdef_flag)
            {
              /* Barf if the parameter itself has an incomplete type.  */
              tree type = TREE_VALUE (typelt);
-             if (TYPE_SIZE (type) == 0)
+             if (!COMPLETE_TYPE_P (type))
                {
                  if (funcdef_flag && DECL_NAME (parm) != 0)
                    error ("parameter `%s' has incomplete type",
@@ -5002,7 +4966,7 @@ grokparms (parms_info, funcdef_flag)
                         || TREE_CODE (type) == REFERENCE_TYPE)
                    type = TREE_TYPE (type);
                  type = TYPE_MAIN_VARIANT (type);
-                 if (TYPE_SIZE (type) == 0)
+                 if (!COMPLETE_TYPE_P (type))
                    {
                      if (DECL_NAME (parm) != 0)
                        warning ("parameter `%s' points to incomplete type",
@@ -5015,19 +4979,6 @@ grokparms (parms_info, funcdef_flag)
              typelt = TREE_CHAIN (typelt);
            }
 
-      /* Allocate the list of types the way we allocate a type.  */
-      if (first_parm && ! TREE_PERMANENT (first_parm))
-       {
-         /* Construct a copy of the list of types
-            on the saveable obstack.  */
-         tree result = NULL;
-         for (typelt = first_parm; typelt; typelt = TREE_CHAIN (typelt))
-           result = saveable_tree_cons (NULL_TREE, TREE_VALUE (typelt),
-                                        result);
-         return nreverse (result);
-       }
-      else
-       /* The list we have is permanent already.  */
        return first_parm;
     }
 }
@@ -5054,16 +5005,24 @@ get_parm_info (void_at_end)
   tree new_parms = 0;
   tree order = current_binding_level->parm_order;
 
-  /* Just `void' (and no ellipsis) is special.  There are really no parms.  */
+  /* Just `void' (and no ellipsis) is special.  There are really no parms.
+     But if the `void' is qualified (by `const' or `volatile') or has a
+     storage class specifier (`register'), then the behavior is undefined;
+     by not counting it as the special case of `void' we will cause an
+     error later.  Typedefs for `void' are OK (see DR#157).
+  */
   if (void_at_end && parms != 0
       && TREE_CHAIN (parms) == 0
-      && TYPE_MAIN_VARIANT (TREE_TYPE (parms)) == void_type_node
+      && VOID_TYPE_P (TREE_TYPE (parms))
+      && ! TREE_THIS_VOLATILE (parms)
+      && ! TREE_READONLY (parms)
+      && ! DECL_REGISTER (parms)
       && DECL_NAME (parms) == 0)
     {
       parms = NULL_TREE;
       storedecls (NULL_TREE);
-      return saveable_tree_cons (NULL_TREE, NULL_TREE,
-                                saveable_tree_cons (NULL_TREE, void_type_node, NULL_TREE));
+      return tree_cons (NULL_TREE, NULL_TREE,
+                       tree_cons (NULL_TREE, void_type_node, NULL_TREE));
     }
 
   /* Extract enumerator values and other non-parms declared with the parms.
@@ -5117,8 +5076,8 @@ get_parm_info (void_at_end)
            && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
          DECL_ARG_TYPE (decl) = integer_type_node;
 
-       types = saveable_tree_cons (NULL_TREE, TREE_TYPE (decl), types);
-       if (TYPE_MAIN_VARIANT (TREE_VALUE (types)) == void_type_node && ! erred
+       types = tree_cons (NULL_TREE, TREE_TYPE (decl), types);
+       if (VOID_TYPE_P (TREE_VALUE (types)) && ! erred
            && DECL_NAME (decl) == 0)
          {
            error ("`void' in parameter list must be the entire list");
@@ -5127,10 +5086,10 @@ get_parm_info (void_at_end)
       }
 
   if (void_at_end)
-    return saveable_tree_cons (new_parms, tags,
-                              nreverse (saveable_tree_cons (NULL_TREE, void_type_node, types)));
+    return tree_cons (new_parms, tags,
+                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
 
-  return saveable_tree_cons (new_parms, tags, nreverse (types));
+  return tree_cons (new_parms, tags, nreverse (types));
 }
 
 /* At end of parameter list, warn about any struct, union or enum tags
@@ -5156,11 +5115,15 @@ parmlist_tags_warning ()
                  : "enum"),
                 IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
       else
-       warning ("anonymous %s declared inside parameter list",
-                (code == RECORD_TYPE ? "struct"
-                 : code == UNION_TYPE ? "union"
-                 : "enum"));
-
+        {
+          /* For translation these need to be seperate warnings */
+          if (code == RECORD_TYPE)
+           warning ("anonymous struct declared inside parameter list");
+         else if (code == UNION_TYPE)
+           warning ("anonymous union declared inside parameter list");
+         else    
+           warning ("anonymous enum declared inside parameter list");
+       }
       if (! already)
        {
          warning ("its scope is only this definition or declaration, which is probably not what you want.");
@@ -5177,8 +5140,6 @@ xref_tag (code, name)
      enum tree_code code;
      tree name;
 {
-  int temporary = allocation_temporary_p ();
-
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
 
@@ -5190,11 +5151,6 @@ xref_tag (code, name)
   if (ref)
     return ref;
 
-  push_obstacks_nochange ();
-
-  if (current_binding_level == global_binding_level && temporary)
-    end_temporary_allocation ();
-
   /* If no such tag is yet defined, create a forward-reference node
      and record it as the "definition".
      When a real declaration of this type is found,
@@ -5210,6 +5166,7 @@ xref_tag (code, name)
         to avoid crashing if it does not get defined.  */
       TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
       TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+      TYPE_USER_ALIGN (ref) = 0;
       TREE_UNSIGNED (ref) = 1;
       TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
       TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
@@ -5218,17 +5175,12 @@ xref_tag (code, name)
 
   pushtag (name, ref);
 
-  pop_obstacks ();
-
   return ref;
 }
 \f
 /* Make sure that the tag NAME is defined *in the current binding level*
    at least as a forward reference.
-   CODE says which kind of tag NAME ought to be.
-
-   We also do a push_obstacks_nochange
-   whose matching pop is in finish_struct.  */
+   CODE says which kind of tag NAME ought to be.  */
 
 tree
 start_struct (code, name)
@@ -5240,10 +5192,6 @@ start_struct (code, name)
 
   register tree ref = 0;
 
-  push_obstacks_nochange ();
-  if (current_binding_level == global_binding_level)
-    end_temporary_allocation ();
-
   if (name != 0)
     ref = lookup_tag (code, name, current_binding_level, 1);
   if (ref && TREE_CODE (ref) == code)
@@ -5283,9 +5231,6 @@ grokfield (filename, line, declarator, declspecs, width)
 {
   tree value;
 
-  /* The corresponding pop_obstacks is in finish_decl.  */
-  push_obstacks_nochange ();
-
   value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
 
   finish_decl (value, NULL_TREE, NULL_TREE);
@@ -5297,9 +5242,7 @@ grokfield (filename, line, declarator, declspecs, width)
 \f
 /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
    FIELDLIST is a chain of FIELD_DECL nodes for the fields.
-   ATTRIBUTES are attributes to be applied to the structure.
-
-   We also do a pop_obstacks to match the push in start_struct.  */
+   ATTRIBUTES are attributes to be applied to the structure.  */
 
 tree
 finish_struct (t, fieldlist, attributes)
@@ -5308,7 +5251,6 @@ finish_struct (t, fieldlist, attributes)
      tree attributes;
 {
   register tree x;
-  int old_momentary;
   int toplevel = global_binding_level == current_binding_level;
 
   /* If this type was previously laid out as a forward reference,
@@ -5325,14 +5267,12 @@ finish_struct (t, fieldlist, attributes)
       {
        if (pedantic)
          pedwarn ("%s defined inside parms",
-                  TREE_CODE (t) == UNION_TYPE ? "union" : "structure");
+                  TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
        else if (! flag_traditional)
          warning ("%s defined inside parms",
-                  TREE_CODE (t) == UNION_TYPE ? "union" : "structure");
+                  TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
       }
 
-  old_momentary = suspend_momentary ();
-
   if (pedantic)
     {
       for (x = fieldlist; x; x = TREE_CHAIN (x))
@@ -5340,15 +5280,13 @@ finish_struct (t, fieldlist, attributes)
          break;
 
       if (x == 0)
-       pedwarn ("%s has no %smembers",
-                TREE_CODE (t) == UNION_TYPE ? "union" : "struct",
-                fieldlist ? "named " : "");
+       pedwarn ("%s has no %s",
+                TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
+                fieldlist ? _("named members") : _("members"));
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
-     Also process specified field sizes.
-     Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
-     The specified size is found in the DECL_INITIAL.
+     Also process specified field sizes,m which is found in the DECL_INITIAL.
      Store 0 there, except for ": 0" fields (so we can find them
      and delete them, below).  */
 
@@ -5356,7 +5294,6 @@ finish_struct (t, fieldlist, attributes)
     {
       DECL_CONTEXT (x) = t;
       DECL_PACKED (x) |= TYPE_PACKED (t);
-      DECL_FIELD_SIZE (x) = 0;
 
       /* If any field is const, the structure type is pseudo-const.  */
       if (TREE_READONLY (x))
@@ -5395,7 +5332,8 @@ finish_struct (t, fieldlist, attributes)
            constant_expression_warning (DECL_INITIAL (x));
          else
            {
-             error_with_decl (x, "bit-field `%s' width not an integer constant");
+             error_with_decl (x,
+                              "bit-field `%s' width not an integer constant");
              DECL_INITIAL (x) = NULL;
            }
        }
@@ -5408,6 +5346,7 @@ finish_struct (t, fieldlist, attributes)
          error_with_decl (x, "bit-field `%s' has invalid type");
          DECL_INITIAL (x) = NULL;
        }
+
       if (DECL_INITIAL (x) && pedantic
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
@@ -5417,69 +5356,67 @@ finish_struct (t, fieldlist, attributes)
                   == TYPE_PRECISION (integer_type_node))))
        pedwarn_with_decl (x, "bit-field `%s' type invalid in ANSI C");
 
-      /* Detect and ignore out of range field width.  */
+      /* Detect and ignore out of range field width and process valid
+        field widths.  */
       if (DECL_INITIAL (x))
        {
-         unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (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), 
+                                        TYPE_PRECISION (TREE_TYPE (x))))
+           pedwarn_with_decl (x, "width of `%s' exceeds its type");
+         else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
+           error_with_decl (x, "zero width for bit-field `%s'");
+         else
            {
-             DECL_INITIAL (x) = NULL;
-             error_with_decl (x, "negative width in bit-field `%s'");
-           }
-         else if (TREE_INT_CST_HIGH (DECL_INITIAL (x)) != 0
-                  || width > TYPE_PRECISION (TREE_TYPE (x)))
-           {
-             DECL_INITIAL (x) = NULL;
-             pedwarn_with_decl (x, "width of `%s' exceeds its type");
-           }
-         else if (width == 0 && DECL_NAME (x) != 0)
-           {
-             error_with_decl (x, "zero width for bit-field `%s'");
-             DECL_INITIAL (x) = NULL;
-           }
-       }
-
-      /* Process valid field width.  */
-      if (DECL_INITIAL (x))
-       {
-         register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
-         if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
-             && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
-                                        TREE_UNSIGNED (TREE_TYPE (x)))
-                 || width < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
-                                           TREE_UNSIGNED (TREE_TYPE (x)))))
-           warning_with_decl (x, "`%s' is narrower than values of its type");
-
-         DECL_FIELD_SIZE (x) = width;
-         DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
-         DECL_INITIAL (x) = NULL;
-
-         if (width == 0)
-           {
-             /* field size 0 => force desired amount of alignment.  */
+             /* 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));
+
+             if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+                 && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
+                                            TREE_UNSIGNED (TREE_TYPE (x)))
+                     || (width
+                         < min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
+                                          TREE_UNSIGNED (TREE_TYPE (x))))))
+               warning_with_decl (x,
+                                  "`%s' is narrower than values of its type");
+
+             DECL_SIZE (x) = bitsize_int (width);
+             DECL_BIT_FIELD (x) = DECL_C_BIT_FIELD (x) = 1;
+
+             if (width == 0)
+               {
+                 /* field size 0 => force desired amount of alignment.  */
 #ifdef EMPTY_FIELD_BOUNDARY
-             DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
+                 DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
 #endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-             if (PCC_BITFIELD_TYPE_MATTERS)
-               DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
-                                     TYPE_ALIGN (TREE_TYPE (x)));
+                 if (PCC_BITFIELD_TYPE_MATTERS)
+                   {
+                     DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+                                           TYPE_ALIGN (TREE_TYPE (x)));
+                     DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
+                   }
 #endif
+               }
            }
        }
+
       else if (TREE_TYPE (x) != error_mark_node)
        {
          unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
-                          : TYPE_ALIGN (TREE_TYPE (x)));
+                                   : TYPE_ALIGN (TREE_TYPE (x)));
+
          /* Non-bit-fields are aligned for their type, except packed
             fields which require only BITS_PER_UNIT alignment.  */
          DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
+         if (! DECL_PACKED (x))
+           DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
        }
-    }
 
-  /* Now DECL_INITIAL is null on all members.  */
+      DECL_INITIAL (x) = 0;
+    }
 
   /* Delete all duplicate fields from the fieldlist */
   for (x = fieldlist; x && TREE_CHAIN (x);)
@@ -5533,6 +5470,7 @@ finish_struct (t, fieldlist, attributes)
       TYPE_FIELDS (x) = TYPE_FIELDS (t);
       TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
       TYPE_ALIGN (x) = TYPE_ALIGN (t);
+      TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
     }
 
   /* If this was supposed to be a transparent union, but we can't
@@ -5564,7 +5502,7 @@ finish_struct (t, fieldlist, attributes)
                expand_decl (decl);
              --current_binding_level->n_incomplete;
            }
-         else if (TYPE_SIZE (TREE_TYPE (decl)) == 0
+         else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
                   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
            {
              tree element = TREE_TYPE (decl);
@@ -5576,14 +5514,9 @@ finish_struct (t, fieldlist, attributes)
        }
     }
 
-  resume_momentary (old_momentary);
-
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (t, toplevel);
 
-  /* The matching push is in start_struct.  */
-  pop_obstacks ();
-
   return t;
 }
 
@@ -5617,12 +5550,6 @@ start_enum (name)
   if (name != 0)
     enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
 
-  /* The corresponding pop_obstacks is in finish_enum.  */
-  push_obstacks_nochange ();
-  /* If these symbols and types are global, make them permanent.  */
-  if (current_binding_level == global_binding_level)
-    end_temporary_allocation ();
-
   if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
     {
       enumtype = make_node (ENUMERAL_TYPE);
@@ -5663,7 +5590,7 @@ finish_enum (enumtype, values, attributes)
      tree attributes;
 {
   register tree pair, tem;
-  tree minnode = 0, maxnode = 0;
+  tree minnode = 0, maxnode = 0, enum_value_type;
   int precision, unsign;
   int toplevel = (global_binding_level == current_binding_level);
 
@@ -5704,6 +5631,11 @@ finish_enum (enumtype, values, attributes)
       precision = TYPE_PRECISION (long_long_integer_type_node);
     }
 
+  if (precision == TYPE_PRECISION (integer_type_node))
+    enum_value_type = type_for_size (precision, 0);
+  else
+    enum_value_type = enumtype;
+
   TYPE_MIN_VALUE (enumtype) = minnode;
   TYPE_MAX_VALUE (enumtype) = maxnode;
   TYPE_PRECISION (enumtype) = precision;
@@ -5726,9 +5658,22 @@ finish_enum (enumtype, values, attributes)
 
          TREE_TYPE (enu) = enumtype;
          DECL_SIZE (enu) = TYPE_SIZE (enumtype);
+         DECL_SIZE_UNIT (enu) = TYPE_SIZE_UNIT (enumtype);
          DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
+         DECL_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype);
          DECL_MODE (enu) = TYPE_MODE (enumtype);
-         DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
+
+         /* The ISO C Standard mandates enumerators to have type int,
+            even though the underlying type of an enum type is
+            unspecified.  Here we convert any enumerators that fit in
+            an int to type int, to avoid promotions to unsigned types
+            when comparing integers with enumerators that fit in the
+            int range.  When -pedantic is given, build_enumerator()
+            would have already taken care of those that don't fit.  */
+         if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
+           DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
+         else
+           DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
 
          TREE_PURPOSE (pair) = DECL_NAME (enu);
          TREE_VALUE (pair) = DECL_INITIAL (enu);
@@ -5750,15 +5695,13 @@ finish_enum (enumtype, values, attributes)
       TYPE_MODE (tem) = TYPE_MODE (enumtype);
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+      TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
       TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
     }
 
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (enumtype, toplevel);
 
-  /* This matches a push in start_enum.  */
-  pop_obstacks ();
-
   return enumtype;
 }
 
@@ -5807,7 +5750,7 @@ build_enumerator (name, value)
   if (pedantic && ! int_fits_type_p (value, integer_type_node))
     {
       pedwarn ("ANSI C restricts enumerator values to range of `int'");
-      value = integer_zero_node;
+      value = convert (integer_type_node, value);
     }
 
   /* Set basis for default for next value.  */
@@ -5824,11 +5767,10 @@ build_enumerator (name, value)
                         && TREE_UNSIGNED (type)));
 
   decl = build_decl (CONST_DECL, name, type);
-  DECL_INITIAL (decl) = value;
-  TREE_TYPE (value) = type;
+  DECL_INITIAL (decl) = convert (type, value);
   pushdecl (decl);
 
-  return saveable_tree_cons (decl, value, NULL_TREE);
+  return tree_cons (decl, value, NULL_TREE);
 }
 \f
 /* Create the FUNCTION_DECL for a function definition.
@@ -5841,14 +5783,11 @@ build_enumerator (name, value)
 
    Returns 1 on success.  If the DECLARATOR is not suitable for a function
    (it defines a datum instead), we return 0, which tells
-   yyparse to report a parse error.
-
-   NESTED is nonzero for a function nested within another function.  */
+   yyparse to report a parse error.  */
 
 int
-start_function (declspecs, declarator, prefix_attributes, attributes, nested)
+start_function (declspecs, declarator, prefix_attributes, attributes)
      tree declarator, declspecs, prefix_attributes, attributes;
-     int nested;
 {
   tree decl1, old_decl;
   tree restype;
@@ -5879,9 +5818,9 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
 
   announce_function (decl1);
 
-  if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl1))) == 0)
+  if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
     {
-      error ("return-type is an incomplete type");
+      error ("return type is an incomplete type");
       /* Make it return void instead.  */
       TREE_TYPE (decl1)
        = build_function_type (void_type_node,
@@ -5889,7 +5828,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
     }
 
   if (warn_about_return_type)
-    warning ("return-type defaults to `int'");
+    pedwarn_c99 ("return type defaults to `int'");
 
   /* Save the parm names or decls from this function's declarator
      where store_parm_decls will find them.  */
@@ -6060,11 +5999,6 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   DECL_RESULT (current_function_decl)
     = build_decl (RESULT_DECL, NULL_TREE, restype);
 
-  if (!nested)
-    /* Allocate further tree nodes temporarily during compilation
-       of this function only.  */
-    temporary_allocation ();
-
   /* If this fcn was already referenced via a block-scope `extern' decl
      (or an implicit decl), propagate certain information about the usage.  */
   if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
@@ -6155,7 +6089,8 @@ store_parm_decls ()
            {
              if (DECL_NAME (parm) == 0)
                error_with_decl (parm, "parameter name omitted");
-             else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
+             else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
+                      && VOID_TYPE_P (TREE_TYPE (parm)))
                {
                  error_with_decl (parm, "parameter `%s' declared void");
                  /* Change the type to error_mark_node so this parameter
@@ -6222,8 +6157,10 @@ store_parm_decls ()
         Associate decls with the names and store the decls
         into the TREE_PURPOSE slots.  */
 
+      /* We use DECL_WEAK as a flag to show which parameters have been
+        seen already since it is not used on PARM_DECL or CONST_DECL.  */
       for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-       DECL_RESULT (parm) = 0;
+       DECL_WEAK (parm) = 0;
 
       for (parm = specparms; parm; parm = TREE_CHAIN (parm))
        {
@@ -6231,7 +6168,8 @@ store_parm_decls ()
 
          if (TREE_VALUE (parm) == 0)
            {
-             error_with_decl (fndecl, "parameter name missing from parameter list");
+             error_with_decl (fndecl,
+                              "parameter name missing from parameter list");
              TREE_PURPOSE (parm) = 0;
              continue;
            }
@@ -6248,14 +6186,14 @@ store_parm_decls ()
 
          /* If declaration already marked, we have a duplicate name.
             Complain, and don't use this decl twice.   */
-         if (found && DECL_RESULT (found) != 0)
+         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 && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
+         if (found && VOID_TYPE_P (TREE_TYPE (found)))
            {
              error_with_decl (found, "parameter `%s' declared void");
              TREE_TYPE (found) = integer_type_node;
@@ -6280,17 +6218,17 @@ store_parm_decls ()
              DECL_ARG_TYPE (found) = TREE_TYPE (found);
              DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
              DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
-             if (extra_warnings)
+             if (flag_isoc99)
+               pedwarn_with_decl (found, "type of `%s' defaults to `int'");
+             else if (extra_warnings)
                warning_with_decl (found, "type of `%s' defaults to `int'");
              pushdecl (found);
            }
 
          TREE_PURPOSE (parm) = found;
 
-         /* Mark this decl as "already found" -- see test, above.
-            It is safe to use DECL_RESULT for this
-            since it is not used in PARM_DECLs or CONST_DECLs.  */
-         DECL_RESULT (found) = error_mark_node;
+         /* Mark this decl as "already found" */
+         DECL_WEAK (found) = 1;
        }
 
       /* Put anything which is on the parmdecls chain and which is
@@ -6310,13 +6248,13 @@ store_parm_decls ()
          else
            {
              /* Complain about args with incomplete types.  */
-             if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+             if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
                {
                  error_with_decl (parm, "parameter `%s' has incomplete type");
                  TREE_TYPE (parm) = error_mark_node;
                }
 
-             if (DECL_RESULT (parm) == 0)
+             if (! DECL_WEAK (parm))
                {
                  error_with_decl (parm,
                                   "declaration for parameter `%s' but no such parameter");
@@ -6428,15 +6366,14 @@ store_parm_decls ()
 
          for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
            {
-             type = perm_tree_cons (NULL_TREE, DECL_ARG_TYPE (parm),
-                                    NULL_TREE);
+             type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
              if (last)
                TREE_CHAIN (last) = type;
              else
                actual = type;
              last = type;
            }
-         type = perm_tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+         type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
          if (last)
            TREE_CHAIN (last) = type;
          else
@@ -6533,7 +6470,7 @@ combine_parm_decls (specparms, parmlist, void_at_end)
   tree types = 0;
 
   for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-    DECL_RESULT (parm) = 0;
+    DECL_WEAK (parm) = 0;
 
   for (parm = specparms; parm; parm = TREE_CHAIN (parm))
     {
@@ -6549,14 +6486,14 @@ combine_parm_decls (specparms, parmlist, void_at_end)
 
       /* If declaration already marked, we have a duplicate name.
         Complain, and don't use this decl twice.   */
-      if (found && DECL_RESULT (found) != 0)
+      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 && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == void_type_node)
+      if (found && VOID_TYPE_P (TREE_TYPE (found)))
        {
          error_with_decl (found, "parameter `%s' declared void");
          TREE_TYPE (found) = integer_type_node;
@@ -6587,10 +6524,8 @@ combine_parm_decls (specparms, parmlist, void_at_end)
 
       TREE_PURPOSE (parm) = found;
 
-      /* Mark this decl as "already found" -- see test, above.
-        It is safe to use DECL_RESULT for this
-        since it is not used in PARM_DECLs or CONST_DECLs.  */
-      DECL_RESULT (found) = error_mark_node;
+      /* Mark this decl as "already found".  */
+      DECL_WEAK (found) = 1;
     }
 
   /* Complain about any actual PARM_DECLs not matched with any names.  */
@@ -6601,13 +6536,13 @@ combine_parm_decls (specparms, parmlist, void_at_end)
       TREE_CHAIN (parm) = 0;
 
       /* Complain about args with incomplete types.  */
-      if (TYPE_SIZE (TREE_TYPE (parm)) == 0)
+      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
          error_with_decl (parm, "parameter `%s' has incomplete type");
          TREE_TYPE (parm) = error_mark_node;
        }
 
-      if (DECL_RESULT (parm) == 0)
+      if (! DECL_WEAK (parm))
        {
          error_with_decl (parm,
                           "declaration for parameter `%s' but no such parameter");
@@ -6639,17 +6574,15 @@ combine_parm_decls (specparms, parmlist, void_at_end)
          last = TREE_PURPOSE (parm);
          TREE_CHAIN (last) = 0;
 
-         types = saveable_tree_cons (NULL_TREE, TREE_TYPE (parm), types);
+         types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
        }
   }
   
   if (void_at_end)
-    return saveable_tree_cons (parmdecls, nonparms,
-                              nreverse (saveable_tree_cons (NULL_TREE,
-                                                            void_type_node,
-                                                            types)));
+    return tree_cons (parmdecls, nonparms,
+                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
 
-  return saveable_tree_cons (parmdecls, nonparms, nreverse (types));
+  return tree_cons (parmdecls, nonparms, nreverse (types));
 }
 \f
 /* Finish up a function declaration and compile that function
@@ -6684,7 +6617,8 @@ finish_function (nested)
       setjmp_protect_args ();
     }
 
-  if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main"))
+  if (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
+      && flag_hosted)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
          != integer_type_node)
@@ -6699,6 +6633,9 @@ finish_function (nested)
 #ifdef DEFAULT_MAIN_RETURN
          /* Make it so that `main' always returns success by default.  */
          DEFAULT_MAIN_RETURN;
+#else
+         if (flag_isoc99)
+           c_expand_return (integer_zero_node);
 #endif
        }
     }
@@ -6711,14 +6648,14 @@ finish_function (nested)
 
   /* If this is a nested function, protect the local variables in the stack
      above us from being collected while we're compiling this function.  */
-  if (ggc_p && nested)
+  if (nested)
     ggc_push_context ();
 
   /* Run the optimizers and output the assembler code for this function.  */
   rest_of_compilation (fndecl);
 
   /* Undo the GC context switch.  */
-  if (ggc_p && nested)
+  if (nested)
     ggc_pop_context ();
 
   current_function_returns_null |= can_reach_end;
@@ -6732,7 +6669,7 @@ finish_function (nested)
   if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
     warning ("`noreturn' function does return");
   else if (warn_return_type && can_reach_end
-          && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
+          && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
     /* If this function returns non-void and control can drop through,
        complain.  */
     warning ("control reaches end of non-void function");
@@ -6748,40 +6685,36 @@ finish_function (nested)
 
   if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
     {
-      register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+      tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
 
-      if (ret_type)
+      if (ret_type && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
+         && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
+                                  larger_than_size))
        {
-         register tree ret_type_size = TYPE_SIZE (ret_type);
-
-         if (TREE_CODE (ret_type_size) == INTEGER_CST)
-           {
-             unsigned units
-               = TREE_INT_CST_LOW (ret_type_size) / BITS_PER_UNIT;
+         unsigned int size_as_int
+           = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
-             if (units > larger_than_size)
-               warning_with_decl (fndecl,
-                                  "size of return value of `%s' is %u bytes",
-                                  units);
-           }
+         if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
+           warning_with_decl (fndecl,
+                              "size of return value of `%s' is %u bytes",
+                              size_as_int);
+         else
+           warning_with_decl (fndecl,
+                      "size of return value of `%s' is larger than %d bytes",
+                              larger_than_size);
        }
     }
 
-  /* Free all the tree nodes making up this function.  */
-  /* Switch back to allocating nodes permanently
-     until we start another function.  */
-  if (! nested)
-    permanent_allocation (1);
-
   if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
     {
-      /* Stop pointing to the local nodes about to be freed.  */
-      /* But DECL_INITIAL must remain nonzero so we know this
-        was an actual function definition.  */
-      /* For a nested function, this is done in pop_c_function_context.  */
-      /* If rest_of_compilation set this to 0, leave it 0.  */
+      /* Stop pointing to the local nodes about to be freed. 
+        But DECL_INITIAL must remain nonzero so we know this
+        was an actual function definition. 
+        For a nested function, this is done in pop_c_function_context.
+        If rest_of_compilation set this to 0, leave it 0.  */
       if (DECL_INITIAL (fndecl) != 0)
        DECL_INITIAL (fndecl) = error_mark_node;
+
       DECL_ARGUMENTS (fndecl) = 0;
     }
 
@@ -6789,7 +6722,7 @@ finish_function (nested)
     {
 #ifndef ASM_OUTPUT_CONSTRUCTOR
       if (! flag_gnu_linker)
-       static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
       else
 #endif
        assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))); 
@@ -6799,7 +6732,7 @@ finish_function (nested)
     {
 #ifndef ASM_OUTPUT_DESTRUCTOR
       if (! flag_gnu_linker)
-       static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
       else
 #endif
        assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
@@ -6937,3 +6870,125 @@ lang_mark_tree (t)
   else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
     ggc_mark (TYPE_LANG_SPECIFIC (t));
 }
+
+/* The functions below are required for functionality of doing
+   function at once processing in the C front end. Currently these
+   functions are not called from anywhere in the C front end, but as
+   these changes continue, that will change. */
+
+/* Returns non-zero if the current statement is a full expression,
+   i.e. temporaries created during that statement should be destroyed
+   at the end of the statement.  */
+
+int
+stmts_are_full_exprs_p ()
+{
+  return 0;
+}
+
+/* Nonzero if TYPE is an anonymous union or struct type.  Always 0 in
+   C. */
+
+int 
+anon_aggr_type_p (node)
+     tree node ATTRIBUTE_UNUSED;
+{
+  return 0;
+}
+
+/* One if we have already declared __FUNCTION__ (and related
+   variables) in the current function.  Two if we are in the process
+   of doing so.  */
+
+int
+current_function_name_declared ()
+{
+  abort ();
+  return 0;
+}
+
+/* Code to generate the RTL for a case label in C. */
+
+void
+do_case (low_value, high_value)
+     tree low_value;
+     tree high_value;
+{
+  tree value1 = NULL_TREE, value2 = NULL_TREE, label;
+
+  if (low_value != NULL_TREE)
+    value1 = check_case_value (low_value);
+  if (high_value != NULL_TREE)
+    value2 = check_case_value (high_value);
+
+  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+  
+  if (pedantic && (high_value != NULL_TREE))
+    pedwarn ("ANSI C forbids case ranges");
+
+  if (value1 != error_mark_node && value2 != error_mark_node)
+    {
+      tree duplicate;
+      int success;
+      
+      if (high_value == NULL_TREE && value1 != NULL_TREE &&
+         pedantic && ! INTEGRAL_TYPE_P (TREE_TYPE (value1)))
+       pedwarn ("label must have integral type in ANSI C");
+      
+      if (low_value == NULL_TREE)
+       success = pushcase (NULL_TREE, 0, label, &duplicate);
+      else if (high_value == NULL_TREE)
+       success = pushcase (value1, convert_and_check, label,
+                           &duplicate);
+      else
+       success = pushcase_range (value1, value2, convert_and_check,
+                                 label, &duplicate);
+      
+      if (success == 1)
+       {
+         if (low_value == NULL_TREE)
+           error ("default label not within a switch statement");
+         else
+           error ("case label not within a switch statement");
+       }
+      else if (success == 2) {
+       if (low_value == NULL_TREE) 
+         {
+           error ("multiple default labels in one switch");
+           error_with_decl (duplicate, "this is the first default label");
+         }
+       else
+         error ("dupicate case value");
+       if (high_value != NULL_TREE)
+         error_with_decl (duplicate, "this is the first entry for that value");
+      }
+      else if (low_value != NULL_TREE) 
+       {
+         if (success == 3)
+           warning ("case value out of range");
+         else if (success == 5)
+           error ("case label within scope of cleanup or variable array");
+       }
+    }
+}
+
+/* Language specific handler of tree nodes used when generating RTL
+   from a tree. */
+
+tree
+lang_expand_stmt (t)
+     tree t ATTRIBUTE_UNUSED;
+{
+  abort ();
+  return NULL_TREE;
+}
+
+/* Accessor to set the 'current_function_name_declared' flag. */
+
+void
+set_current_function_name_declared (i)
+     int i ATTRIBUTE_UNUSED;
+{
+  abort ();
+}
+