OSDN Git Service

(finish_decl): If asmspec_tree, clear DECL_BUILT_IN for function and
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 65ff9f7..a7cd30e 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -208,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;
 
@@ -434,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;
@@ -477,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.  */
 
@@ -534,6 +546,8 @@ 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;
@@ -618,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"))
@@ -1285,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
        {
@@ -1573,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");
@@ -1611,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)
@@ -1668,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.  */
@@ -1728,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);
@@ -1778,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)
@@ -1786,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!  */
        {
@@ -1889,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))
            {
@@ -2058,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
@@ -2296,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;
     }
@@ -2623,6 +2657,14 @@ 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',
@@ -2640,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;
@@ -2648,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"),
@@ -2741,8 +2777,8 @@ init_decl_processing ()
   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;
@@ -2941,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,
@@ -3051,7 +3087,8 @@ init_decl_processing ()
 
   start_identifier_warnings ();
 
-  init_format_info_table ();
+  /* Prepare to check format strings against argument lists.  */
+  init_function_format_info ();
 
   init_iterators ();
 
@@ -3088,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.  */
@@ -3325,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
@@ -3365,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.  */
 
@@ -3441,10 +3487,12 @@ finish_decl (decl, init, asmspec_tree)
            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);
     }
@@ -3460,9 +3508,11 @@ finish_decl (decl, init, asmspec_tree)
              ?
                /* A static variable with an incomplete type
                   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.  */
-               DECL_INITIAL (decl) != 0
+               (DECL_INITIAL (decl) != 0
+                || current_binding_level != global_binding_level)
              :
                /* An automatic variable with an incomplete type
                   is an error.  */
@@ -3482,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.  */
@@ -3537,8 +3592,11 @@ 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)
@@ -3549,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
@@ -3563,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
@@ -3592,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;
@@ -3605,6 +3703,7 @@ push_parm_decl (parm)
 #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");
@@ -3653,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, - (nelts == 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
        {
@@ -3957,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
@@ -3994,9 +4108,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     type = long_integer_type_node;
   else if (specbits & 1 << (int) RID_SHORT)
     type = short_integer_type_node;
-  else if (specbits & 1 << (int) RID_COMPLEX)
+
+  if (specbits & 1 << (int) RID_COMPLEX)
     {
-      if (defaulted_int)
+      /* 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;
@@ -4007,7 +4130,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (type == long_double_type_node)
        type = complex_long_double_type_node;
       else
-       error ("invalid complex type");
+       type = build_complex_type (type);
     }
 
   /* Set CONSTP if this declaration is `const', whether by
@@ -4134,6 +4257,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          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);
 
@@ -4178,21 +4303,25 @@ 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
                {
+                 /* Make sure the array size remains visibly nonconstant
+                    even if it is (eg) a const variable with known value.  */
+                 size_varies = 1;
+
                  if (pedantic)
                    {
                      if (TREE_CONSTANT (size))
@@ -4200,14 +4329,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                      else
                        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);
                }
+
+             /* 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
@@ -4466,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;
          }
@@ -4475,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;
          }
 
@@ -4579,7 +4715,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
        if (volatilep
            && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
-         warning ("volatile function returns non-void value");
+         warning ("`noreturn' function returns non-void value");
 
        if (extern_ref)
          DECL_EXTERNAL (decl) = 1;
@@ -4879,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
@@ -5183,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'");
@@ -5463,10 +5600,8 @@ finish_enum (enumtype, values)
   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");
@@ -5529,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))
@@ -5580,7 +5716,7 @@ tree
 build_enumerator (name, value)
      tree name, value;
 {
-  register tree decl;
+  register tree decl, type;
 
   /* Validate and default VALUE.  */
 
@@ -5591,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",
@@ -5622,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);
@@ -5721,7 +5867,20 @@ start_function (declspecs, declarator, nested)
   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.
@@ -6090,7 +6249,8 @@ 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;
@@ -6126,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))
            {
@@ -6400,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;
@@ -6411,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,
@@ -6423,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)
     {
@@ -6435,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;
     }
 
@@ -6455,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;
@@ -6484,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;
@@ -6521,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;