OSDN Git Service

* config/linux.h (ASM_COMMENT_START): Remove from here,
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 611b3ef..ba67ec5 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -27,12 +27,13 @@ Boston, MA 02111-1307, USA.  */
    line numbers.  For example, the CONST_DECLs for enum values.  */
 
 #include "config.h"
+#include "system.h"
 #include "tree.h"
 #include "flags.h"
 #include "output.h"
 #include "c-tree.h"
 #include "c-lex.h"
-#include <stdio.h>
+#include "toplev.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -143,11 +144,13 @@ tree intQI_type_node;
 tree intHI_type_node;
 tree intSI_type_node;
 tree intDI_type_node;
+tree intTI_type_node;
 
 tree unsigned_intQI_type_node;
 tree unsigned_intHI_type_node;
 tree unsigned_intSI_type_node;
 tree unsigned_intDI_type_node;
+tree unsigned_intTI_type_node;
 
 /* a VOID_TYPE node.  */
 
@@ -423,7 +426,7 @@ static tree lookup_tag_reverse              PROTO((tree));
 static tree grokdeclarator             PROTO((tree, tree, enum decl_context,
                                               int));
 static tree grokparms                  PROTO((tree, int));
-static int field_decl_cmp              PROTO((tree *, tree *));
+static int field_decl_cmp              PROTO((const GENERIC_PTR, const GENERIC_PTR));
 static void layout_array_type          PROTO((tree));
 \f
 /* C-specific option variables.  */
@@ -454,6 +457,10 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
+/* Nonzero means that we have builtin functions, and main is an int */
+
+int flag_hosted = 1;
+
 /* Nonzero means to allow single precision math even if we're generally
    being traditional.  */
 int flag_allow_single_precision = 0;
@@ -467,9 +474,14 @@ int explicit_flag_signed_bitfields = 0;
 
 int flag_no_ident = 0;
 
-/* Nonzero means warn about implicit declarations.  */
+/* Nonzero means warn about use of implicit int. */
+
+int warn_implicit_int;
 
-int warn_implicit;
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
+
+int mesg_implicit_function_declaration;
 
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
@@ -545,9 +557,18 @@ int warn_parentheses;
 
 int warn_missing_braces;
 
-/* Warn about comparison of signed and unsigned values.  */
+/* Warn if main is suspicious.  */
+
+int warn_main;
+
+/* Warn about #pragma directives that are not recognised.  */
 
-int warn_sign_compare;
+int warn_unknown_pragmas = 0; /* Tri state variable.  */  
+
+/* Warn about comparison of signed and unsigned values.
+   If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified.  */
+
+int warn_sign_compare = -1;
 
 /* Nonzero means `$' can be in an identifier.  */
 
@@ -571,6 +592,19 @@ c_decode_option (p)
     }
   else if (!strcmp (p, "-fallow-single-precision"))
     flag_allow_single_precision = 1;
+  else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
+    {
+      flag_hosted = 1;
+      flag_no_builtin = 0;
+    }
+  else if (!strcmp (p, "-ffreestanding") || !strcmp (p, "-fno-hosted"))
+    {
+      flag_hosted = 0;
+      flag_no_builtin = 1;
+      /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */
+      if (warn_main == 2)
+       warn_main = 0;
+    }
   else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
     {
       flag_traditional = 0;
@@ -626,10 +660,24 @@ c_decode_option (p)
     flag_no_ident = 0;
   else if (!strcmp (p, "-ansi"))
     flag_no_asm = 1, flag_no_nonansi_builtin = 1;
+  else if (!strcmp (p, "-Werror-implicit-function-declaration"))
+    mesg_implicit_function_declaration = 2;
+  else if (!strcmp (p, "-Wimplicit-function-declaration"))
+    mesg_implicit_function_declaration = 1;
+  else if (!strcmp (p, "-Wno-implicit-function-declaration"))
+    mesg_implicit_function_declaration = 0;
+  else if (!strcmp (p, "-Wimplicit-int"))
+    warn_implicit_int = 1;
+  else if (!strcmp (p, "-Wno-implicit-int"))
+    warn_implicit_int = 0;
   else if (!strcmp (p, "-Wimplicit"))
-    warn_implicit = 1;
+    {
+      warn_implicit_int = 1;
+      if (mesg_implicit_function_declaration != 2)
+        mesg_implicit_function_declaration = 1;
+    }
   else if (!strcmp (p, "-Wno-implicit"))
-    warn_implicit = 0;
+    warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
   else if (!strcmp (p, "-Wwrite-strings"))
     warn_write_strings = 1;
   else if (!strcmp (p, "-Wno-write-strings"))
@@ -702,6 +750,10 @@ c_decode_option (p)
     ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wno-trigraphs"))
     ; /* cpp handles this one.  */
+  else if (!strcmp (p, "-Wundef"))
+    ; /* cpp handles this one.  */
+  else if (!strcmp (p, "-Wno-undef"))
+    ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wimport"))
     ; /* cpp handles this one.  */
   else if (!strcmp (p, "-Wno-import"))
@@ -710,10 +762,20 @@ c_decode_option (p)
     warn_missing_braces = 1;
   else if (!strcmp (p, "-Wno-missing-braces"))
     warn_missing_braces = 0;
+  else if (!strcmp (p, "-Wmain"))
+    warn_main = 1;
+  else if (!strcmp (p, "-Wno-main"))
+    warn_main = 0;
   else if (!strcmp (p, "-Wsign-compare"))
     warn_sign_compare = 1;
   else if (!strcmp (p, "-Wno-sign-compare"))
     warn_sign_compare = 0;
+  else if (!strcmp (p, "-Wunknown-pragmas"))
+    /* Set to greater than 1, so that even unknown pragmas in system
+       headers will be warned about.  */
+    warn_unknown_pragmas = 2;
+  else if (!strcmp (p, "-Wno-unknown-pragmas"))
+    warn_unknown_pragmas = 0;
   else if (!strcmp (p, "-Wall"))
     {
       /* We save the value of warn_uninitialized, since if they put
@@ -721,7 +783,8 @@ c_decode_option (p)
         warning about not using it without also specifying -O.  */
       if (warn_uninitialized != 1)
        warn_uninitialized = 2;
-      warn_implicit = 1;
+      warn_implicit_int = 1;
+      mesg_implicit_function_declaration = 1;
       warn_return_type = 1;
       warn_unused = 1;
       warn_switch = 1;
@@ -729,7 +792,11 @@ c_decode_option (p)
       warn_char_subscripts = 1;
       warn_parentheses = 1;
       warn_missing_braces = 1;
-      warn_sign_compare = 1;
+      /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding can turn
+        it off only if it's not explicit.  */
+      warn_main = 2;
+      /* Only warn about unknown pragmas that are not in system headers.  */
+      warn_unknown_pragmas = 1;
     }
   else
     return 0;
@@ -1003,7 +1070,7 @@ poplevel (keep, reverse, functionbody)
        if (DECL_ABSTRACT_ORIGIN (decl) != 0
            && DECL_ABSTRACT_ORIGIN (decl) != decl)
          TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-       else
+       else if (DECL_SAVED_INSNS (decl) != 0)
          {
            push_function_context ();
            output_inline_function (decl);
@@ -1324,6 +1391,10 @@ pushtag (name, type)
      tagged type.  */
 
   TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
+
+  /* An approximation for now, so we can tell this is a function-scope tag.
+     This will be updated in poplevel.  */
+  TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
 }
 \f
 /* Handle when a new declaration NEWDECL
@@ -1350,7 +1421,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   char *errmsg = 0;
 
   if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
-    DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
+    DECL_MACHINE_ATTRIBUTES (newdecl)
+      =  merge_machine_decl_attributes (olddecl, newdecl);
 
   if (TREE_CODE (newtype) == ERROR_MARK
       || TREE_CODE (oldtype) == ERROR_MARK)
@@ -1702,7 +1774,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
   /* Optionally warn about more than one declaration for the same name.  */
   if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0
-      /* Dont warn about a function declaration
+      /* Don't warn about a function declaration
         followed by a definition.  */
       && !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
           && DECL_INITIAL (olddecl) == 0)
@@ -1906,17 +1978,20 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+         if (DECL_INLINE (newdecl))
+           DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
        }
     }
   if (different_binding_level)
     {
-      /* Don't output a duplicate symbol for this declaration.  */
-      TREE_ASM_WRITTEN (newdecl) = 1;
+      /* Don't output a duplicate symbol or debugging information for this
+        declaration.  */
+      TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
       return 0;
     }
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
-     But preserve OLDdECL's DECL_UID.  */
+     But preserve OLDDECL's DECL_UID.  */
   {
     register unsigned olddecl_uid = DECL_UID (olddecl);
 
@@ -1926,6 +2001,10 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
     DECL_UID (olddecl) = olddecl_uid;
   }
 
+  /* NEWDECL contains the merged attribute lists.
+     Update OLDDECL to be the same.  */
+  DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+
   return 1;
 }
 
@@ -2010,6 +2089,7 @@ pushdecl (x)
             DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)),
             "previous declaration of `%s'",
             IDENTIFIER_POINTER (name));
+         TREE_THIS_VOLATILE (name) = 1;
        }
 
       if (t != 0 && duplicate_decls (x, t, different_binding_level))
@@ -2043,7 +2123,7 @@ pushdecl (x)
                MY_TYPE object;
 
         Later parts of the compiler might only know that `object' was of
-        type `struct S' if if were not for code just below.  With this
+        type `struct S' if it were not for code just below.  With this
         code however, later parts of the compiler see something like:
 
                struct S' == struct S
@@ -2074,7 +2154,8 @@ pushdecl (x)
              if (TYPE_NAME (TREE_TYPE (x)) == 0)
                TYPE_NAME (TREE_TYPE (x)) = x;
             }
-          else if (TREE_TYPE (x) != error_mark_node)
+          else if (TREE_TYPE (x) != error_mark_node
+                  && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
             {
               tree tt = TREE_TYPE (x);
              DECL_ORIGINAL_TYPE (x) = tt;
@@ -2212,8 +2293,11 @@ pushdecl (x)
              else if (TREE_CODE (x) == TYPE_DECL)
                ;
              else if (IDENTIFIER_IMPLICIT_DECL (name))
-               pedwarn ("`%s' was declared implicitly `extern' and later `static'",
-                        IDENTIFIER_POINTER (name));
+               {
+                 if (! TREE_THIS_VOLATILE (name))
+                   pedwarn ("`%s' was declared implicitly `extern' and later `static'",
+                            IDENTIFIER_POINTER (name));
+               }
              else
                pedwarn ("`%s' was declared `extern' and later `static'",
                         IDENTIFIER_POINTER (name));
@@ -2429,9 +2513,15 @@ implicitly_declare (functionid)
 
   rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
 
-  if (warn_implicit && implicit_warning)
-    warning ("implicit declaration of function `%s'",
-            IDENTIFIER_POINTER (functionid));
+  if (mesg_implicit_function_declaration && implicit_warning)
+    {
+      if (mesg_implicit_function_declaration == 2)
+        error ("implicit declaration of function `%s'",
+                 IDENTIFIER_POINTER (functionid));
+      else
+        warning ("implicit declaration of function `%s'",
+                 IDENTIFIER_POINTER (functionid));
+    }
   else if (warn_traditional && traditional_warning)
     warning ("function `%s' was previously declared within a block",
             IDENTIFIER_POINTER (functionid));
@@ -2811,7 +2901,7 @@ init_decl_processing ()
   tree traditional_ptr_type_node;
   /* Data types of memcpy and strlen.  */
   tree memcpy_ftype, memset_ftype, strlen_ftype;
-  tree void_ftype_any;
+  tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
   int wchar_type_size;
   tree temp;
   tree array_domain_type;
@@ -2870,25 +2960,15 @@ init_decl_processing ()
   /* `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.  */
-  sizetype
-    = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE)));
+     and this must agree, even if long and int are the same size.  */
+  set_sizetype
+    (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
   if (flag_traditional && TREE_UNSIGNED (sizetype))
-    sizetype = signed_type (sizetype);
+    set_sizetype (signed_type (sizetype));
 
   ptrdiff_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
 
-  TREE_TYPE (TYPE_SIZE (integer_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (char_type_node)) = sizetype;
-  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;
-  TREE_TYPE (TYPE_SIZE (short_integer_type_node)) = sizetype;
-  TREE_TYPE (TYPE_SIZE (short_unsigned_type_node)) = sizetype;
-
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
@@ -2913,6 +2993,9 @@ init_decl_processing ()
   intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
 
+  intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
+
   unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
 
@@ -2925,6 +3008,9 @@ init_decl_processing ()
   unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
 
+  unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+
   float_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
   pushdecl (build_decl (TYPE_DECL, ridpointers[(int) RID_FLOAT],
@@ -3127,6 +3213,11 @@ init_decl_processing ()
                                                            sizetype,
                                                            endlink))));
 
+  ptr_ftype_void = build_function_type (ptr_type_node, endlink);
+  ptr_ftype_ptr
+    = build_function_type (ptr_type_node,
+                          tree_cons (NULL_TREE, ptr_type_node, endlink));
+
   builtin_function ("__builtin_constant_p", default_function_type,
                    BUILT_IN_CONSTANT_P, NULL_PTR);
 
@@ -3144,6 +3235,42 @@ init_decl_processing ()
                                                    endlink)),
                    BUILT_IN_FRAME_ADDRESS, NULL_PTR);
 
+  builtin_function ("__builtin_aggregate_incoming_address",
+                   build_function_type (ptr_type_node, NULL_TREE),
+                   BUILT_IN_AGGREGATE_INCOMING_ADDRESS, NULL_PTR);
+
+  /* Hooks for the DWARF 2 __throw routine.  */
+  builtin_function ("__builtin_unwind_init",
+                   build_function_type (void_type_node, endlink),
+                   BUILT_IN_UNWIND_INIT, NULL_PTR);
+  builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
+  builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
+  builtin_function ("__builtin_dwarf_fp_regnum",
+                   build_function_type (unsigned_type_node, endlink),
+                   BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
+  builtin_function ("__builtin_dwarf_reg_size", int_ftype_int,
+                   BUILT_IN_DWARF_REG_SIZE, NULL_PTR);             
+  builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
+                   BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
+  builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
+                   BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
+  builtin_function ("__builtin_set_return_addr_reg",
+                   build_function_type (void_type_node, 
+                                        tree_cons (NULL_TREE,
+                                                   ptr_type_node,
+                                                   endlink)),
+                   BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
+  builtin_function ("__builtin_eh_stub", ptr_ftype_void,
+                   BUILT_IN_EH_STUB, NULL_PTR);
+  builtin_function
+    ("__builtin_set_eh_regs",
+     build_function_type (void_type_node,
+                         tree_cons (NULL_TREE, ptr_type_node,
+                                    tree_cons (NULL_TREE,
+                                               type_for_mode (ptr_mode, 0),
+                                               endlink))),
+     BUILT_IN_SET_EH_REGS, NULL_PTR);
+
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
                                         tree_cons (NULL_TREE,
@@ -3236,7 +3363,7 @@ init_decl_processing ()
   builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
                    BUILT_IN_MEMCMP, "memcmp");
   builtin_function ("__builtin_memset", memset_ftype,
-                   BUILT_IN_MEMSET, NULL_PTR);
+                   BUILT_IN_MEMSET, "memset");
   builtin_function ("__builtin_strcmp", int_ftype_string_string,
                    BUILT_IN_STRCMP, "strcmp");
   builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
@@ -3333,8 +3460,6 @@ init_decl_processing ()
                    BUILT_IN_FMOD, NULL_PTR);
   builtin_function ("__builtin_frem", double_ftype_double_double,
                    BUILT_IN_FREM, NULL_PTR);
-  builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int,
-                   BUILT_IN_MEMSET, NULL_PTR);
   builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
                    NULL_PTR);
   builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
@@ -3420,9 +3545,14 @@ shadow_tag_warned (declspecs, warned)
 {
   int found_tag = 0;
   register tree link;
+  tree specs, attrs;
 
   pending_invalid_xref = 0;
 
+  /* Remove the attributes from declspecs, since they will confuse the
+     following code.  */
+  split_specs_attrs (declspecs, &specs, &attrs);
+
   for (link = declspecs; link; link = TREE_CHAIN (link))
     {
       register tree value = TREE_VALUE (link);
@@ -3536,6 +3666,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* The corresponding pop_obstacks is in finish_decl.  */
   push_obstacks_nochange ();
 
+  if (warn_main && !strcmp (IDENTIFIER_POINTER (declarator), "main"))
+    warning_with_decl (decl, "`%s' is usually a function");
+
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
@@ -3780,7 +3913,7 @@ finish_decl (decl, init, asmspec_tree)
                 declaration into a file scope one.  This can be detected
                 by TREE_ASM_WRITTEN being set.  */
                (DECL_INITIAL (decl) != 0
-                || DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl))
+                || (DECL_CONTEXT (decl) != 0 && ! TREE_ASM_WRITTEN (decl)))
              :
                /* An automatic variable with an incomplete type
                   is an error.  */
@@ -3798,6 +3931,9 @@ finish_decl (decl, init, asmspec_tree)
          else
            error_with_decl (decl, "storage size of `%s' isn't constant");
        }
+
+      if (TREE_USED  (type))
+       TREE_USED (decl) = 1;
     }
 
   /* If this is a function and an assembler name is specified, it isn't
@@ -4066,12 +4202,6 @@ 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.  */
@@ -4277,10 +4407,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   if (type == 0)
     {
-      if (funcdef_flag && warn_return_type
-         && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
-                           | (1 << (int) RID_SIGNED) | (1 << (int) RID_UNSIGNED))))
-       warn_about_return_type = 1;
+      if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
+                         | (1 << (int) RID_SIGNED)
+                         | (1 << (int) RID_UNSIGNED))))
+         && ! (in_system_header && ! allocation_temporary_p ()))
+       {
+         /* C9x will probably require a diagnostic here.
+            For now, issue a warning if -Wreturn-type and this is a function,
+            or if -Wimplicit; prefer the former warning since it is more
+            explicit.  */
+         if ((warn_implicit_int || warn_return_type) && funcdef_flag)
+           warn_about_return_type = 1;
+         else if (warn_implicit_int)
+           warning ("type defaults to `int' in declaration of `%s'", name);
+       }
+
       defaulted_int = 1;
       type = integer_type_node;
     }
@@ -4290,7 +4431,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   /* Long double is a special combination.  */
 
-  if ((specbits & 1 << (int) RID_LONG)
+  if ((specbits & 1 << (int) RID_LONG) && ! longlong
       && TYPE_MAIN_VARIANT (type) == double_type_node)
     {
       specbits &= ~ (1 << (int) RID_LONG);
@@ -4304,11 +4445,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       int ok = 0;
 
-      if (TREE_CODE (type) != INTEGER_TYPE)
-       error ("long, short, signed or unsigned invalid for `%s'", name);
-      else if ((specbits & 1 << (int) RID_LONG)
-              && (specbits & 1 << (int) RID_SHORT))
-       error ("long and short specified together for `%s'", name);
+      if ((specbits & 1 << (int) RID_LONG)
+         && (specbits & 1 << (int) RID_SHORT))
+       error ("both long and short specified for `%s'", name);
       else if (((specbits & 1 << (int) RID_LONG)
                || (specbits & 1 << (int) RID_SHORT))
               && explicit_char)
@@ -4316,10 +4455,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (((specbits & 1 << (int) RID_LONG)
                || (specbits & 1 << (int) RID_SHORT))
               && TREE_CODE (type) == REAL_TYPE)
-       error ("long or short specified with floating type for `%s'", name);
+       {
+         static int already = 0;
+
+         error ("long or short specified with floating type for `%s'", name);
+         if (! already && ! pedantic)
+           {
+             error ("the only valid combination is `long double'");
+             already = 1;
+           }
+       }
       else if ((specbits & 1 << (int) RID_SIGNED)
               && (specbits & 1 << (int) RID_UNSIGNED))
-       error ("signed and unsigned given together for `%s'", name);
+       error ("both signed and unsigned specified for `%s'", name);
+      else if (TREE_CODE (type) != INTEGER_TYPE)
+       error ("long, short, signed or unsigned invalid for `%s'", name);
       else
        {
          ok = 1;
@@ -4614,6 +4764,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                   convert (index_type, size),
                                   convert (index_type, size_one_node)));
 
+             /* If that overflowed, the array is too big.
+                ??? While a size of INT_MAX+1 technically shouldn't cause
+                an overflow (because we subtract 1), the overflow is recorded
+                during the conversion to index_type, before the subtraction.
+                Handling this case seems like an unnecessary complication.  */
+             if (TREE_OVERFLOW (itype))
+               {
+                 error ("size of array `%s' is too large", name);
+                 type = error_mark_node;
+                 continue;
+               }
+
              if (size_varies)
                itype = variable_size (itype);
              itype = build_index_type (itype);
@@ -4732,7 +4894,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          {
            register tree link;
 
-           for (link = current_function_parm_tags;
+           for (link = last_function_parm_tags;
                 link;
                 link = TREE_CHAIN (link))
              TYPE_CONTEXT (TREE_VALUE (link)) = type;
@@ -4789,6 +4951,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
   /* Now TYPE has the actual type.  */
 
+  /* Did array size calculations overflow?  */
+
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_SIZE (type)
+      && TREE_OVERFLOW (TYPE_SIZE (type)))
+    error ("size of array `%s' is too large", name);
+
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
 
   if (specbits & (1 << (int) RID_TYPEDEF))
@@ -4985,6 +5154,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ANSI C forbids const or volatile functions");
 
+       if (pedantic
+           && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
+           && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
+               || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
+           && ! DECL_IN_SYSTEM_HEADER (decl))
+         pedwarn ("ANSI C forbids const or volatile void function return type");
+
        if (volatilep
            && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
          warning ("`noreturn' function returns non-void value");
@@ -5002,9 +5178,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
 
            if (! strcmp (IDENTIFIER_POINTER (declarator), "main"))
              warning ("cannot inline function `main'");
-           else if (last && (TYPE_MAIN_VARIANT (TREE_VALUE (last))
-                             != void_type_node))
-             warning ("inline declaration ignored for function with `...'");
            else
              /* Assume that otherwise the function can be inlined.  */
              DECL_INLINE (decl) = 1;
@@ -5324,7 +5497,7 @@ parmlist_tags_warning ()
       enum tree_code code = TREE_CODE (TREE_VALUE (elt));
       /* An anonymous union parm type is meaningful as a GNU extension.
         So don't warn for that.  */
-      if (code == UNION_TYPE && !pedantic)
+      if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
        continue;
       if (TREE_PURPOSE (elt) != 0)
        warning ("`%s %s' declared inside parameter list",
@@ -5427,6 +5600,7 @@ start_struct (code, name)
   if (ref && TREE_CODE (ref) == code)
     {
       C_TYPE_BEING_DEFINED (ref) = 1;
+      TYPE_PACKED (ref) = flag_pack_struct;
       if (TYPE_FIELDS (ref))
        error ((code == UNION_TYPE ? "redefinition of `union %s'"
                : "redefinition of `struct %s'"),
@@ -5475,9 +5649,12 @@ grokfield (filename, line, declarator, declspecs, width)
 /* Function to help qsort sort FIELD_DECLs by name order.  */
 
 static int
-field_decl_cmp (x, y)
-     tree *x, *y;
+field_decl_cmp (xp, yp)
+     const GENERIC_PTR xp;
+     const GENERIC_PTR yp;
 {
+  tree *x = (tree *)xp, *y = (tree *)yp;
+
   if (DECL_NAME (*x) == DECL_NAME (*y))
     return 0;
   if (DECL_NAME (*x) == NULL)
@@ -5665,7 +5842,7 @@ finish_struct (t, fieldlist, attributes)
        }
       else if (TREE_TYPE (x) != error_mark_node)
        {
-         int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
+         unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
                           : TYPE_ALIGN (TREE_TYPE (x)));
          /* Non-bit-fields are aligned for their type, except packed
             fields which require only BITS_PER_UNIT alignment.  */
@@ -6105,7 +6282,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == 0)
-    return 0;
+    {
+      immediate_size_expand = old_immediate_size_expand;
+      return 0;
+    }
 
   decl_attributes (decl1, prefix_attributes, attributes);
 
@@ -6198,6 +6378,67 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   if (current_function_decl != 0)
     TREE_PUBLIC (decl1) = 0;
 
+  /* Warn for unlikely, improbable, or stupid declarations of `main'. */
+  if (warn_main
+      && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+    {
+      tree args;
+      int argct = 0;
+
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
+          != integer_type_node)
+       pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
+
+      for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
+          args = TREE_CHAIN (args))
+       {
+         tree type = args ? TREE_VALUE (args) : 0;
+
+         if (type == void_type_node)
+           break;
+
+         ++argct;
+         switch (argct)
+           {
+           case 1:
+             if (TYPE_MAIN_VARIANT (type) != integer_type_node)
+               pedwarn_with_decl (decl1,
+                                  "first argument of `%s' should be `int'");
+             break;
+
+           case 2:
+             if (TREE_CODE (type) != POINTER_TYPE
+                 || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+                 || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
+                     != char_type_node))
+               pedwarn_with_decl (decl1,
+                              "second argument of `%s' should be `char **'");
+             break;
+
+           case 3:
+             if (TREE_CODE (type) != POINTER_TYPE
+                 || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
+                 || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
+                     != char_type_node))
+               pedwarn_with_decl (decl1,
+                  "third argument of `%s' should probably be `char **'");
+             break;
+           }
+       }
+
+      /* It is intentional that this message does not mention the third
+        argument, which is warned for only pedantically, because it's
+        blessed by mention in an appendix of the standard. */
+      if (argct > 0 && (argct < 2 || argct > 3))
+       pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
+
+      if (argct == 3 && pedantic)
+       pedwarn_with_decl (decl1, "third argument of `%s' is deprecated");
+
+      if (! TREE_PUBLIC (decl1))
+       pedwarn_with_decl (decl1, "`%s' is normally a non-static function");
+    }
+
   /* Record the decl so that the function name is defined.
      If we already have a decl for this name, and it is a FUNCTION_DECL,
      use the old decl.  */
@@ -6854,7 +7095,16 @@ finish_function (nested)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
          != integer_type_node)
-       pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
+       {
+         /* You would expect the sense of this test to be the other way
+            around, but if warn_main is set, we will already have warned,
+            so this would be a duplicate.  This is the warning you get
+            in some environments even if you *don't* ask for it, because
+            these are environments where it may be more of a problem than
+            usual.  */
+         if (! warn_main)
+           pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
+       }
       else
        {
 #ifdef DEFAULT_MAIN_RETURN