OSDN Git Service

* cp-tree.h (finish_unary_op_expr): New function.
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 8e04798..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,8 +457,12 @@ 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. */
+   being traditional.  */
 int flag_allow_single_precision = 0;
 
 /* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
@@ -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;
+
+/* Nonzero means message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
 
-int warn_implicit;
+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
@@ -525,7 +537,7 @@ int warn_redundant_decls = 0;
 
 int warn_nested_externs = 0;
 
-/* Warn about *printf or *scanf format/argument anomalies. */
+/* Warn about *printf or *scanf format/argument anomalies.  */
 
 int warn_format;
 
@@ -545,17 +557,25 @@ 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_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;
+int warn_sign_compare = -1;
 
-/* Nonzero means `$' can be in an identifier.
-   See cccp.c for reasons why this breaks some obscure ANSI C programs.  */
+/* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
 #define DOLLARS_IN_IDENTIFIERS 1
 #endif
-int dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 1;
+int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 
 /* Decode the string P as a language-specific option for C.
    Return 1 if it is recognized (and handle it);
@@ -569,24 +589,29 @@ c_decode_option (p)
     {
       flag_traditional = 1;
       flag_writable_strings = 1;
-#if DOLLARS_IN_IDENTIFIERS > 0
-      dollars_in_ident = 1;
-#endif
     }
   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;
       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
-    }
+    dollars_in_ident = 1;
   else if (!strcmp (p, "-fno-dollars-in-identifiers"))
     dollars_in_ident = 0;
   else if (!strcmp (p, "-fsigned-char"))
@@ -634,11 +659,25 @@ c_decode_option (p)
   else if (!strcmp (p, "-fident"))
     flag_no_ident = 0;
   else if (!strcmp (p, "-ansi"))
-    flag_no_asm = 1, flag_no_nonansi_builtin = 1, dollars_in_ident = 0;
+    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"))
@@ -711,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"))
@@ -719,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
@@ -730,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;
@@ -738,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;
@@ -1012,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);
@@ -1333,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
@@ -1359,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)
@@ -1711,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)
@@ -1915,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);
 
@@ -1935,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;
 }
 
@@ -2007,6 +2077,7 @@ pushdecl (x)
          /* Don't test for DECL_EXTERNAL, because grokdeclarator
             sets this for all functions.  */
          && ! TREE_PUBLIC (x)
+         && (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level)
          /* We used to warn also for explicit extern followed by static,
             but sometimes you need to do it that way.  */
          && IDENTIFIER_IMPLICIT_DECL (name) != 0)
@@ -2018,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))
@@ -2051,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
@@ -2082,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;
@@ -2220,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));
@@ -2437,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));
@@ -2807,7 +2889,7 @@ lookup_name_current_level (name)
 }
 \f
 /* Create the predefined scalar types of C,
-   and some nodes representing standard constants (0, 1, (void *)0).
+   and some nodes representing standard constants (0, 1, (void *) 0).
    Initialize the global binding level.
    Make definitions for built-in primitive functions.  */
 
@@ -2818,8 +2900,8 @@ init_decl_processing ()
   /* Either char* or void*.  */
   tree traditional_ptr_type_node;
   /* Data types of memcpy and strlen.  */
-  tree memcpy_ftype, strlen_ftype;
-  tree void_ftype_any;
+  tree memcpy_ftype, memset_ftype, strlen_ftype;
+  tree void_ftype_any, ptr_ftype_void, ptr_ftype_ptr;
   int wchar_type_size;
   tree temp;
   tree array_domain_type;
@@ -2867,37 +2949,29 @@ init_decl_processing ()
   pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
                        long_long_unsigned_type_node));
 
+  short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
+                       short_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));
+
   /* `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;
-
   error_mark_node = make_node (ERROR_MARK);
   TREE_TYPE (error_mark_node) = error_mark_node;
 
-  short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
-                       short_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));
-
   /* 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"),
@@ -2919,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));
 
@@ -2931,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],
@@ -3125,6 +3205,19 @@ init_decl_processing ()
                                                            sizetype,
                                                            endlink))));
 
+  memset_ftype /* memset prototype */
+    = build_function_type (traditional_ptr_type_node,
+                          tree_cons (NULL_TREE, ptr_type_node,
+                                     tree_cons (NULL_TREE, integer_type_node,
+                                                tree_cons (NULL_TREE,
+                                                           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);
 
@@ -3142,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,
@@ -3233,6 +3362,8 @@ init_decl_processing ()
                    BUILT_IN_MEMCPY, "memcpy");
   builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
                    BUILT_IN_MEMCMP, "memcmp");
+  builtin_function ("__builtin_memset", memset_ftype,
+                   BUILT_IN_MEMSET, "memset");
   builtin_function ("__builtin_strcmp", int_ftype_string_string,
                    BUILT_IN_STRCMP, "strcmp");
   builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
@@ -3286,6 +3417,7 @@ init_decl_processing ()
       builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR);
       builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
                        NULL_PTR);
+      builtin_function ("memset", memset_ftype, BUILT_IN_MEMSET, NULL_PTR);
       builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
                        NULL_PTR);
       builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
@@ -3328,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,
@@ -3415,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);
@@ -3531,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
@@ -3775,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.  */
@@ -3793,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
@@ -4061,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.  */
@@ -4272,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;
     }
@@ -4285,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);
@@ -4299,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)
@@ -4311,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;
@@ -4609,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);
@@ -4727,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;
@@ -4784,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))
@@ -4980,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");
@@ -4997,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;
@@ -5319,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",
@@ -5422,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'"),
@@ -5470,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)
@@ -5522,9 +5704,17 @@ finish_struct (t, fieldlist, attributes)
 
   old_momentary = suspend_momentary ();
 
-  if (fieldlist == 0 && pedantic)
-    pedwarn ((TREE_CODE (t) == UNION_TYPE ? "union has no members"
-             : "structure has no members"));
+  if (pedantic)
+    {
+      for (x = fieldlist; x; x = TREE_CHAIN (x))
+       if (DECL_NAME (x) != 0)
+         break;
+
+      if (x == 0)
+       pedwarn ("%s has no %smembers",
+                (TREE_CODE (t) == UNION_TYPE ? "union" : "structure"),
+                (fieldlist ? "named " : ""));
+    }
 
   /* Install struct as DECL_CONTEXT of each field decl.
      Also process specified field sizes.
@@ -5644,14 +5834,15 @@ finish_struct (t, fieldlist, attributes)
              DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
 #endif
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-             DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
-                                   TYPE_ALIGN (TREE_TYPE (x)));
+             if (PCC_BITFIELD_TYPE_MATTERS)
+               DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
+                                     TYPE_ALIGN (TREE_TYPE (x)));
 #endif
            }
        }
       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.  */
@@ -6075,7 +6266,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
   tree restype;
   int old_immediate_size_expand = immediate_size_expand;
 
-  current_function_returns_value = 0;  /* Assume, until we see it does. */
+  current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
@@ -6091,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);
 
@@ -6184,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.  */
@@ -6840,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