OSDN Git Service

For gcc:
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 1b040b1..97db33f 100644 (file)
@@ -1,5 +1,5 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -37,9 +37,7 @@ Boston, MA 02111-1307, USA.  */
 
 #if USE_CPPLIB
 #include "cpplib.h"
-extern cpp_reader  parse_in;
-extern cpp_options parse_options;
-static int cpp_initialized;
+extern cpp_reader parse_in;
 #endif
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
@@ -125,6 +123,14 @@ tree unsigned_type_node;
 tree long_unsigned_type_node;
 tree long_long_unsigned_type_node;
 
+/* These are used for integer literals that are larger than 
+   a long long.  The largest integer literals we can handle
+   are the width of two HOST_WIDE_INTs.  If two HOST_WIDE_INTs
+   are not larger than the target's long long, then these
+   will never be used. */
+tree widest_integer_literal_type_node;
+tree widest_unsigned_literal_type_node;
+
 tree boolean_type_node;
 tree boolean_false_node;
 tree boolean_true_node;
@@ -151,13 +157,17 @@ tree intQI_type_node;
 tree intHI_type_node;
 tree intSI_type_node;
 tree intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
 tree intTI_type_node;
+#endif
 
 tree unsigned_intQI_type_node;
 tree unsigned_intHI_type_node;
 tree unsigned_intSI_type_node;
 tree unsigned_intDI_type_node;
+#if HOST_BITS_PER_WIDE_INT >= 64
 tree unsigned_intTI_type_node;
+#endif
 
 /* a VOID_TYPE node.  */
 
@@ -424,7 +434,7 @@ tree static_ctors, static_dtors;
 static struct binding_level * make_binding_level       PROTO((void));
 static void clear_limbo_values         PROTO((tree));
 static int duplicate_decls             PROTO((tree, tree, int));
-static char *redeclaration_error_message PROTO((tree, tree));
+static int redeclaration_error_message PROTO((tree, tree));
 static void storedecls                 PROTO((tree));
 static void storetags                  PROTO((tree));
 static tree lookup_tag                 PROTO((enum tree_code, tree,
@@ -464,6 +474,10 @@ int flag_no_nonansi_builtin;
 
 int flag_traditional;
 
+/* Nonzero means use the ISO C9x dialect of C.  */
+
+int flag_isoc9x = 0;
+
 /* Nonzero means that we have builtin functions, and main is an int */
 
 int flag_hosted = 1;
@@ -477,10 +491,6 @@ int flag_allow_single_precision = 0;
 int flag_signed_bitfields = 1;
 int explicit_flag_signed_bitfields = 0;
 
-/* Nonzero means handle `#ident' directives.  0 means ignore them.  */
-
-int flag_no_ident = 0;
-
 /* Nonzero means warn about use of implicit int. */
 
 int warn_implicit_int;
@@ -498,7 +508,7 @@ int mesg_implicit_function_declaration;
    to get extra warnings from them.  These warnings will be too numerous
    to be useful, except in thoroughly ANSIfied programs.  */
 
-int warn_write_strings;
+int flag_const_strings;
 
 /* Nonzero means warn about pointer casts that can drop a type qualifier
    from the pointer target type.  */
@@ -511,6 +521,10 @@ int warn_cast_qual;
 
 int warn_bad_function_cast;
 
+/* Warn about functions which might be candidates for attribute noreturn. */
+
+int warn_missing_noreturn;
+
 /* Warn about traditional constructs whose meanings changed in ANSI C.  */
 
 int warn_traditional;
@@ -597,19 +611,12 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
    
 int
 c_decode_option (argc, argv)
-     int argc;
+     int argc ATTRIBUTE_UNUSED;
      char **argv;
 {
   int strings_processed;
   char *p = argv[0];
 #if USE_CPPLIB
-  if (! cpp_initialized)
-    {
-      cpp_reader_init (&parse_in);
-      parse_in.data = &parse_options;
-      cpp_options_init (&parse_options);
-      cpp_initialized = 1;
-    }
   strings_processed = cpp_handle_option (&parse_in, argc, argv);
 #else
   strings_processed = 0;
@@ -640,6 +647,63 @@ c_decode_option (argc, argv)
       flag_traditional = 0;
       flag_writable_strings = 0;
     }
+  else if (!strncmp (p, "-std=", 5))
+    {
+      /* Select the appropriate language standard.  We currently
+        recognize:
+        -std=iso9899:1990      same as -ansi
+        -std=iso9899:199409    ISO C as modified in amend. 1
+        -std=iso9899:199x      ISO C 9x
+        -std=c89               same as -std=iso9899:1990
+        -std=c9x               same as -std=iso9899:199x
+        -std=gnu89             default, iso9899:1990 + gnu extensions
+        -std=gnu9x             iso9899:199x + gnu extensions
+      */
+      const char *argstart = &p[5];
+
+      if (!strcmp (argstart, "iso9899:1990")
+         || !strcmp (argstart, "c89"))
+       {
+       iso_1990:
+         flag_traditional = 0;
+         flag_writable_strings = 0;
+         flag_no_asm = 1;
+         flag_no_nonansi_builtin = 1;
+         flag_isoc9x = 0;
+       }
+      else if (!strcmp (argstart, "iso9899:199409"))
+       {
+         /* ??? The changes since ISO C 1990 are not supported.  */
+         goto iso_1990;
+       }
+      else if (!strcmp (argstart, "iso9899:199x")
+              || !strcmp (argstart, "c9x"))
+       {
+         flag_traditional = 0;
+         flag_writable_strings = 0;
+         flag_no_asm = 1;
+         flag_no_nonansi_builtin = 1;
+         flag_isoc9x = 1;
+       }
+      else if (!strcmp (argstart, "gnu89"))
+       {
+         flag_traditional = 0;
+         flag_writable_strings = 0;
+         flag_no_asm = 0;
+         flag_no_nonansi_builtin = 0;
+         flag_isoc9x = 0;
+       }
+      else if (!strcmp (argstart, "gnu9x"))
+       {
+         flag_traditional = 0;
+         flag_writable_strings = 0;
+         flag_no_asm = 0;
+         flag_no_nonansi_builtin = 0;
+         flag_isoc9x = 1;
+       }
+      else
+       error ("unknown C standard `%s'", argstart);
+    }
   else if (!strcmp (p, "-fdollars-in-identifiers"))
     dollars_in_ident = 1;
   else if (!strcmp (p, "-fno-dollars-in-identifiers"))
@@ -684,12 +748,8 @@ c_decode_option (argc, argv)
     flag_no_builtin = 0;
   else if (!strcmp (p, "-fno-builtin"))
     flag_no_builtin = 1;
-  else if (!strcmp (p, "-fno-ident"))
-    flag_no_ident = 1;
-  else if (!strcmp (p, "-fident"))
-    flag_no_ident = 0;
   else if (!strcmp (p, "-ansi"))
-    flag_no_asm = 1, flag_no_nonansi_builtin = 1;
+    goto iso_1990;
   else if (!strcmp (p, "-Werror-implicit-function-declaration"))
     mesg_implicit_function_declaration = 2;
   else if (!strcmp (p, "-Wimplicit-function-declaration"))
@@ -713,9 +773,9 @@ c_decode_option (argc, argv)
   else if (!strcmp (p, "-Wno-long-long"))
     warn_long_long = 0;
   else if (!strcmp (p, "-Wwrite-strings"))
-    warn_write_strings = 1;
+    flag_const_strings = 1;
   else if (!strcmp (p, "-Wno-write-strings"))
-    warn_write_strings = 0;
+    flag_const_strings = 0;
   else if (!strcmp (p, "-Wcast-qual"))
     warn_cast_qual = 1;
   else if (!strcmp (p, "-Wno-cast-qual"))
@@ -724,6 +784,10 @@ c_decode_option (argc, argv)
     warn_bad_function_cast = 1;
   else if (!strcmp (p, "-Wno-bad-function-cast"))
     warn_bad_function_cast = 0;
+  else if (!strcmp (p, "-Wmissing-noreturn"))
+    warn_missing_noreturn = 1;
+  else if (!strcmp (p, "-Wno-missing-noreturn"))
+    warn_missing_noreturn = 0;
   else if (!strcmp (p, "-Wpointer-arith"))
     warn_pointer_arith = 1;
   else if (!strcmp (p, "-Wno-pointer-arith"))
@@ -799,7 +863,7 @@ c_decode_option (argc, argv)
   else if (!strcmp (p, "-Wmain"))
     warn_main = 1;
   else if (!strcmp (p, "-Wno-main"))
-    warn_main = 0;
+    warn_main = -1;
   else if (!strcmp (p, "-Wsign-compare"))
     warn_sign_compare = 1;
   else if (!strcmp (p, "-Wno-sign-compare"))
@@ -942,7 +1006,7 @@ kept_level_p ()
 
 void
 declare_parm_level (definition_flag)
-     int definition_flag;
+     int definition_flag ATTRIBUTE_UNUSED;
 {
   current_binding_level->parm_flag = 1;
 }
@@ -1059,24 +1123,22 @@ poplevel (keep, reverse, functionbody)
     if (TYPE_SIZE (TREE_VALUE (link)) == 0)
       {
        tree type = TREE_VALUE (link);
-       char *errmsg;
+       tree type_name = TYPE_NAME (type);
+       char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
+                                      ? type_name
+                                      : DECL_NAME (type_name));
        switch (TREE_CODE (type))
          {
          case RECORD_TYPE:
-           errmsg = "`struct %s' incomplete in scope ending here";
+           error ("`struct %s' incomplete in scope ending here", id);
            break;
          case UNION_TYPE:
-           errmsg = "`union %s' incomplete in scope ending here";
+           error ("`union %s' incomplete in scope ending here", id);
            break;
          case ENUMERAL_TYPE:
-           errmsg = "`enum %s' incomplete in scope ending here";
+           error ("`enum %s' incomplete in scope ending here", id);
            break;
          }
-       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-         error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
-       else
-         /* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL.  */
-         error (errmsg, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
       }
 #endif /* 0 */
 
@@ -1456,7 +1518,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                           && DECL_INITIAL (newdecl) != 0);
   tree oldtype = TREE_TYPE (olddecl);
   tree newtype = TREE_TYPE (newdecl);
-  char *errmsg = 0;
+  int errmsg = 0;
 
   if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
     DECL_MACHINE_ATTRIBUTES (newdecl)
@@ -1683,16 +1745,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              if (TREE_CHAIN (t) == 0
                  && TYPE_MAIN_VARIANT (type) != void_type_node)
                {
-                 error ("A parameter list with an ellipsis can't match");
-                 error ("an empty parameter name list declaration.");
+                 error ("A parameter list with an ellipsis can't match an empty parameter name list declaration.");
                  break;
                }
 
              if (TYPE_MAIN_VARIANT (type) == float_type_node
                  || C_PROMOTING_INTEGER_TYPE_P (type))
                {
-                 error ("An argument type that has a default promotion");
-                 error ("can't match an empty parameter name list declaration.");
+                 error ("An argument type that has a default promotion can't match an empty parameter name list declaration.");
                  break;
                }
            }
@@ -1704,7 +1764,21 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
       errmsg = redeclaration_error_message (newdecl, olddecl);
       if (errmsg)
        {
-         error_with_decl (newdecl, errmsg);
+         switch (errmsg)
+           {
+           case 1:
+             error_with_decl (newdecl, "redefinition of `%s'");
+             break;
+           case 2:
+             error_with_decl (newdecl, "redeclaration of `%s'");
+             break;
+           case 3:
+             error_with_decl (newdecl, "conflicting declarations of `%s'");
+             break;
+           default:
+             abort ();
+           }
+
          error_with_decl (olddecl,
                           ((DECL_INITIAL (olddecl)
                             && current_binding_level == global_binding_level)
@@ -1736,14 +1810,22 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
               type = TYPE_ARG_TYPES (newtype),
               nargs = 1;
-              (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) != void_type_node
-               || TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node);
+              ;
               parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
            {
              if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
+                 && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
+               {
+                 warning_with_decl (newdecl, "prototype for `%s' follows");
+                 warning_with_decl (olddecl, "non-prototype definition here");
+                 break;
+               }
+             if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
                  || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
                {
-                 errmsg = "prototype for `%s' follows and number of arguments";
+                 error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match");
+                 error_with_decl (olddecl, "non-prototype definition here");
+                 errmsg = 1;
                  break;
                }
              /* Type for passing arg must be consistent
@@ -1755,21 +1837,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                         && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
                         && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
                {
-                 errmsg = "prototype for `%s' follows and argument %d";
+                 error_with_decl (newdecl,
+                                  "prototype for `%s' follows and argument %d doesn't match",
+                                  nargs);
+                 error_with_decl (olddecl, "non-prototype definition here");
+                 errmsg = 1;
                  break;
                }
            }
-         if (errmsg)
-           {
-             error_with_decl (newdecl, errmsg, nargs);
-             error_with_decl (olddecl,
-                              "doesn't match non-prototype definition here");
-           }
-         else
-           {
-             warning_with_decl (newdecl, "prototype for `%s' follows");
-             warning_with_decl (olddecl, "non-prototype definition here");
-           }
        }
       /* Warn about mismatches in various flags.  */
       else
@@ -1794,6 +1869,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              && !TREE_PUBLIC (newdecl))
            warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
 
+         /* If warn_traditional, warn when a non-static function
+            declaration follows a static one. */
+         if (warn_traditional
+             && TREE_CODE (olddecl) == FUNCTION_DECL
+             && !TREE_PUBLIC (olddecl)
+             && TREE_PUBLIC (newdecl))
+           warning_with_decl (newdecl, "non-static declaration for `%s' follows static");
+
          /* Warn when const declaration follows a non-const
             declaration, but not for functions.  */
          if (TREE_CODE (olddecl) != FUNCTION_DECL
@@ -1934,6 +2017,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
+         DECL_NO_CHECK_MEMORY_USAGE (newdecl)
+           |= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
        }
 
       pop_obstacks ();
@@ -2020,7 +2105,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
          if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
+           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
        }
     }
   if (different_binding_level)
@@ -2384,7 +2469,7 @@ pushdecl (x)
                      DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
                      DECL_RESULT (x) = DECL_RESULT (oldglobal);
                      TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
-                     DECL_ABSTRACT_ORIGIN (x) = oldglobal;
+                     DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal);
                    }
                  /* Inner extern decl is built-in if global one is.  */
                  if (DECL_BUILT_IN (oldglobal))
@@ -2457,7 +2542,7 @@ pushdecl (x)
                   /* No shadow warnings for vars made for inlining.  */
                   && ! DECL_FROM_INLINE (x))
            {
-             char *warnstring = 0;
+             char *id = IDENTIFIER_POINTER (name);
 
              if (TREE_CODE (x) == PARM_DECL
                  && current_binding_level->level_chain->parm_flag)
@@ -2468,15 +2553,12 @@ pushdecl (x)
                   but there is no way to tell it's not a definition.  */
                ;
              else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
-               warnstring = "declaration of `%s' shadows a parameter";
+               warning ("declaration of `%s' shadows a parameter", id);
              else if (oldlocal != 0)
-               warnstring = "declaration of `%s' shadows previous local";
+               warning ("declaration of `%s' shadows previous local", id);
              else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
                       && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-               warnstring = "declaration of `%s' shadows global declaration";
-
-             if (warnstring)
-               warning (warnstring, IDENTIFIER_POINTER (name));
+               warning ("declaration of `%s' shadows global declaration", id);
            }
 
          /* If storing a local value, there may already be one (inherited).
@@ -2587,10 +2669,10 @@ implicitly_declare (functionid)
 /* Return zero if the declaration NEWDECL is valid
    when the declaration OLDDECL (assumed to be for the same name)
    has already been seen.
-   Otherwise return an error message format string with a %s
-   where the identifier should go.  */
+   Otherwise return 1 if NEWDECL is a redefinition, 2 if it is a redeclaration,
+   and 3 if it is a conflicting declaration.  */
 
-static char *
+static int
 redeclaration_error_message (newdecl, olddecl)
      tree newdecl, olddecl;
 {
@@ -2609,7 +2691,7 @@ redeclaration_error_message (newdecl, olddecl)
        return 0;
       if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
        return 0;
-      return "redefinition of `%s'";
+      return 1;
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -2622,7 +2704,7 @@ redeclaration_error_message (newdecl, olddecl)
             time in another way is ok.  */
          && !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
               && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
-       return "redefinition of `%s'";
+       return 1;
       return 0;
     }
   else if (current_binding_level == global_binding_level)
@@ -2633,11 +2715,11 @@ redeclaration_error_message (newdecl, olddecl)
        return 0;
       /* Reject two definitions.  */
       if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
-       return "redefinition of `%s'";
+       return 1;
       /* Now we have two tentative defs, or one tentative and one real def.  */
       /* Insist that the linkage match.  */
       if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
-       return "conflicting declarations of `%s'";
+       return 3;
       return 0;
     }
   else if (current_binding_level->parm_flag
@@ -2651,7 +2733,7 @@ redeclaration_error_message (newdecl, olddecl)
         be an extern reference to olddecl.  */
       if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
          && DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
-       return "redeclaration of `%s'";
+       return 2;
       return 0;
     }
 }
@@ -3029,6 +3111,16 @@ init_decl_processing ()
   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
                        unsigned_char_type_node));
 
+  /* Create the widest literal types. */
+  widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
+                       widest_integer_literal_type_node));
+
+  widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
+                       widest_unsigned_literal_type_node));
+
+  /* Now all the integer mode types. */
   intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
 
@@ -3041,8 +3133,10 @@ init_decl_processing ()
   intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
 
+#if HOST_BITS_PER_WIDE_INT >= 64
   intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+#endif
 
   unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
@@ -3056,8 +3150,10 @@ 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));
 
+#if HOST_BITS_PER_WIDE_INT >= 64
   unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+#endif
 
   float_type_node = make_node (REAL_TYPE);
   TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
@@ -3291,8 +3387,8 @@ init_decl_processing ()
   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_cfa", ptr_ftype_void,
+                   BUILT_IN_DWARF_CFA, NULL_PTR);
   builtin_function ("__builtin_dwarf_fp_regnum",
                    build_function_type (unsigned_type_node, endlink),
                    BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
@@ -3302,24 +3398,16 @@ init_decl_processing ()
                    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_old", ptr_ftype_void,
-                   BUILT_IN_EH_STUB_OLD, NULL_PTR);
-  builtin_function ("__builtin_eh_stub", ptr_ftype_void,
-                   BUILT_IN_EH_STUB, NULL_PTR);
   builtin_function
-    ("__builtin_set_eh_regs",
+    ("__builtin_eh_return",
      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);
+                                               tree_cons (NULL_TREE,
+                                                          ptr_type_node,
+                                                          endlink)))),
+     BUILT_IN_EH_RETURN, NULL_PTR);
 
   builtin_function ("__builtin_alloca",
                    build_function_type (ptr_type_node,
@@ -3546,10 +3634,10 @@ init_decl_processing ()
 
 tree
 builtin_function (name, type, function_code, library_name)
-     char *name;
+     const char *name;
      tree type;
      enum built_in_function function_code;
-     char *library_name;
+     const char *library_name;
 {
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
@@ -3721,7 +3809,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* The corresponding pop_obstacks is in finish_decl.  */
   push_obstacks_nochange ();
 
-  if (warn_main && TREE_CODE (decl) != FUNCTION_DECL 
+  if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL 
       && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
     warning_with_decl (decl, "`%s' is usually a function");
 
@@ -4312,13 +4400,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   tree type = NULL_TREE;
   int longlong = 0;
   int constp;
+  int restrictp;
   int volatilep;
+  int type_quals = TYPE_UNQUALIFIED;
   int inlinep;
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
   tree typedef_decl = 0;
-  char *name;
+  const char *name;
   tree typedef_type = 0;
   int funcdef_flag = 0;
   enum tree_code innermost_code = ERROR_MARK;
@@ -4474,13 +4564,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
          && ! (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.  */
+         /* Issue a warning if this is an ISO C 9x program or if -Wreturn-type
+            and this is a function, or if -Wimplicit; prefer the former
+            warning since it is more explicit.  */
          if ((warn_implicit_int || warn_return_type) && funcdef_flag)
            warn_about_return_type = 1;
-         else if (warn_implicit_int)
+         else if (warn_implicit_int || flag_isoc9x)
            warning ("type defaults to `int' in declaration of `%s'", name);
        }
 
@@ -4622,19 +4711,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        type = build_complex_type (type);
     }
 
-  /* Set CONSTP if this declaration is `const', whether by
-     explicit specification or via a typedef.
-     Likewise for VOLATILEP.  */
-
+  /* Figure out the type qualifiers for the declaration.  There are
+     two ways a declaration can become qualified.  One is something
+     like `const int i' where the `const' is explicit.  Another is
+     something like `typedef const int CI; CI i' where the type of the
+     declaration contains the `const'.  */
   constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
+  restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
   volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
   inlinep = !! (specbits & (1 << (int) RID_INLINE));
   if (constp > 1)
     pedwarn ("duplicate `const'");
+  if (restrictp > 1)
+    pedwarn ("duplicate `restrict'");
   if (volatilep > 1)
     pedwarn ("duplicate `volatile'");
-  if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
+  if (! flag_gen_aux_info && (TYPE_QUALS (type)))
     type = TYPE_MAIN_VARIANT (type);
+  type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+               | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+               | (volatilep ? TYPE_QUAL_VOLATILE : 0));
 
   /* Warn if two storage classes are given. Default to `auto'.  */
 
@@ -4868,13 +4964,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             is set correctly.  */
 
          type = build_array_type (type, itype);
-         if (constp || volatilep)
-           type = c_build_type_variant (type, constp, volatilep);
+         if (type_quals)
+           type = c_build_qualified_type (type, type_quals);
 
 #if 0  /* don't clear these; leave them set so that the array type
           or the variable is itself const or volatile.  */
-         constp = 0;
-         volatilep = 0;
+         type_quals = TYPE_UNQUALIFIED;
 #endif
 
          if (size_varies)
@@ -4939,12 +5034,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                                      flag_traditional 
                                      ? NULL_TREE : arg_types);
 #endif
-         /* ANSI seems to say that `const int foo ();'
-            does not make the function foo const.  */
-         if (constp || volatilep)
-           type = c_build_type_variant (type, constp, volatilep);
-         constp = 0;
-         volatilep = 0;
+         /* Type qualifiers before the return type of the function
+            qualify the return type, not the function type.  */
+         if (type_quals)
+           type = c_build_qualified_type (type, type_quals);
+         type_quals = TYPE_UNQUALIFIED;
 
          type = build_function_type (type, arg_types);
          declarator = TREE_OPERAND (declarator, 0);
@@ -4968,12 +5062,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             for the pointer.  */
 
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-             && (constp || volatilep))
-           pedwarn ("ANSI C forbids const or volatile function types");
-         if (constp || volatilep)
-           type = c_build_type_variant (type, constp, volatilep);
-         constp = 0;
-         volatilep = 0;
+             && type_quals)
+           pedwarn ("ANSI C forbids qualified function types");
+         if (type_quals)
+           type = c_build_qualified_type (type, type_quals);
+         type_quals = TYPE_UNQUALIFIED;
          size_varies = 0;
 
          type = build_pointer_type (type);
@@ -4985,13 +5078,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            {
              register tree typemodlist;
              int erred = 0;
+
+             constp = 0;
+             volatilep = 0;
+             restrictp = 0;
              for (typemodlist = TREE_TYPE (declarator); typemodlist;
                   typemodlist = TREE_CHAIN (typemodlist))
                {
-                 if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
+                 tree qualifier = TREE_VALUE (typemodlist);
+
+                 if (qualifier == ridpointers[(int) RID_CONST])
                    constp++;
-                 else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
+                 else if (qualifier == ridpointers[(int) RID_VOLATILE])
                    volatilep++;
+                 else if (qualifier == ridpointers[(int) RID_RESTRICT])
+                   restrictp++;
                  else if (!erred)
                    {
                      erred = 1;
@@ -5002,6 +5103,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                pedwarn ("duplicate `const'");
              if (volatilep > 1)
                pedwarn ("duplicate `volatile'");
+             if (restrictp > 1)
+               pedwarn ("duplicate `restrict'");
+
+             type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+                           | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+                           | (volatilep ? TYPE_QUAL_VOLATILE : 0));
            }
 
          declarator = TREE_OPERAND (declarator, 0);
@@ -5028,10 +5135,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Note that the grammar rejects storage classes
         in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-         && (constp || volatilep))
-       pedwarn ("ANSI C forbids const or volatile function types");
-      if (constp || volatilep)
-       type = c_build_type_variant (type, constp, volatilep);
+         && type_quals)
+       pedwarn ("ANSI C forbids qualified function types");
+      if (type_quals)
+       type = c_build_qualified_type (type, type_quals);
       decl = build_decl (TYPE_DECL, declarator, type);
       if ((specbits & (1 << (int) RID_SIGNED))
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
@@ -5063,10 +5170,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Note that the grammar rejects storage classes
         in typenames, fields or parameters */
       if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
-         && (constp || volatilep))
+         && type_quals)
        pedwarn ("ANSI C forbids const or volatile function types");
-      if (constp || volatilep)
-       type = c_build_type_variant (type, constp, volatilep);
+      if (type_quals)
+       type = c_build_qualified_type (type, type_quals);
       pop_obstacks ();
       return type;
     }
@@ -5106,20 +5213,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          {
            /* Transfer const-ness of array into that of type pointed to.  */
            type = TREE_TYPE (type);
-           if (constp || volatilep)
-             type = c_build_type_variant (type, constp, volatilep);
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
-           volatilep = constp = 0;
+           type_quals = TYPE_UNQUALIFIED;
            size_varies = 0;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
          {
-           if (pedantic && (constp || volatilep))
-             pedwarn ("ANSI C forbids const or volatile function types");
-           if (constp || volatilep)
-             type = c_build_type_variant (type, constp, volatilep);
+           if (pedantic && type_quals)
+             pedwarn ("ANSI C forbids qualified function types");
+           if (type_quals)
+             type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
-           volatilep = constp = 0;
+           type_quals = TYPE_UNQUALIFIED;
          }
 
        decl = build_decl (PARM_DECL, declarator, type);
@@ -5167,13 +5274,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = error_mark_node;
          }
        /* Move type qualifiers down to element of an array.  */
-       if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+       if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
          {
-           type = build_array_type (c_build_type_variant (TREE_TYPE (type),
-                                                          constp, volatilep),
+           type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+                                                            type_quals),
                                     TYPE_DOMAIN (type));
 #if 0 /* Leave the field const or volatile as well.  */
-           constp = volatilep = 0;
+           type_quals = TYPE_UNQUALIFIED;
 #endif
          }
        decl = build_decl (FIELD_DECL, declarator, type);
@@ -5212,18 +5319,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        decl = build_decl (FUNCTION_DECL, declarator, type);
        decl = build_decl_attribute_variant (decl, decl_machine_attr);
 
-       if (pedantic && (constp || volatilep)
-           && ! DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn ("ANSI C forbids const or volatile functions");
+       if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+         pedwarn ("ANSI C forbids qualified function types");
 
        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))))
+           && TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
            && ! DECL_IN_SYSTEM_HEADER (decl))
-         pedwarn ("ANSI C forbids const or volatile void function return type");
+         pedwarn ("ANSI C forbids qualified void function return type");
 
-       if (volatilep
+       /* GNU C interprets a `volatile void' return type to indicate
+          that the function does not return.  */
+       if ((type_quals & TYPE_QUAL_VOLATILE)
            && TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
          warning ("`noreturn' function returns non-void value");
 
@@ -5253,13 +5360,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
 
        /* Move type qualifiers down to element of an array.  */
-       if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
+       if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
          {
-           type = build_array_type (c_build_type_variant (TREE_TYPE (type),
-                                                          constp, volatilep),
+           type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+                                                            type_quals),
                                     TYPE_DOMAIN (type));
 #if 0 /* Leave the variable const or volatile as well.  */
-           constp = volatilep = 0;
+           type_quals = TYPE_UNQUALIFIED;
 #endif
          }
 
@@ -5306,14 +5413,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       DECL_REGISTER (decl) = 1;
 
     /* Record constancy and volatility.  */
+    c_apply_type_quals_to_decl (type_quals, decl);
 
-    if (constp)
-      TREE_READONLY (decl) = 1;
-    if (volatilep)
-      {
-       TREE_SIDE_EFFECTS (decl) = 1;
-       TREE_THIS_VOLATILE (decl) = 1;
-      }
     /* If a type has volatile components, it should be stored in memory.
        Otherwise, the fact that those components are volatile
        will be ignored, and would even crash the compiler.  */
@@ -5573,8 +5674,7 @@ parmlist_tags_warning ()
 
       if (! already)
        {
-         warning ("its scope is only this definition or declaration,");
-         warning ("which is probably not what you want.");
+         warning ("its scope is only this definition or declaration, which is probably not what you want.");
          already = 1;
        }
     }
@@ -5688,8 +5788,8 @@ start_struct (code, name)
 
 tree
 grokfield (filename, line, declarator, declspecs, width)
-     char *filename;
-     int line;
+     const char *filename ATTRIBUTE_UNUSED;
+     int line ATTRIBUTE_UNUSED;
      tree declarator, declspecs, width;
 {
   tree value;
@@ -5771,9 +5871,10 @@ finish_struct (t, fieldlist, attributes)
          break;
 
       if (x == 0)
-       pedwarn ("%s has no %smembers",
-                (TREE_CODE (t) == UNION_TYPE ? "union" : "structure"),
-                (fieldlist ? "named " : ""));
+       pedwarn ((fieldlist
+                 ? "%s has no named members"
+                 : "%s has no members"),
+                TREE_CODE (t) == UNION_TYPE ? "union" : "struct");
     }
 
   /* Install struct as DECL_CONTEXT of each field decl.
@@ -6431,6 +6532,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
      except for defining how to inline.  So set DECL_EXTERNAL in that case.  */
   DECL_EXTERNAL (decl1) = current_extern_inline;
 
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+  SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
+#endif
+  
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
@@ -6440,7 +6545,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
     TREE_PUBLIC (decl1) = 0;
 
   /* Warn for unlikely, improbable, or stupid declarations of `main'. */
-  if (warn_main
+  if (warn_main > 0
       && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
     {
       tree args;
@@ -7157,12 +7262,8 @@ finish_function (nested)
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
          != integer_type_node)
        {
-         /* 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 is 1 (-Wmain) or 2 (-Wall), we have already warned.
+            If warn_main is -1 (-Wno-main) we don't want to be warned. */
          if (! warn_main)
            pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
        }
@@ -7186,6 +7287,12 @@ finish_function (nested)
 
   current_function_returns_null |= can_reach_end;
 
+  if (warn_missing_noreturn
+      && !TREE_THIS_VOLATILE (fndecl)
+      && !current_function_returns_null
+      && !current_function_returns_value)
+    warning ("function might be possible candidate for attribute `noreturn'");
+
   if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
     warning ("`noreturn' function does return");
   else if (warn_return_type && can_reach_end