OSDN Git Service

H
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index bc8f617..91e3510 100644 (file)
@@ -35,6 +35,13 @@ Boston, MA 02111-1307, USA.  */
 #include "c-lex.h"
 #include "toplev.h"
 
+#if USE_CPPLIB
+#include "cpplib.h"
+extern cpp_reader  parse_in;
+extern cpp_options parse_options;
+static int cpp_initialized;
+#endif
+
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
 { NORMAL,                      /* Ordinary declaration */
@@ -144,13 +151,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.  */
 
@@ -457,6 +468,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;
@@ -478,6 +493,10 @@ int flag_no_ident = 0;
 
 int warn_implicit_int;
 
+/* Nonzero means warn about usage of long long when `-pedantic'.  */
+
+int warn_long_long = 1;
+
 /* Nonzero means message about use of implicit function declarations;
  1 means warning; 2 means error. */
 
@@ -487,7 +506,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.  */
@@ -500,6 +519,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;
@@ -570,6 +593,10 @@ int warn_unknown_pragmas = 0; /* Tri state variable.  */
 
 int warn_sign_compare = -1;
 
+/* Nonzero means warn about use of multicharacter literals.  */
+
+int warn_multichar = 1;
+
 /* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
@@ -578,13 +605,28 @@ int warn_sign_compare = -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);
-   return 0 if not recognized.  */
+   Return the number of strings consumed.  */
    
 int
-c_decode_option (p)
-     char *p;
+c_decode_option (argc, argv)
+     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;
+#endif /* ! USE_CPPLIB */
+
   if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
     {
       flag_traditional = 1;
@@ -610,6 +652,8 @@ c_decode_option (p)
       flag_traditional = 0;
       flag_writable_strings = 0;
     }
+  else if (!strcmp (p, "-flang-isoc9x"))
+    flag_isoc9x = 1;
   else if (!strcmp (p, "-fdollars-in-identifiers"))
     dollars_in_ident = 1;
   else if (!strcmp (p, "-fno-dollars-in-identifiers"))
@@ -678,10 +722,14 @@ c_decode_option (p)
     }
   else if (!strcmp (p, "-Wno-implicit"))
     warn_implicit_int = 0, mesg_implicit_function_declaration = 0;
+  else if (!strcmp (p, "-Wlong-long"))
+    warn_long_long = 1;
+  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"))
@@ -690,6 +738,10 @@ c_decode_option (p)
     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"))
@@ -770,6 +822,10 @@ c_decode_option (p)
     warn_sign_compare = 1;
   else if (!strcmp (p, "-Wno-sign-compare"))
     warn_sign_compare = 0;
+  else if (!strcmp (p, "-Wmultichar"))
+    warn_multichar = 1;
+  else if (!strcmp (p, "-Wno-multichar"))
+    warn_multichar = 0;
   else if (!strcmp (p, "-Wunknown-pragmas"))
     /* Set to greater than 1, so that even unknown pragmas in system
        headers will be warned about.  */
@@ -799,7 +855,7 @@ c_decode_option (p)
       warn_unknown_pragmas = 1;
     }
   else
-    return 0;
+    return strings_processed;
 
   return 1;
 }
@@ -904,7 +960,7 @@ kept_level_p ()
 
 void
 declare_parm_level (definition_flag)
-     int definition_flag;
+     int definition_flag ATTRIBUTE_UNUSED;
 {
   current_binding_level->parm_flag = 1;
 }
@@ -1893,6 +1949,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
        {
          DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
          DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+
+         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 ();
@@ -1979,14 +2040,21 @@ 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)
     {
       /* Don't output a duplicate symbol or debugging information for this
-        declaration.  */
-      TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
+        declaration.
+
+        Do not set TREE_ASM_WRITTEN for a FUNCTION_DECL since we may actually
+        just have two declarations without a definition.  VAR_DECLs may need
+        the same treatment, I'm not sure.  */
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       DECL_IGNORED_P (newdecl) = 1;
+      else
+       TREE_ASM_WRITTEN (newdecl) = DECL_IGNORED_P (newdecl) = 1;
       return 0;
     }
 
@@ -2336,7 +2404,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))
@@ -2993,8 +3061,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, intDI_type_node));
+  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));
@@ -3008,8 +3078,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;
@@ -3243,8 +3315,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);
@@ -3254,24 +3326,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,
@@ -3403,6 +3467,9 @@ init_decl_processing ()
                                           integer_type_node,
                                           endlink))),
                    BUILT_IN_LONGJMP, NULL_PTR);
+  builtin_function ("__builtin_trap",
+                   build_function_type (void_type_node, endlink),
+                   BUILT_IN_TRAP, NULL_PTR);
 
   /* In an ANSI C program, it is okay to supply built-in meanings
      for these functions, since applications cannot validly use them
@@ -3481,6 +3548,8 @@ init_decl_processing ()
   init_iterators ();
 
   incomplete_decl_finalize_hook = finish_incomplete_decl;
+
+  lang_get_alias_set = c_get_alias_set;
 }
 
 /* Return a definition for a builtin function named NAME and whose data type
@@ -3555,7 +3624,7 @@ shadow_tag_warned (declspecs, warned)
      following code.  */
   split_specs_attrs (declspecs, &specs, &attrs);
 
-  for (link = declspecs; link; link = TREE_CHAIN (link))
+  for (link = specs; link; link = TREE_CHAIN (link))
     {
       register tree value = TREE_VALUE (link);
       register enum tree_code code = TREE_CODE (value);
@@ -3668,7 +3737,8 @@ 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"))
+  if (warn_main && TREE_CODE (decl) != FUNCTION_DECL 
+      && !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
     warning_with_decl (decl, "`%s' is usually a function");
 
   if (initialized)
@@ -3763,6 +3833,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   if (! flag_no_common || ! TREE_PUBLIC (decl))
     DECL_COMMON (decl) = 1;
 
+#ifdef SET_DEFAULT_DECL_ATTRIBUTES
+  SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
+#endif
+
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   decl_attributes (decl, attributes, prefix_attributes);
 
@@ -4254,7 +4328,9 @@ 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;
@@ -4359,7 +4435,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
                      error ("`long long long' is too long for GCC");
                    else
                      {
-                       if (pedantic && ! in_system_header)
+                       if (pedantic && ! in_system_header && warn_long_long)
                          pedwarn ("ANSI C does not support `long long'");
                        longlong = 1;
                      }
@@ -4412,6 +4488,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
                          | (1 << (int) RID_SIGNED)
                          | (1 << (int) RID_UNSIGNED))))
+         /* Don't warn about typedef foo = bar.  */
+         && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
          && ! (in_system_header && ! allocation_temporary_p ()))
        {
          /* C9x will probably require a diagnostic here.
@@ -4562,19 +4640,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'.  */
 
@@ -4808,13 +4893,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)
@@ -4879,12 +4963,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);
@@ -4908,12 +4991,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);
@@ -4925,13 +5007,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;
@@ -4942,6 +5032,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);
@@ -4968,10 +5064,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)))
@@ -5003,10 +5099,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;
     }
@@ -5046,20 +5142,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);
@@ -5107,13 +5203,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);
@@ -5152,18 +5248,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");
 
@@ -5176,8 +5272,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        /* Record presence of `inline', if it is reasonable.  */
        if (inlinep)
          {
-           tree last = tree_last (TYPE_ARG_TYPES (type));
-
            if (! strcmp (IDENTIFIER_POINTER (declarator), "main"))
              warning ("cannot inline function `main'");
            else
@@ -5195,13 +5289,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
          }
 
@@ -5248,14 +5342,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.  */
@@ -6161,6 +6249,7 @@ finish_enum (enumtype, values, attributes)
       TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
       TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
       TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+      TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
       TYPE_MODE (tem) = TYPE_MODE (enumtype);
       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
@@ -6372,6 +6461,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;
@@ -7127,6 +7220,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