OSDN Git Service

(finish_decl): If asmspec_tree, clear DECL_BUILT_IN for function and
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 15da5ba..a7cd30e 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -128,6 +128,11 @@ tree float_type_node;
 tree double_type_node;
 tree long_double_type_node;
 
+tree complex_integer_type_node;
+tree complex_float_type_node;
+tree complex_double_type_node;
+tree complex_long_double_type_node;
+
 tree intQI_type_node;
 tree intHI_type_node;
 tree intSI_type_node;
@@ -203,7 +208,10 @@ char *pending_invalid_xref_file;
 int pending_invalid_xref_line;
 
 /* While defining an enum type, this is 1 plus the last enumerator
-   constant value.  */
+   constant value.  Note that will do not have to save this or `enum_overflow'
+   around nested function definition since such a definition could only
+   occur in an enum value expression and we don't use these variables in
+   that case.  */
 
 static tree enum_next_value;
 
@@ -230,6 +238,11 @@ static tree current_function_parms;
 /* Similar, for last_function_parm_tags.  */
 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 int current_function_prototype_line;
+
 /* 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.  */
@@ -392,7 +405,7 @@ void shadow_tag_warned ();
 
 static tree lookup_tag ();
 static tree lookup_tag_reverse ();
-static tree lookup_name_current_level ();
+tree lookup_name_current_level ();
 static char *redeclaration_error_message ();
 static void layout_array_type ();
 \f
@@ -424,6 +437,10 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
+/* Nonzero means to allow single precision math even if we're generally
+   being traditional. */
+int flag_allow_single_precision = 0;
+
 /* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
 
 int flag_signed_bitfields = 1;
@@ -467,6 +484,11 @@ int warn_strict_prototypes;
 
 int warn_missing_prototypes;
 
+/* Nonzero means warn for any global function def
+   without separate previous decl.  */
+
+int warn_missing_declarations;
+
 /* Nonzero means warn about multiple (redundant) decls for the same single
    variable or function.  */
 
@@ -524,12 +546,22 @@ c_decode_option (p)
       dollars_in_ident = 1;
 #endif
     }
+  else if (!strcmp (p, "-fallow-single-precision"))
+    flag_allow_single_precision = 1;
   else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
     {
       flag_traditional = 0;
       flag_writable_strings = 0;
       dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1;
     }
+  else if (!strcmp (p, "-fdollars-in-identifiers"))
+    {
+#if DOLLARS_IN_IDENTIFIERS > 0
+      dollars_in_ident = 1;
+#endif
+    }
+  else if (!strcmp (p, "-fnodollars-in-identifiers"))
+    dollars_in_ident = 0;
   else if (!strcmp (p, "-fsigned-char"))
     flag_signed_char = 1;
   else if (!strcmp (p, "-funsigned-char"))
@@ -600,6 +632,10 @@ c_decode_option (p)
     warn_missing_prototypes = 1;
   else if (!strcmp (p, "-Wno-missing-prototypes"))
     warn_missing_prototypes = 0;
+  else if (!strcmp (p, "-Wmissing-declarations"))
+    warn_missing_declarations = 1;
+  else if (!strcmp (p, "-Wno-missing-declarations"))
+    warn_missing_declarations = 0;
   else if (!strcmp (p, "-Wredundant-decls"))
     warn_redundant_decls = 1;
   else if (!strcmp (p, "-Wno-redundant-decls"))
@@ -678,12 +714,18 @@ c_decode_option (p)
 /* Hooks for print_node.  */
 
 void
-print_lang_decl ()
+print_lang_decl (file, node, indent)
+     FILE *file;
+     tree node;
+     int indent;
 {
 }
 
 void
-print_lang_type ()
+print_lang_type (file, node, indent)
+     FILE *file;
+     tree node;
+     int indent;
 {
 }
 
@@ -701,6 +743,27 @@ print_lang_identifier (file, node, indent)
   print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
 }
 \f
+/* Hook called at end of compilation to assume 1 elt
+   for a top-level array decl that wasn't complete before.  */
+   
+void
+finish_incomplete_decl (decl)
+     tree decl;
+{
+  if (TREE_CODE (decl) == VAR_DECL && TREE_TYPE (decl) != error_mark_node)
+    {
+      tree type = TREE_TYPE (decl);
+      if (TREE_CODE (type) == ARRAY_TYPE
+         && TYPE_DOMAIN (type) == 0
+         && TREE_CODE (decl) != TYPE_DECL)
+       {
+         complete_array_type (type, NULL_TREE, 1);
+
+         layout_decl (decl, 0);
+       }
+    }
+}
+\f
 /* Create a new `struct binding_level'.  */
 
 static
@@ -892,7 +955,11 @@ poplevel (keep, reverse, functionbody)
        if (DECL_ABSTRACT_ORIGIN (decl) != 0)
          TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
        else
-         output_inline_function (decl);
+         {
+           push_function_context ();
+           output_inline_function (decl);
+           pop_function_context ();
+         }
       }
 
   /* If there were any declarations or structure tags in that level,
@@ -1064,7 +1131,7 @@ delete_block (block)
 
 /* 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 teh BIND_EXPR.  */
+   to handle the BLOCK node inside the BIND_EXPR.  */
 
 void
 insert_block (block)
@@ -1127,8 +1194,8 @@ pop_label_level ()
        {
          if (DECL_SOURCE_LINE (TREE_VALUE (link)) == 0)
            {
-             error_with_decl ("label `%s' used but not defined",
-                              TREE_VALUE (link));
+             error_with_decl (TREE_VALUE (link),
+                              "label `%s' used but not defined");
              /* Avoid crashing later.  */
              define_label (input_filename, lineno,
                            DECL_NAME (TREE_VALUE (link)));
@@ -1236,39 +1303,33 @@ duplicate_decls (newdecl, olddecl)
   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
       if (TREE_CODE (olddecl) == FUNCTION_DECL
-         && DECL_BUILT_IN (olddecl))
+         && (DECL_BUILT_IN (olddecl)
+             || DECL_BUILT_IN_NONANSI (olddecl)))
        {
-         /* If you declare a built-in function name as static, the
-            built-in definition is overridden,
+         /* If you declare a built-in or predefined function name as static,
+            the old definition is overridden,
             but optionally warn this was a bad choice of name.  */
          if (!TREE_PUBLIC (newdecl))
            {
-             if (warn_shadow)
+             if (!warn_shadow)
+               ;
+             else if (DECL_BUILT_IN (olddecl))
                warning_with_decl (newdecl, "shadowing built-in function `%s'");
+             else
+               warning_with_decl (newdecl, "shadowing library function `%s'");
            }
          /* Likewise, if the built-in is not ansi, then programs can
             override it even globally without an error.  */
+         else if (! DECL_BUILT_IN (olddecl))
+           warning_with_decl (newdecl,
+                              "library function `%s' declared as non-function");
+
          else if (DECL_BUILT_IN_NONANSI (olddecl))
            warning_with_decl (newdecl,
                               "built-in function `%s' declared as non-function");
          else
-           error_with_decl (newdecl,
-                            "built-in function `%s' declared as non-function");
-       }
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL
-              && DECL_BUILT_IN_NONANSI (olddecl))
-       {
-         /* If overriding decl is static,
-            optionally warn this was a bad choice of name.  */
-         if (!TREE_PUBLIC (newdecl))
-           {
-             if (warn_shadow)
-               warning_with_decl (newdecl, "shadowing library function `%s'");
-           }
-         /* Otherwise, always warn.  */
-         else
            warning_with_decl (newdecl,
-                              "library function `%s' declared as non-function");
+                            "built-in function `%s' declared as non-function");
        }
       else
        {
@@ -1524,9 +1585,10 @@ duplicate_decls (newdecl, olddecl)
              && DECL_INITIAL (olddecl) != 0)
            warning_with_decl (newdecl,
                               "`%s' declared inline after its definition");
-         /* It is nice to warn when a function is declared
-            global first and then static.  */
-         if (TREE_CODE (olddecl) == FUNCTION_DECL
+
+         /* If pedantic, warn when static declaration follows a non-static
+            declaration.  Otherwise, do so only for functions.  */
+         if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL)
              && TREE_PUBLIC (olddecl)
              && !TREE_PUBLIC (newdecl))
            warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
@@ -1546,7 +1608,9 @@ duplicate_decls (newdecl, olddecl)
       /* Dont warn about a function declaration
         followed by a definition.  */
       && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
-          && DECL_INITIAL (olddecl) == 0))
+          && DECL_INITIAL (olddecl) == 0)
+      /* Don't warn about extern decl followed by (tentative) definition.  */
+      && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
     {
       warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope");
       warning_with_decl (olddecl, "previous declaration of `%s'");
@@ -1560,6 +1624,17 @@ duplicate_decls (newdecl, olddecl)
 
   if (types_match)
     {
+      /* 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))
        TREE_TYPE (newdecl)
@@ -1617,6 +1692,15 @@ duplicate_decls (newdecl, olddecl)
       /* Merge the initialization information.  */
       if (DECL_INITIAL (newdecl) == 0)
        DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+
+      /* Merge the section attribute.
+         We want to issue an error if the sections conflict but that must be
+        done later in decl_attributes since we are called before attributes
+        are assigned.  */
+      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+
+      pop_obstacks ();
     }
   /* If cannot merge, then use the new type and qualifiers,
      and don't preserve the old rtl.  */
@@ -1677,7 +1761,7 @@ duplicate_decls (newdecl, olddecl)
       if (DECL_BUILT_IN (olddecl))
        {
          DECL_BUILT_IN (newdecl) = 1;
-         DECL_SET_FUNCTION_CODE (newdecl, DECL_FUNCTION_CODE (olddecl));
+         DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
        }
       else
        DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
@@ -1727,7 +1811,9 @@ pushdecl (x)
     DECL_CONTEXT (x) = 0;
 
   if (warn_nested_externs && DECL_EXTERNAL (x) && b != global_binding_level
-      && x != IDENTIFIER_IMPLICIT_DECL (name))
+      && 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)
@@ -1735,7 +1821,10 @@ pushdecl (x)
       char *file;
       int line;
 
-      t = lookup_name_current_level (name);
+      if (DECL_EXTERNAL (x) && TREE_PUBLIC (x))
+       t = lookup_name (name);
+      else
+       t = lookup_name_current_level (name);
       if (t != 0 && t == error_mark_node)
        /* error_mark_node is 0 for a while during initialization!  */
        {
@@ -1827,7 +1916,7 @@ pushdecl (x)
              if (TYPE_NAME (TREE_TYPE (x)) == 0)
                TYPE_NAME (TREE_TYPE (x)) = x;
             }
-          else
+          else if (TREE_TYPE (x) != error_mark_node)
             {
               tree tt = TREE_TYPE (x);
 
@@ -1838,26 +1927,20 @@ pushdecl (x)
         }
 
       /* Multiple external decls of the same identifier ought to match.
-        Check against both global declarations and out of scope (limbo) block
-        level declarations.
+        Check against out of scope (limbo) block level declarations.
+
+        If this is a block level declaration, then DECL_EXTERNAL must also
+        be set, so we have already checked against global declarations above
+        via the lookup_name call.
 
         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) && ! DECL_INLINE (x)
+         && IDENTIFIER_LIMBO_VALUE (name))
        {
-         tree decl;
-
-         if (IDENTIFIER_GLOBAL_VALUE (name) != 0
-             && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
-                 || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
-           decl = IDENTIFIER_GLOBAL_VALUE (name);
-         else if (IDENTIFIER_LIMBO_VALUE (name) != 0)
-           /* Decls in limbo are always extern, so no need to check that.  */
-           decl = IDENTIFIER_LIMBO_VALUE (name);
-         else
-           decl = 0;
+         tree decl = IDENTIFIER_LIMBO_VALUE (name);
 
-         if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
+         if (! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
              /* If old decl is built-in, we already warned if we should.  */
              && !DECL_BUILT_IN (decl))
            {
@@ -1997,6 +2080,7 @@ pushdecl (x)
                      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_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
                      DECL_RESULT (x) = DECL_RESULT (oldglobal);
                      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
@@ -2006,7 +2090,7 @@ pushdecl (x)
                  if (DECL_BUILT_IN (oldglobal))
                    {
                      DECL_BUILT_IN (x) = DECL_BUILT_IN (oldglobal);
-                     DECL_SET_FUNCTION_CODE (x, DECL_FUNCTION_CODE (oldglobal));
+                     DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
                    }
                  /* Keep the arg types from a file-scope fcn defn.  */
                  if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0
@@ -2244,10 +2328,12 @@ redeclaration_error_message (newdecl, olddecl)
     return 0;
   else
     {
-      /* Objects declared with block scope:  */
-      /* Reject two definitions, and reject a definition
-        together with an external reference.  */
-      if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
+      /* Newdecl has block scope.  If olddecl has block scope also, then
+        reject two definitions, and reject a definition together with an
+        external reference.  Otherwise, it is OK, because newdecl must
+        be an extern reference to olddecl.  */
+      if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
+         && DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
        return "redeclaration of `%s'";
       return 0;
     }
@@ -2347,7 +2433,7 @@ define_label (filename, line, name)
 
   if (DECL_INITIAL (decl) != 0)
     {
-      error_with_decl (decl, "duplicate label `%s'");
+      error ("duplicate label `%s'", IDENTIFIER_POINTER (name));
       return 0;
     }
   else
@@ -2499,7 +2585,7 @@ lookup_name (name)
 
 /* Similar to `lookup_name' but look only at current binding level.  */
 
-static tree
+tree
 lookup_name_current_level (name)
      tree name;
 {
@@ -2571,15 +2657,22 @@ init_decl_processing ()
   pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
                        long_unsigned_type_node));
 
+  long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
+                       long_long_integer_type_node));
+
+  long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
+                       long_long_unsigned_type_node));
+
   /* `unsigned long' is the standard type for sizeof.
      Traditionally, use a signed type.
      Note that stddef.h uses `unsigned long',
      and this must agree, even of long and int are the same size.  */
-  if (flag_traditional)
-    sizetype = long_integer_type_node;
-  else
-    sizetype
-      = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+  sizetype
+    = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+  if (flag_traditional && TREE_UNSIGNED (sizetype))
+    sizetype = signed_type (sizetype);
 
   ptrdiff_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
@@ -2589,6 +2682,8 @@ init_decl_processing ()
   TREE_TYPE (TYPE_SIZE (unsigned_type_node)) = sizetype;
   TREE_TYPE (TYPE_SIZE (long_unsigned_type_node)) = sizetype;
   TREE_TYPE (TYPE_SIZE (long_integer_type_node)) = sizetype;
+  TREE_TYPE (TYPE_SIZE (long_long_integer_type_node)) = sizetype;
+  TREE_TYPE (TYPE_SIZE (long_long_unsigned_type_node)) = sizetype;
 
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
@@ -2597,18 +2692,10 @@ init_decl_processing ()
   pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
                        short_integer_type_node));
 
-  long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
-                       long_long_integer_type_node));
-
   short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
   pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
                        short_unsigned_type_node));
 
-  long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
-                       long_long_unsigned_type_node));
-
   /* Define both `signed char' and `unsigned char'.  */
   signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
   pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
@@ -2663,11 +2750,35 @@ init_decl_processing ()
                        long_double_type_node));
   layout_type (long_double_type_node);
 
+  complex_integer_type_node = make_node (COMPLEX_TYPE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
+                       complex_integer_type_node));
+  TREE_TYPE (complex_integer_type_node) = integer_type_node;
+  layout_type (complex_integer_type_node);
+
+  complex_float_type_node = make_node (COMPLEX_TYPE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
+                       complex_float_type_node));
+  TREE_TYPE (complex_float_type_node) = float_type_node;
+  layout_type (complex_float_type_node);
+
+  complex_double_type_node = make_node (COMPLEX_TYPE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
+                       complex_double_type_node));
+  TREE_TYPE (complex_double_type_node) = double_type_node;
+  layout_type (complex_double_type_node);
+
+  complex_long_double_type_node = make_node (COMPLEX_TYPE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
+                       complex_long_double_type_node));
+  TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
+  layout_type (complex_long_double_type_node);
+
   wchar_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
-  signed_wchar_type_node = type_for_size (wchar_type_size, 0);
-  unsigned_wchar_type_node = type_for_size (wchar_type_size, 1);
+  signed_wchar_type_node = signed_type (wchar_type_node);
+  unsigned_wchar_type_node = unsigned_type (wchar_type_node);
 
   integer_zero_node = build_int_2 (0, 0);
   TREE_TYPE (integer_zero_node) = integer_type_node;
@@ -2866,7 +2977,7 @@ init_decl_processing ()
   builtin_function ("__builtin_classify_type", default_function_type,
                    BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
   builtin_function ("__builtin_next_arg",
-                   build_function_type (ptr_type_node, endlink),
+                   build_function_type (ptr_type_node, NULL_TREE),
                    BUILT_IN_NEXT_ARG, NULL_PTR);
   builtin_function ("__builtin_args_info",
                    build_function_type (integer_type_node,
@@ -2875,6 +2986,29 @@ init_decl_processing ()
                                                    endlink)),
                    BUILT_IN_ARGS_INFO, NULL_PTR);
 
+  /* Untyped call and return.  */
+  builtin_function ("__builtin_apply_args",
+                   build_function_type (ptr_type_node, NULL_TREE),
+                   BUILT_IN_APPLY_ARGS, NULL_PTR);
+
+  temp = tree_cons (NULL_TREE,
+                   build_pointer_type (build_function_type (void_type_node,
+                                                            NULL_TREE)),
+                   tree_cons (NULL_TREE,
+                              ptr_type_node,
+                              tree_cons (NULL_TREE,
+                                         sizetype,
+                                         endlink)));
+  builtin_function ("__builtin_apply",
+                   build_function_type (ptr_type_node, temp),
+                   BUILT_IN_APPLY, NULL_PTR);
+  builtin_function ("__builtin_return",
+                   build_function_type (void_type_node,
+                                        tree_cons (NULL_TREE,
+                                                   ptr_type_node,
+                                                   endlink)),
+                   BUILT_IN_RETURN, NULL_PTR);
+
   /* Currently under experimentation.  */
   builtin_function ("__builtin_memcpy", memcpy_ftype,
                    BUILT_IN_MEMCPY, "memcpy");
@@ -2953,7 +3087,12 @@ init_decl_processing ()
 
   start_identifier_warnings ();
 
-  init_format_info_table ();
+  /* Prepare to check format strings against argument lists.  */
+  init_function_format_info ();
+
+  init_iterators ();
+
+  incomplete_decl_finalize_hook = finish_incomplete_decl;
 }
 
 /* Return a definition for a builtin function named NAME and whose data type
@@ -2986,7 +3125,7 @@ builtin_function (name, type, function_code, library_name)
   if (function_code != NOT_BUILT_IN)
     {
       DECL_BUILT_IN (decl) = 1;
-      DECL_SET_FUNCTION_CODE (decl, function_code);
+      DECL_FUNCTION_CODE (decl) = function_code;
     }
   /* Warn if a function in the namespace for users
      is used without an occasion to consider it declared.  */
@@ -3015,6 +3154,8 @@ void
 shadow_tag_warned (declspecs, warned)
      tree declspecs;
      int warned;
+     /* 1 => we have done a pedwarn.  2 => we have done a warning, but
+       no pedwarn.  */
 {
   int found_tag = 0;
   register tree link;
@@ -3037,7 +3178,8 @@ shadow_tag_warned (declspecs, warned)
 
          if (name == 0)
            {
-             if (!warned && code != ENUMERAL_TYPE) /* Empty unnamed enum OK */
+             if (warned != 1 && code != ENUMERAL_TYPE)
+               /* Empty unnamed enum OK */
                {
                  pedwarn ("unnamed struct/union that defines no instances");
                  warned = 1;
@@ -3057,15 +3199,18 @@ shadow_tag_warned (declspecs, warned)
       else
        {
          if (!warned)
-           pedwarn ("useless keyword or type name in empty declaration");
-         warned = 1;
+           {
+             warning ("useless keyword or type name in empty declaration");
+             warned = 2;
+           }
        }
     }
 
-  if (!warned)
+  if (found_tag > 1)
+    error ("two types specified in one empty declaration");
+
+  if (warned != 1)
     {
-      if (found_tag > 1)
-       error ("two types specified in one empty declaration");
       if (found_tag == 0)
        pedwarn ("empty declaration");
     }
@@ -3217,6 +3362,10 @@ start_decl (declarator, declspecs, initialized)
      TEM may equal DECL or it may be a previous decl of the same name.  */
   tem = pushdecl (decl);
 
+  /* For C and Obective-C, we by default put things in .common when
+     possible.  */
+  DECL_COMMON (tem) = 1;
+
   /* For a local variable, define the RTL now.  */
   if (current_binding_level != global_binding_level
       /* But not if this is a duplicate decl
@@ -3257,8 +3406,13 @@ finish_decl (decl, init, asmspec_tree)
   int temporary = allocation_temporary_p ();
   char *asmspec = 0;
 
+  /* If a name was specified, get the string.  Then reset DECL_RTL
+     so that we will remake it with the new name.  */
   if (asmspec_tree)
-    asmspec = TREE_STRING_POINTER (asmspec_tree);
+    {
+      asmspec = TREE_STRING_POINTER (asmspec_tree);
+      DECL_RTL (decl) = 0;
+    }
 
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
 
@@ -3323,15 +3477,22 @@ finish_decl (decl, init, asmspec_tree)
        {
          if (do_default)
            error_with_decl (decl, "array size missing in `%s'");
-         else if (!pedantic && TREE_STATIC (decl))
-           /* ??? Perhaps should set TREE_PUBLIC here?  */
+         /* If a `static' var's size isn't known,
+            make it extern as well as static, so it does not get
+            allocated.
+            If it is not `static', then do not mark extern;
+            finish_incomplete_decl will give it a default size
+            and it will get allocated.  */
+         else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl))
            DECL_EXTERNAL (decl) = 1;
        }
 
+      /* TYPE_MAX_VALUE is always one less than the number of elements
+        in the array, because we start counting at zero.  Therefore,
+        warn only if the value is less than zero.  */
       if (pedantic && TYPE_DOMAIN (type) != 0
-         && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
-                             integer_zero_node))
-       error_with_decl (decl, "zero-size array `%s'");
+         && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+       error_with_decl (decl, "zero or negative size array `%s'");
 
       layout_decl (decl, 0);
     }
@@ -3339,13 +3500,19 @@ finish_decl (decl, init, asmspec_tree)
   if (TREE_CODE (decl) == VAR_DECL)
     {
       if (DECL_SIZE (decl) == 0
+         && TYPE_SIZE (TREE_TYPE (decl)) != 0)
+       layout_decl (decl, 0);
+
+      if (DECL_SIZE (decl) == 0
          && (TREE_STATIC (decl)
              ?
                /* A static variable with an incomplete type
-                  is an error if it is initialized or `static'.
+                  is an error if it is initialized.
+                  Also if it is not file scope.
                   Otherwise, let it through, but if it is not `extern'
                   then it may cause an error message later.  */
-               !TREE_PUBLIC (decl) || DECL_INITIAL (decl)
+               (DECL_INITIAL (decl) != 0
+                || current_binding_level != global_binding_level)
              :
                /* An automatic variable with an incomplete type
                   is an error.  */
@@ -3365,6 +3532,11 @@ finish_decl (decl, init, asmspec_tree)
        }
     }
 
+  /* If this is a function and an assembler name is specified, it isn't
+     builtin any more.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
+    DECL_BUILT_IN (decl) = 0;
+
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
      If not, it will get done when the type is completed.  */
@@ -3420,8 +3592,14 @@ finish_decl (decl, init, asmspec_tree)
     }
 
   /* ??? 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 && TREE_PERMANENT (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,
@@ -3429,8 +3607,48 @@ finish_decl (decl, init, asmspec_tree)
       /* 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 (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))
+           {
+             preserve_initializer ();
+             /* Hack?  Set the permanent bit for something that is permanent,
+                but not on the permenent 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);
+       }
     }
 
 #if 0
@@ -3443,7 +3661,7 @@ finish_decl (decl, init, asmspec_tree)
   /* 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 ();
+    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
@@ -3472,7 +3690,7 @@ void
 push_parm_decl (parm)
      tree parm;
 {
-  tree decl, olddecl;
+  tree decl;
   int old_immediate_size_expand = immediate_size_expand;
   /* Don't try computing parm sizes now -- wait till fn is called.  */
   immediate_size_expand = 0;
@@ -3481,12 +3699,17 @@ push_parm_decl (parm)
   push_obstacks_nochange ();
 
   decl = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), PARM, 0);
+
+#if 0
   if (DECL_NAME (decl))
     {
+      tree olddecl;
       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");
     }
+#endif
+
   decl = pushdecl (decl);
 
   immediate_size_expand = old_immediate_size_expand;
@@ -3529,13 +3752,21 @@ complete_array_type (type, initial_value, do_default)
        {
          int eltsize
            = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
-         maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) / eltsize - 1, 0);
+         maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
+                                  / eltsize) - 1, 0);
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
-         register int nelts
-           = list_length (CONSTRUCTOR_ELTS (initial_value));
-         maxindex = build_int_2 (nelts - 1, 0);
+         tree elts = CONSTRUCTOR_ELTS (initial_value);
+         maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+         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 = copy_node (maxindex);
        }
       else
        {
@@ -3544,14 +3775,14 @@ complete_array_type (type, initial_value, do_default)
            value = 1;
 
          /* Prevent further error messages.  */
-         maxindex = build_int_2 (1, 0);
+         maxindex = build_int_2 (0, 0);
        }
     }
 
   if (!maxindex)
     {
       if (do_default)
-       maxindex = build_int_2 (1, 0);
+       maxindex = build_int_2 (0, 0);
       value = 2;
     }
 
@@ -3560,6 +3791,12 @@ complete_array_type (type, initial_value, do_default)
       TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (!TREE_TYPE (maxindex))
        TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+#if 0 /* I took out this change
+        together with the change in build_array_type. --rms  */
+      change_main_variant (type,
+                          build_array_type (TREE_TYPE (type),
+                                            TYPE_DOMAIN (type)));
+#endif
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -3614,6 +3851,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   int inlinep;
   int explicit_int = 0;
   int explicit_char = 0;
+  int defaulted_int = 0;
   tree typedef_decl = 0;
   char *name;
   tree typedef_type = 0;
@@ -3757,7 +3995,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   if (type)
     size_varies = C_TYPE_VARIABLE_SIZE (type);
 
-  /* No type at all: default to `int', and set EXPLICIT_INT
+  /* No type at all: default to `int', and set DEFAULTED_INT
      because it was not a user-defined typedef.  */
 
   if (type == 0)
@@ -3766,7 +4004,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
                            | (1 << (int) RID_SIGNED) | (1 << (int) RID_UNSIGNED))))
        warn_about_return_type = 1;
-      explicit_int = 1;
+      defaulted_int = 1;
       type = integer_type_node;
     }
 
@@ -3808,7 +4046,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else
        {
          ok = 1;
-         if (!explicit_int && !explicit_char && pedantic)
+         if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
            {
              pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
                       name);
@@ -3826,6 +4064,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        }
     }
 
+  if ((specbits & (1 << (int) RID_COMPLEX))
+      && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
+    {
+      error ("complex invalid for `%s'", name);
+      specbits &= ~ (1 << (int) RID_COMPLEX);
+    }
+
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
   if (specbits & 1 << (int) RID_UNSIGNED
@@ -3833,7 +4078,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       || (bitfield && flag_traditional
          && (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
       || (bitfield && ! flag_signed_bitfields
-         && (explicit_int || explicit_char
+         && (explicit_int || defaulted_int || explicit_char
              /* A typedef for plain `int' without `signed'
                 can be controlled just like plain `int'.  */
              || ! (typedef_decl != 0
@@ -3864,6 +4109,30 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   else if (specbits & 1 << (int) RID_SHORT)
     type = short_integer_type_node;
 
+  if (specbits & 1 << (int) RID_COMPLEX)
+    {
+      /* If we just have "complex", it is equivalent to
+        "complex double", but if any modifiers at all are specified it is
+        the complex form of TYPE.  E.g, "complex short" is
+        "complex short int".  */
+
+      if (defaulted_int && ! longlong
+         && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
+                           | (1 << (int) RID_SIGNED)
+                           | (1 << (int) RID_UNSIGNED))))
+       type = complex_double_type_node;
+      else if (type == integer_type_node)
+       type = complex_integer_type_node;
+      else if (type == float_type_node)
+       type = complex_float_type_node;
+      else if (type == double_type_node)
+       type = complex_double_type_node;
+      else if (type == long_double_type_node)
+       type = complex_long_double_type_node;
+      else
+       type = build_complex_type (type);
+    }
+
   /* Set CONSTP if this declaration is `const', whether by
      explicit specification or via a typedef.
      Likewise for VOLATILEP.  */
@@ -3986,6 +4255,10 @@ 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);
 
          declarator = TREE_OPERAND (declarator, 0);
 
@@ -4009,6 +4282,12 @@ 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.  */
@@ -4024,31 +4303,43 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                  error ("size of array `%s' has non-integer type", name);
                  size = integer_one_node;
                }
+
              if (pedantic && integer_zerop (size))
                pedwarn ("ANSI C forbids zero-size array `%s'", name);
+
              if (TREE_CODE (size) == INTEGER_CST)
                {
                  constant_expression_warning (size);
-                 if (INT_CST_LT (size, integer_zero_node))
+                 if (tree_int_cst_sgn (size) < 0)
                    {
                      error ("size of array `%s' is negative", name);
                      size = integer_one_node;
                    }
-                 itype = build_index_type (size_binop (MINUS_EXPR, size,
-                                                       size_one_node));
                }
              else
                {
-                 if (pedantic)
-                   pedwarn ("ANSI C forbids variable-size array `%s'", name);
-                 itype = build_binary_op (MINUS_EXPR, size, integer_one_node,
-                                          1);
                  /* Make sure the array size remains visibly nonconstant
                     even if it is (eg) a const variable with known value.  */
                  size_varies = 1;
-                 itype = variable_size (itype);
-                 itype = build_index_type (itype);
+
+                 if (pedantic)
+                   {
+                     if (TREE_CONSTANT (size))
+                       pedwarn ("ANSI C forbids array `%s' whose size can't be evaluated", name);
+                     else
+                       pedwarn ("ANSI C forbids variable-size array `%s'", name);
+                   }
                }
+
+             /* Convert size to index_type, so that if it is a variable
+                the computations will be done in the proper mode.  */
+             itype = fold (build (MINUS_EXPR, index_type,
+                                  convert (index_type, size),
+                                  convert (index_type, size_one_node)));
+
+             if (size_varies)
+               itype = variable_size (itype);
+             itype = build_index_type (itype);
            }
 
 #if 0 /* This had bad results for pointers to arrays, as in
@@ -4063,15 +4354,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            warning ("array type has incomplete element type");
 #endif
 
-         /* Build the array type itself.
-            Merge any constancy or volatility into the target type.  */
-
 #if 0  /* We shouldn't have a function type here at all!
          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");
 #endif
+
+         /* Build the array type itself, then merge any constancy or
+            volatility into the target type.  We must do it in this order
+            to ensure that the TYPE_MAIN_VARIANT field of the array type
+            is set correctly.  */
+
+         type = build_array_type (type, itype);
          if (constp || volatilep)
            type = c_build_type_variant (type, constp, volatilep);
 
@@ -4081,7 +4376,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          volatilep = 0;
 #endif
 
-         type = build_array_type (type, itype);
          if (size_varies)
            C_TYPE_VARIABLE_SIZE (type) = 1;
        }
@@ -4144,6 +4438,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                      flag_traditional 
                                      ? NULL_TREE : arg_types);
 #endif
+         /* ANSI seems to say that `const int foo ();'
+            does not make the function foo const.  */
+         if (constp || volatilep)
+           type = c_build_type_variant (type, constp, volatilep);
+         constp = 0;
+         volatilep = 0;
+
          type = build_function_type (type, arg_types);
          declarator = TREE_OPERAND (declarator, 0);
 
@@ -4262,12 +4563,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       return type;
     }
 
-  /* `void' at top level (not within pointer)
-     is allowed only in typedefs or type names.
+  /* Aside from typedefs and type names (handle above),
+     `void' at top level (not within pointer)
+     is allowed only in public variables.
      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 (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM
+      && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
+           && ((specbits & (1 << (int) RID_EXTERN))
+               || (current_binding_level == global_binding_level
+                   && !(specbits
+                        & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
     {
       error ("variable or field `%s' declared void",
             IDENTIFIER_POINTER (declarator));
@@ -4291,8 +4598,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        if (TREE_CODE (type) == ARRAY_TYPE)
          {
            /* Transfer const-ness of array into that of type pointed to.  */
-           type = build_pointer_type
-                   (c_build_type_variant (TREE_TYPE (type), constp, volatilep));
+           type = TREE_TYPE (type);
+           if (constp || volatilep)
+             type = c_build_type_variant (type, constp, volatilep);
+           type = build_pointer_type (type);
            volatilep = constp = 0;
            size_varies = 0;
          }
@@ -4300,7 +4609,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          {
            if (pedantic && (constp || volatilep))
              pedwarn ("ANSI C forbids const or volatile function types");
-           type = build_pointer_type (c_build_type_variant (type, constp, volatilep));
+           if (constp || volatilep)
+             type = c_build_type_variant (type, constp, volatilep);
+           type = build_pointer_type (type);
            volatilep = constp = 0;
          }
 
@@ -4314,13 +4625,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
           When there is a prototype, this is overridden later.  */
 
        DECL_ARG_TYPE (decl) = type;
-       main_type = TYPE_MAIN_VARIANT (type);
+       main_type = (type == error_mark_node
+                    ? error_mark_node
+                    : TYPE_MAIN_VARIANT (type));
        if (main_type == float_type_node)
          DECL_ARG_TYPE (decl) = double_type_node;
        /* Don't use TYPE_PRECISION to decide whether to promote,
           because we should convert short if it's the same size as int,
           but we should not convert long if it's the same size as int.  */
-       else if (C_PROMOTING_INTEGER_TYPE_P (main_type))
+       else if (TREE_CODE (main_type) != ERROR_MARK
+                && C_PROMOTING_INTEGER_TYPE_P (main_type))
          {
            if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)
                && TREE_UNSIGNED (type))
@@ -4399,6 +4713,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ANSI C forbids const or volatile functions");
 
+       if (volatilep
+           && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
+         warning ("`noreturn' function returns non-void value");
+
        if (extern_ref)
          DECL_EXTERNAL (decl) = 1;
        /* Record absence of global scope for `static' or `auto'.  */
@@ -4473,11 +4791,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
        if (specbits & 1 << (int) RID_ITERATOR)
          ITERATOR_P (decl) = 1;
-      {
-       error ("iterator `%s' has derived type", name);
-       type = error_mark_node;
-      }
-
       }
 
     /* Record `register' declaration for warnings on &
@@ -4702,7 +5015,8 @@ get_parm_info (void_at_end)
        tree type = TREE_TYPE (decl);
        DECL_ARG_TYPE (decl) = type;
 #ifdef PROMOTE_PROTOTYPES
-       if (TREE_CODE (type) == INTEGER_TYPE
+       if ((TREE_CODE (type) == INTEGER_TYPE
+            || TREE_CODE (type) == ENUMERAL_TYPE)
            && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
          DECL_ARG_TYPE (decl) = integer_type_node;
 #endif
@@ -4880,6 +5194,7 @@ grokfield (filename, line, declarator, declspecs, width)
   finish_decl (value, NULL_TREE, NULL_TREE);
   DECL_INITIAL (value) = width;
 
+  maybe_objc_check_decl (value);
   return value;
 }
 \f
@@ -4993,7 +5308,11 @@ finish_struct (t, fieldlist)
        }
       if (DECL_INITIAL (x) && pedantic
          && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
-         && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node)
+         && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
+         /* Accept an enum that's equivalent to int or unsigned int.  */
+         && !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
+              && (TYPE_PRECISION (TREE_TYPE (x))
+                  == 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.  */
@@ -5001,7 +5320,7 @@ finish_struct (t, fieldlist)
        {
          unsigned HOST_WIDE_INT width = TREE_INT_CST_LOW (DECL_INITIAL (x));
 
-         if (tree_int_cst_lt (DECL_INITIAL (x), integer_zero_node))
+         if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
            {
              DECL_INITIAL (x) = NULL;
              error_with_decl (x, "negative width in bit-field `%s'");
@@ -5148,19 +5467,23 @@ finish_struct (t, fieldlist)
   /* Promote each bit-field's type to int if it is narrower than that.  */
   for (x = fieldlist; x; x = TREE_CHAIN (x))
     if (DECL_BIT_FIELD (x)
-       && C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x)))
-    {
-      tree type = TREE_TYPE (x);
-
-      /* Preserve unsignedness if traditional or if not really any wider.  */
-      if (TREE_UNSIGNED (type)
-         && (flag_traditional
-             || (TYPE_PRECISION (type)
-                 == TYPE_PRECISION (integer_type_node))))
-       TREE_TYPE (x) = unsigned_type_node;
-      else
-       TREE_TYPE (x) = integer_type_node;
-    }
+       && (C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x))
+           || DECL_FIELD_SIZE (x) < TYPE_PRECISION (integer_type_node)))
+      {
+       tree type = TREE_TYPE (x);
+
+       /* Preserve unsignedness if traditional
+          or if not really getting any wider.  */
+       if (TREE_UNSIGNED (type)
+           && (flag_traditional
+               ||
+               (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)
+                &&
+                DECL_FIELD_SIZE (x) == TYPE_PRECISION (integer_type_node))))
+         TREE_TYPE (x) = unsigned_type_node;
+       else
+         TREE_TYPE (x) = integer_type_node;
+      }
 
   /* If this structure or union completes the type of any previous
      variable declaration, lay it out and output its rtl.  */
@@ -5273,14 +5596,12 @@ tree
 finish_enum (enumtype, values)
      register tree enumtype, values;
 {
-  register tree pair;
+  register tree pair, tem;
   tree minnode = 0, maxnode = 0;
   register HOST_WIDE_INT maxvalue = 0;
   register HOST_WIDE_INT minvalue = 0;
-  register int i;
   unsigned precision = 0;
   int toplevel = global_binding_level == current_binding_level;
-  int temporary = allocation_temporary_p ();
 
   if (in_parm_level_p ())
     warning ("enum defined inside parms");
@@ -5343,19 +5664,20 @@ finish_enum (enumtype, values)
   layout_type (enumtype);
 
   /* An enum can have some negative values; then it is signed.  */
-  TREE_UNSIGNED (enumtype) = ! tree_int_cst_lt (minnode, integer_zero_node);
+  TREE_UNSIGNED (enumtype) = tree_int_cst_sgn (minnode) >= 0;
 
-  /* If the enumerators might not fit in an int, change their type now.  */
-  /* It seems more useful in the debugger to leave these as int
-     unless the enumerator is wider than int.  */
-  if (TYPE_PRECISION (enumtype) <= TYPE_PRECISION (integer_type_node))
-    for (pair = values; pair; pair = TREE_CHAIN (pair))
-      {
-       TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
-       DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
-       if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
-         DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
-      }
+  /* Change the type of the enumerators to be the enum type.
+     Formerly this was done only for enums that fit in an int,
+     but the comment said it was done only for enums wider than int.
+     It seems necessary to do this for wide enums,
+     and best not to change what's done for ordinary narrower ones.  */
+  for (pair = values; pair; pair = TREE_CHAIN (pair))
+    {
+      TREE_TYPE (TREE_PURPOSE (pair)) = enumtype;
+      DECL_SIZE (TREE_PURPOSE (pair)) = TYPE_SIZE (enumtype);
+      if (TREE_CODE (TREE_PURPOSE (pair)) != FUNCTION_DECL)
+       DECL_ALIGN (TREE_PURPOSE (pair)) = TYPE_ALIGN (enumtype);
+    }
 
   /* Replace the decl nodes in VALUES with their names.  */
   for (pair = values; pair; pair = TREE_CHAIN (pair))
@@ -5363,6 +5685,19 @@ finish_enum (enumtype, values)
 
   TYPE_VALUES (enumtype) = values;
 
+  /* Fix up all variant types of this enum type.  */
+  for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
+    {
+      TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+      TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
+      TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
+      TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+      TYPE_MODE (tem) = TYPE_MODE (enumtype);
+      TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
+      TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+      TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+    }
+
   /* Finish debugging output for this type.  */
   rest_of_type_compilation (enumtype, toplevel);
 
@@ -5381,7 +5716,7 @@ tree
 build_enumerator (name, value)
      tree name, value;
 {
-  register tree decl;
+  register tree decl, type;
 
   /* Validate and default VALUE.  */
 
@@ -5392,7 +5727,10 @@ build_enumerator (name, value)
   if (value != 0)
     {
       if (TREE_CODE (value) == INTEGER_CST)
-       constant_expression_warning (value);
+       {
+         value = default_conversion (value);
+         constant_expression_warning (value);
+       }
       else
        {
          error ("enumerator value for `%s' not integer constant",
@@ -5423,9 +5761,16 @@ build_enumerator (name, value)
 
   /* Now create a declaration for the enum value name.  */
 
-  decl = build_decl (CONST_DECL, name, integer_type_node);
+  type = TREE_TYPE (value);
+  type = type_for_size (MAX (TYPE_PRECISION (type),
+                            TYPE_PRECISION (integer_type_node)),
+                       ((flag_traditional
+                         || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
+                        && TREE_UNSIGNED (type)));
+
+  decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = value;
-  TREE_TYPE (value) = integer_type_node;
+  TREE_TYPE (value) = type;
   pushdecl (decl);
 
   return saveable_tree_cons (decl, value, NULL_TREE);
@@ -5500,7 +5845,11 @@ start_function (declspecs, declarator, nested)
       && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
          == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl))))
       && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
-    TREE_TYPE (decl1) = TREE_TYPE (old_decl);
+    {
+      TREE_TYPE (decl1) = TREE_TYPE (old_decl);
+      current_function_prototype_file = DECL_SOURCE_FILE (old_decl);
+      current_function_prototype_line = DECL_SOURCE_LINE (old_decl);
+    }
 
   /* Optionally warn of old-fashioned def with no previous prototype.  */
   if (warn_strict_prototypes
@@ -5510,14 +5859,28 @@ start_function (declspecs, declarator, nested)
   /* Optionally warn of any global def with no previous prototype.  */
   else if (warn_missing_prototypes
           && TREE_PUBLIC (decl1)
-          && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0))
+          && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0)
+          && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
     warning_with_decl (decl1, "no previous prototype for `%s'");
   /* Optionally warn of any def with no previous prototype
      if the function has already been used.  */
   else if (warn_missing_prototypes
           && old_decl != 0 && TREE_USED (old_decl)
           && !(old_decl != 0 && TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0))
-    warning_with_decl (decl1, "`%s' was used with no prototype before its definition");
+    warning_with_decl (decl1,
+                     "`%s' was used with no prototype before its definition");
+  /* Optionally warn of any global def with no previous declaration.  */
+  else if (warn_missing_declarations
+          && TREE_PUBLIC (decl1)
+          && old_decl == 0
+          && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))))
+    warning_with_decl (decl1, "no previous declaration for `%s'");
+  /* Optionally warn of any def with no previous declaration
+     if the function has already been used.  */
+  else if (warn_missing_declarations
+          && old_decl != 0 && TREE_USED (old_decl))
+    warning_with_decl (decl1,
+                   "`%s' was used with no declaration before its definition");
 
   /* This is a definition, not a reference.
      So normally clear DECL_EXTERNAL.
@@ -5766,7 +6129,11 @@ store_parm_decls ()
          /* 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;
+           {
+             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)
@@ -5863,6 +6230,9 @@ store_parm_decls ()
                  || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
                {
                  error ("number of arguments doesn't match prototype");
+                 error_with_file_and_line (current_function_prototype_file,
+                                           current_function_prototype_line,
+                                           "prototype declaration");
                  break;
                }
              /* Type for passing arg must be consistent
@@ -5879,22 +6249,34 @@ store_parm_decls ()
                         useful for argument types like uid_t.  */
                      DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
 #ifdef PROMOTE_PROTOTYPES
-                     if (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+                     if ((TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+                          || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
                          && TYPE_PRECISION (TREE_TYPE (parm))
                          < TYPE_PRECISION (integer_type_node))
                        DECL_ARG_TYPE (parm) = integer_type_node;
 #endif
                      if (pedantic)
-                       pedwarn ("promoted argument `%s' doesn't match prototype",
-                                IDENTIFIER_POINTER (DECL_NAME (parm)));
+                       {
+                         pedwarn ("promoted argument `%s' doesn't match prototype",
+                                  IDENTIFIER_POINTER (DECL_NAME (parm)));
+                         warning_with_file_and_line
+                           (current_function_prototype_file,
+                            current_function_prototype_line,
+                            "prototype declaration");
+                       }
                    }
                  /* If -traditional, allow `int' argument to match
                     `unsigned' prototype.  */
                  else if (! (flag_traditional
                              && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node
                              && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))
-                   error ("argument `%s' doesn't match prototype",
-                          IDENTIFIER_POINTER (DECL_NAME (parm)));
+                   {
+                     error ("argument `%s' doesn't match prototype",
+                            IDENTIFIER_POINTER (DECL_NAME (parm)));
+                     error_with_file_and_line (current_function_prototype_file,
+                                               current_function_prototype_line,
+                                               "prototype declaration");
+                   }
                }
            }
          TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
@@ -5904,8 +6286,7 @@ store_parm_decls ()
 
       else
        {
-         register tree actual, type;
-         register tree last = 0;
+         tree actual = 0, last = 0, type;
 
          for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
            {
@@ -6048,7 +6429,11 @@ combine_parm_decls (specparms, parmlist, void_at_end)
       /* 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;
+       {
+         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)
@@ -6058,7 +6443,7 @@ combine_parm_decls (specparms, parmlist, void_at_end)
          DECL_ARG_TYPE (found) = TREE_TYPE (found);
          DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
          DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
-         error (found, "type of parameter `%s' is not declared");
+         error_with_decl (found, "type of parameter `%s' is not declared");
          pushdecl (found);
        }
 
@@ -6174,7 +6559,7 @@ finish_function (nested)
 #endif
 
   /* Generate rtl for function exit.  */
-  expand_function_end (input_filename, lineno);
+  expand_function_end (input_filename, lineno, 0);
 
   /* So we can tell if jump_optimize sets it to 1.  */
   can_reach_end = 0;
@@ -6185,7 +6570,7 @@ finish_function (nested)
   current_function_returns_null |= can_reach_end;
 
   if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
-    warning ("`volatile' function does return");
+    warning ("`noreturn' function does return");
   else if (warn_return_type && can_reach_end
           && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) != void_type_node)
     /* If this function returns non-void and control can drop through,
@@ -6197,11 +6582,36 @@ finish_function (nested)
           && current_function_returns_value && current_function_returns_null)
     warning ("this function may return with or without a value");
 
+  /* If requested, warn about function definitions where the function will
+     return a value (usually of some struct or union type) which itself will
+     take up a lot of stack space.  */
+
+  if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
+    {
+      register tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
+
+      if (ret_type)
+       {
+         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;
+
+             if (units > larger_than_size)
+               warning_with_decl (fndecl,
+                                  "size of return value of `%s' is %u bytes",
+                                  units);
+           }
+       }
+    }
+
   /* Free all the tree nodes making up this function.  */
   /* Switch back to allocating nodes permanently
      until we start another function.  */
   if (! nested)
-    permanent_allocation ();
+    permanent_allocation (1);
 
   if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested)
     {
@@ -6209,7 +6619,9 @@ finish_function (nested)
       /* 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.  */
-      DECL_INITIAL (fndecl) = error_mark_node;
+      /* 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;
     }
 
@@ -6229,7 +6641,6 @@ finish_function (nested)
 struct c_function
 {
   struct c_function *next;
-  tree enum_next_value;
   tree named_labels;
   tree shadowed_labels;
   int returns_value;
@@ -6258,7 +6669,6 @@ push_c_function_context ()
   p->next = c_function_chain;
   c_function_chain = p;
 
-  p->enum_next_value = enum_next_value;
   p->named_labels = named_labels;
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
@@ -6295,7 +6705,6 @@ pop_c_function_context ()
 
   c_function_chain = p->next;
 
-  enum_next_value = p->enum_next_value;
   named_labels = p->named_labels;
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;