OSDN Git Service

2002-03-03 Aldy Hernandez <aldyh@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 5a34a2c..845cefb 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001 Free Software Foundation, Inc.
+   2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -45,6 +45,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "target.h"
 #include "debug.h"
 #include "timevar.h"
+#include "c-common.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -133,6 +134,11 @@ int current_function_returns_value;
 
 int current_function_returns_null;
 
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a call to a noreturn function is seen.  */
+
+int current_function_returns_abnormally;
+
 /* Set to nonzero by `grokdeclarator' for a function
    whose return type is defaulted, if warnings for this are desired.  */
 
@@ -280,6 +286,7 @@ static tree grokparms                       PARAMS ((tree, int));
 static void layout_array_type          PARAMS ((tree));
 static tree c_make_fname_decl           PARAMS ((tree, int));
 static void c_expand_body               PARAMS ((tree, int, int));
+static void warn_if_shadowing          PARAMS ((tree, tree));
 \f
 /* C-specific option variables.  */
 
@@ -292,10 +299,6 @@ int flag_cond_mismatch;
 
 int flag_no_asm;
 
-/* Nonzero means do some things the same way PCC does.  */
-
-int flag_traditional;
-
 /* Nonzero means enable C89 Amendment 1 features.  */
 
 int flag_isoc94 = 0;
@@ -313,10 +316,6 @@ int flag_hosted = 1;
 
 int flag_noniso_default_format_attributes = 1;
 
-/* Nonzero means to allow single precision math even if we're generally
-   being traditional.  */
-int flag_allow_single_precision = 0;
-
 /* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
 
 int flag_signed_bitfields = 1;
@@ -430,10 +429,6 @@ int warn_float_equal = 0;
 
 int warn_multichar = 1;
 
-/* The variant of the C language being processed.  */
-
-c_language_kind c_language = clk_c;
-
 /* Nonzero means `$' can be in an identifier.  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
@@ -441,6 +436,18 @@ c_language_kind c_language = clk_c;
 #endif
 int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 
+/* States indicating how grokdeclarator() should handle declspecs marked
+   with __attribute__((deprecated)).  An object declared as
+   __attribute__((deprecated)) suppresses warnings of uses of other
+   deprecated items.  */
+   
+enum deprecated_states {
+  DEPRECATED_NORMAL,
+  DEPRECATED_SUPPRESS
+};
+
+static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
 /* Decode the string P as a language-specific option for C.
    Return the number of strings consumed.  Should not complain
    if it does not recognise the option.  */
@@ -453,16 +460,9 @@ c_decode_option (argc, argv)
   int strings_processed;
   char *p = argv[0];
 
-  strings_processed = cpp_handle_option (parse_in, argc, argv);
+  strings_processed = cpp_handle_option (parse_in, argc, argv, 0);
 
-  if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
-    {
-      flag_traditional = 1;
-      flag_writable_strings = 1;
-    }
-  else if (!strcmp (p, "-fallow-single-precision"))
-    flag_allow_single_precision = 1;
-  else if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
+  if (!strcmp (p, "-fhosted") || !strcmp (p, "-fno-freestanding"))
     {
       flag_hosted = 1;
       flag_no_builtin = 0;
@@ -475,11 +475,6 @@ c_decode_option (argc, argv)
       if (warn_main == 2)
        warn_main = 0;
     }
-  else if (!strcmp (p, "-fnotraditional") || !strcmp (p, "-fno-traditional"))
-    {
-      flag_traditional = 0;
-      flag_writable_strings = 0;
-    }
   else if (!strncmp (p, "-std=", 5))
     {
       /* Select the appropriate language standard.  We currently
@@ -500,7 +495,6 @@ c_decode_option (argc, argv)
        iso_1990:
          flag_isoc94 = 0;
        iso_1994:
-         flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 1;
          flag_no_nonansi_builtin = 1;
@@ -517,7 +511,6 @@ c_decode_option (argc, argv)
               || !strcmp (argstart, "c9x")
               || !strcmp (argstart, "c99"))
        {
-         flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 1;
          flag_no_nonansi_builtin = 1;
@@ -527,7 +520,6 @@ c_decode_option (argc, argv)
        }
       else if (!strcmp (argstart, "gnu89"))
        {
-         flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 0;
          flag_no_nonansi_builtin = 0;
@@ -537,7 +529,6 @@ c_decode_option (argc, argv)
        }
       else if (!strcmp (argstart, "gnu9x") || !strcmp (argstart, "gnu99"))
        {
-         flag_traditional = 0;
          flag_writable_strings = 0;
          flag_no_asm = 0;
          flag_no_nonansi_builtin = 0;
@@ -1466,14 +1457,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
      match enough.  Ultimately, copy most of the information from the new
      decl to the old one, and keep using the old one.  */
 
-  if (flag_traditional && TREE_CODE (newdecl) == FUNCTION_DECL
-      && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (newdecl)) == olddecl
-      && DECL_INITIAL (olddecl) == 0)
-    /* If -traditional, avoid error for redeclaring fcn
-       after implicit decl.  */
-    ;
-  else if (TREE_CODE (olddecl) == FUNCTION_DECL
-          && DECL_BUILT_IN (olddecl))
+  if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
     {
       /* A function declaration for a built-in function.  */
       if (!TREE_PUBLIC (newdecl))
@@ -1532,6 +1516,22 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          if (! different_binding_level)
            TREE_TYPE (olddecl) = oldtype;
        }
+      else if (TYPE_ARG_TYPES (oldtype) == NULL
+              && TYPE_ARG_TYPES (newtype) != NULL)
+       {
+         /* For bcmp, bzero, fputs the builtin type has arguments not
+            specified.  Use the ones from the prototype so that type checking
+            is done for them.  */
+         tree trytype
+           = build_function_type (TREE_TYPE (oldtype),
+                                  TYPE_ARG_TYPES (newtype));
+         trytype = build_type_attribute_variant (trytype,
+                                                 TYPE_ATTRIBUTES (oldtype));
+
+         oldtype = trytype;
+         if (! different_binding_level)
+           TREE_TYPE (olddecl) = oldtype;
+       }
       if (!types_match)
        {
          /* If types don't match for a built-in, throw away the built-in.  */
@@ -1620,13 +1620,13 @@ 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 an empty parameter name list declaration.");
+                 error ("a parameter list with an ellipsis can't match an empty parameter name list declaration");
                  break;
                }
 
              if (simple_type_promotes_to (type) != NULL_TREE)
                {
-                 error ("An argument type that has a default promotion 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;
                }
            }
@@ -1658,6 +1658,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                             && current_binding_level == global_binding_level)
                            ? "`%s' previously defined here"
                            : "`%s' previously declared here"));
+         return 0;
        }
       else if (TREE_CODE (newdecl) == TYPE_DECL
                && (DECL_IN_SYSTEM_HEADER (olddecl)
@@ -1705,12 +1706,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
                }
              /* Type for passing arg must be consistent
                 with that declared for the arg.  */
-             if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type))
-                 /* If -traditional, allow `unsigned int' instead of `int'
-                    in the prototype.  */
-                 && (! (flag_traditional
-                        && TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
-                        && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
+             if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
                {
                  error_with_decl (newdecl,
                                   "prototype for `%s' follows and argument %d doesn't match",
@@ -1905,13 +1901,9 @@ 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_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (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);
-         DECL_NO_LIMIT_STACK (newdecl)
-           |= DECL_NO_LIMIT_STACK (olddecl);
        }
     }
   /* If cannot merge, then use the new type and qualifiers,
@@ -1979,10 +1971,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          /* If either decl says `inline', this fn is inline,
             unless its definition was passed already.  */
          if (DECL_DECLARED_INLINE_P (newdecl)
-             && DECL_DECLARED_INLINE_P (olddecl) == 0)
-           DECL_DECLARED_INLINE_P (olddecl) = 1;
-
-         DECL_DECLARED_INLINE_P (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
+             || DECL_DECLARED_INLINE_P (olddecl))
+           DECL_DECLARED_INLINE_P (newdecl) = 1;
 
          DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
            = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
@@ -2008,9 +1998,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
              DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
            }
        }
+
       /* Also preserve various other info from the definition.  */
-      else if (! new_is_definition)
-       DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
       if (! new_is_definition)
        {
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
@@ -2020,9 +2009,28 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
          if (! different_binding_level)
            DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
          DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
+         DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+         DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
          DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-         if (DECL_INLINE (newdecl))
-           DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ABSTRACT_ORIGIN (olddecl);
+
+         /* Set DECL_INLINE on the declaration if we've got a body
+            from which to instantiate.  */
+         if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+           {
+             DECL_INLINE (newdecl) = 1;
+             DECL_ABSTRACT_ORIGIN (newdecl)
+               = (different_binding_level
+                  ? DECL_ORIGIN (olddecl)
+                  : DECL_ABSTRACT_ORIGIN (olddecl));
+           }
+       }
+      else
+       {
+         /* If a previous declaration said inline, mark the
+            definition as inlinable.  */
+         if (DECL_DECLARED_INLINE_P (newdecl)
+             && ! DECL_UNINLINABLE (newdecl))
+           DECL_INLINE (newdecl) = 1;
        }
     }
   if (different_binding_level)
@@ -2046,6 +2054,66 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   return 1;
 }
 
+/* Check whether decl-node X shadows an existing declaration.
+   OLDLOCAL is the old IDENTIFIER_LOCAL_VALUE of the DECL_NAME of X,
+   which might be a NULL_TREE.  */
+static void
+warn_if_shadowing (x, oldlocal)
+     tree x, oldlocal;
+{
+  tree name;
+
+  if (DECL_EXTERNAL (x))
+    return;
+
+  name = DECL_NAME (x);
+
+  /* Warn if shadowing an argument at the top level of the body.  */
+  if (oldlocal != 0
+      /* This warning doesn't apply to the parms of a nested fcn.  */
+      && ! current_binding_level->parm_flag
+      /* Check that this is one level down from the parms.  */
+      && current_binding_level->level_chain->parm_flag
+      /* Check that the decl being shadowed
+        comes from the parm level, one level up.  */
+      && chain_member (oldlocal, current_binding_level->level_chain->names))
+    {
+      if (TREE_CODE (oldlocal) == PARM_DECL)
+       pedwarn ("declaration of `%s' shadows a parameter",
+                IDENTIFIER_POINTER (name));
+      else
+       pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
+                IDENTIFIER_POINTER (name));
+    }
+  /* Maybe warn if shadowing something else.  */
+  else if (warn_shadow
+          /* No shadow warnings for internally generated vars.  */
+          && DECL_SOURCE_LINE (x) != 0
+          /* No shadow warnings for vars made for inlining.  */
+          && ! DECL_FROM_INLINE (x))
+    {
+      if (TREE_CODE (x) == PARM_DECL
+         && current_binding_level->level_chain->parm_flag)
+       /* Don't warn about the parm names in function declarator
+          within a function declarator.
+          It would be nice to avoid warning in any function
+          declarator in a declaration, as opposed to a definition,
+          but there is no way to tell it's not a definition.  */
+       ;
+      else if (oldlocal)
+       {
+         if (TREE_CODE (oldlocal) == PARM_DECL)
+           shadow_warning ("a parameter", name, oldlocal);
+         else
+           shadow_warning ("a previous local", name, oldlocal);
+       }
+      else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
+              && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
+       shadow_warning ("a global declaration", name,
+                       IDENTIFIER_GLOBAL_VALUE (name));
+    }
+}
+
 /* Record a decl-node X as belonging to the current lexical scope.
    Check for errors (such as an incompatible declaration for the same
    name already seen in the same scope).
@@ -2089,16 +2157,15 @@ pushdecl (x)
                 IDENTIFIER_POINTER (name));
 
       t = lookup_name_current_level (name);
-      /* Don't type check externs here when -traditional.  This is so that
-        code with conflicting declarations inside blocks will get warnings
-        not errors.  X11 for instance depends on this.  */
-      if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x) && ! flag_traditional)
+      if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
        {
-         t = lookup_name (name);
+         t = IDENTIFIER_GLOBAL_VALUE (name);
          /* Type decls at global scope don't conflict with externs declared
             inside lexical blocks.  */
-         if (t && TREE_CODE (t) == TYPE_DECL)
-           t = 0;
+         if (! t || TREE_CODE (t) == TYPE_DECL)
+           /* If there's no visible global declaration, try for an
+               invisible one.  */
+           t = IDENTIFIER_LIMBO_VALUE (name);
          different_binding_level = 1;
        }
       if (t != 0 && t == error_mark_node)
@@ -2109,9 +2176,8 @@ pushdecl (x)
        }
 
       /* If this decl is `static' and an implicit decl was seen previously,
-        warn.  But don't complain if -traditional,
-        since traditional compilers don't complain.  */
-      if (! flag_traditional && TREE_PUBLIC (name)
+        warn.  */
+      if (TREE_PUBLIC (name)
          /* Don't test for DECL_EXTERNAL, because grokdeclarator
             sets this for all functions.  */
          && ! TREE_PUBLIC (x)
@@ -2205,9 +2271,6 @@ pushdecl (x)
        }
 
       /* Multiple external decls of the same identifier ought to match.
-        Check against both global declarations (when traditional) and out of
-        scope (limbo) block level declarations.
-
         We get warnings about inline functions where they are defined.
         Avoid duplicate warnings where they are used.  */
       if (TREE_PUBLIC (x)
@@ -2215,11 +2278,7 @@ pushdecl (x)
        {
          tree decl;
 
-         if (flag_traditional && IDENTIFIER_GLOBAL_VALUE (name) != 0
-             && (DECL_EXTERNAL (IDENTIFIER_GLOBAL_VALUE (name))
-                 || TREE_PUBLIC (IDENTIFIER_GLOBAL_VALUE (name))))
-           decl = IDENTIFIER_GLOBAL_VALUE (name);
-         else if (IDENTIFIER_LIMBO_VALUE (name) != 0)
+         if (IDENTIFIER_LIMBO_VALUE (name) != 0)
            /* Decls in limbo are always extern, so no need to check that.  */
            decl = IDENTIFIER_LIMBO_VALUE (name);
          else
@@ -2249,39 +2308,6 @@ pushdecl (x)
                             "previous implicit declaration of `%s'");
        }
 
-      /* In PCC-compatibility mode, extern decls of vars with no current decl
-        take effect at top level no matter where they are.  */
-      if (flag_traditional && DECL_EXTERNAL (x)
-         && lookup_name (name) == 0)
-       {
-         tree type = TREE_TYPE (x);
-
-         /* But don't do this if the type contains temporary nodes.  */
-         while (type)
-           {
-             if (type == error_mark_node)
-               break;
-             if (TYPE_CONTEXT (type))
-               {
-                 warning_with_decl (x, "type of external `%s' is not global");
-                 /* By exiting the loop early, we leave TYPE nonzero,
-                    and thus prevent globalization of the decl.  */
-                 break;
-               }
-             else if (TREE_CODE (type) == FUNCTION_TYPE
-                      && TYPE_ARG_TYPES (type) != 0)
-               /* The types might not be truly local,
-                  but the list of arg types certainly is temporary.
-                  Since prototypes are nontraditional,
-                  ok not to do the traditional thing.  */
-               break;
-             type = TREE_TYPE (type);
-           }
-
-         if (type == 0)
-           b = global_binding_level;
-       }
-
       /* This name is new in its binding level.
         Install the new declaration and return it.  */
       if (b == global_binding_level)
@@ -2430,49 +2456,7 @@ pushdecl (x)
                IDENTIFIER_LIMBO_VALUE (name) = x;
            }
 
-         /* Warn if shadowing an argument at the top level of the body.  */
-         if (oldlocal != 0 && !DECL_EXTERNAL (x)
-             /* This warning doesn't apply to the parms of a nested fcn.  */
-             && ! current_binding_level->parm_flag
-             /* Check that this is one level down from the parms.  */
-             && current_binding_level->level_chain->parm_flag
-             /* Check that the decl being shadowed
-                comes from the parm level, one level up.  */
-             && chain_member (oldlocal, current_binding_level->level_chain->names))
-           {
-             if (TREE_CODE (oldlocal) == PARM_DECL)
-               pedwarn ("declaration of `%s' shadows a parameter",
-                        IDENTIFIER_POINTER (name));
-             else
-               pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
-                        IDENTIFIER_POINTER (name));
-           }
-
-         /* Maybe warn if shadowing something else.  */
-         else if (warn_shadow && !DECL_EXTERNAL (x)
-                  /* No shadow warnings for internally generated vars.  */
-                  && DECL_SOURCE_LINE (x) != 0
-                  /* No shadow warnings for vars made for inlining.  */
-                  && ! DECL_FROM_INLINE (x))
-           {
-             const char *id = IDENTIFIER_POINTER (name);
-
-             if (TREE_CODE (x) == PARM_DECL
-                 && current_binding_level->level_chain->parm_flag)
-               /* Don't warn about the parm names in function declarator
-                  within a function declarator.
-                  It would be nice to avoid warning in any function
-                  declarator in a declaration, as opposed to a definition,
-                  but there is no way to tell it's not a definition.  */
-               ;
-             else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
-               warning ("declaration of `%s' shadows a parameter", id);
-             else if (oldlocal != 0)
-               warning ("declaration of `%s' shadows previous local", id);
-             else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
-                      && IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
-               warning ("declaration of `%s' shadows global declaration", id);
-           }
+         warn_if_shadowing (x, oldlocal);
 
          /* If storing a local value, there may already be one (inherited).
             If so, record it for restoration when this binding level ends.  */
@@ -2486,7 +2470,15 @@ pushdecl (x)
         incomplete type.  */
       if (TREE_TYPE (x) != error_mark_node
          && !COMPLETE_TYPE_P (TREE_TYPE (x)))
-       ++b->n_incomplete;
+       {
+         tree element = TREE_TYPE (x);
+
+         while (TREE_CODE (element) == ARRAY_TYPE)
+           element = TREE_TYPE (element);
+         if (TREE_CODE (element) == RECORD_TYPE
+             || TREE_CODE (element) == UNION_TYPE)
+           ++b->n_incomplete;
+       }
     }
 
   /* Put decls on list in reverse order.
@@ -2549,8 +2541,7 @@ implicitly_declare (functionid)
   IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
 
   /* ANSI standard says implicit declarations are in the innermost block.
-     So we record the decl in the standard fashion.
-     If flag_traditional is set, pushdecl does it top-level.  */
+     So we record the decl in the standard fashion.  */
   pushdecl (decl);
 
   /* This is a no-op in c-lang.c or something real in objc-actions.c.  */
@@ -2598,17 +2589,8 @@ redeclaration_error_message (newdecl, olddecl)
 {
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
-      if (flag_traditional && TREE_TYPE (newdecl) == TREE_TYPE (olddecl))
-       return 0;
-      /* pushdecl creates distinct types for TYPE_DECLs by calling
-        build_type_copy, so the above comparison generally fails.  We do
-        another test against the TYPE_MAIN_VARIANT of the olddecl, which
-        is equivalent to what this code used to do before the build_type_copy
-        call.  The variant type distinction should not matter for traditional
-        code, because it doesn't have type qualifiers.  */
-      if (flag_traditional
-         && TYPE_MAIN_VARIANT (TREE_TYPE (olddecl)) == TREE_TYPE (newdecl))
-       return 0;
+      /* Do not complain about type redeclarations where at least one
+        declaration was in a system header.  */
       if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
        return 0;
       return 1;
@@ -3153,11 +3135,6 @@ builtin_function (name, type, function_code, class, library_name)
   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
-  /* If -traditional, permit redefining a builtin function any way you like.
-     (Though really, if the program redefines these functions,
-     it probably won't work right unless compiled with -fno-builtin.)  */
-  if (flag_traditional && name[0] != '_')
-    DECL_BUILT_IN_NONANSI (decl) = 1;
   if (library_name)
     SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
   make_decl_rtl (decl, NULL);
@@ -3165,6 +3142,10 @@ builtin_function (name, type, function_code, class, library_name)
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = function_code;
 
+  /* The return builtins leave the current function.  */
+  if (function_code == BUILT_IN_RETURN || function_code == BUILT_IN_EH_RETURN)
+    TREE_THIS_VOLATILE (decl) = 1;
+
   /* Warn if a function in the namespace for users
      is used without an occasion to consider it declared.  */
   if (name[0] != '_' || name[1] != '_')
@@ -3334,11 +3315,19 @@ tree
 groktypename (typename)
      tree typename;
 {
+  tree specs, attrs;
+
   if (TREE_CODE (typename) != TREE_LIST)
     return typename;
-  return grokdeclarator (TREE_VALUE (typename),
-                        TREE_PURPOSE (typename),
-                        TYPENAME, 0);
+
+  split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+
+  typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
+
+  /* Apply attributes.  */
+  decl_attributes (&typename, attrs, 0);
+
+  return typename;
 }
 
 /* Return a PARM_DECL node for a given pair of specs and declarator.  */
@@ -3375,9 +3364,18 @@ start_decl (declarator, declspecs, initialized, attributes)
      int initialized;
      tree attributes;
 {
-  tree decl = grokdeclarator (declarator, declspecs,
-                             NORMAL, initialized);
+  tree decl;
   tree tem;
+  
+  /* An object declared as __attribute__((deprecated)) suppresses
+     warnings of uses of other deprecated items.  */
+  if (lookup_attribute ("deprecated", attributes))
+    deprecated_state = DEPRECATED_SUPPRESS;
+
+  decl = grokdeclarator (declarator, declspecs,
+                        NORMAL, initialized);
+  
+  deprecated_state = DEPRECATED_NORMAL;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
       && MAIN_NAME_P (DECL_NAME (decl)))
@@ -3478,7 +3476,7 @@ start_decl (declarator, declspecs, initialized, attributes)
      initializer equal to zero.  (Section 3.7.2)
      -fno-common gives strict ANSI behavior.  Usually you don't want it.
      This matters only for variables with external linkage.  */
-  if (! flag_no_common || ! TREE_PUBLIC (decl))
+  if (!initialized && (! flag_no_common || ! TREE_PUBLIC (decl)))
     DECL_COMMON (decl) = 1;
 
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
@@ -3763,7 +3761,7 @@ push_parm_decl (parm)
       olddecl = lookup_name (DECL_NAME (decl));
       if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
        pedwarn_with_decl (decl,
-                          "ANSI C forbids parameter `%s' shadowing typedef");
+                          "ISO C forbids parameter `%s' shadowing typedef");
     }
 #endif
 
@@ -3788,6 +3786,61 @@ clear_parm_order ()
   current_binding_level->parm_order = NULL_TREE;
 }
 \f
+/* Build a COMPOUND_LITERAL_EXPR.  TYPE is the type given in the compound
+   literal, which may be an incomplete array type completed by the
+   initializer; INIT is a CONSTRUCTOR that initializes the compound
+   literal.  */
+
+tree
+build_compound_literal (type, init)
+     tree type;
+     tree init;
+{
+  /* We do not use start_decl here because we have a type, not a declarator;
+     and do not use finish_decl because the decl should be stored inside
+     the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT.  */
+  tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+  tree complit;
+  tree stmt;
+  DECL_EXTERNAL (decl) = 0;
+  TREE_PUBLIC (decl) = 0;
+  TREE_STATIC (decl) = (current_binding_level == global_binding_level);
+  DECL_CONTEXT (decl) = current_function_decl;
+  TREE_USED (decl) = 1;
+  TREE_TYPE (decl) = type;
+  store_init_value (decl, init);
+
+  if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
+    {
+      int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
+      if (failure)
+       abort ();
+    }
+
+  type = TREE_TYPE (decl);
+  if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+    return error_mark_node;
+
+  stmt = build_stmt (DECL_STMT, decl);
+  complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+  TREE_SIDE_EFFECTS (complit) = 1;
+
+  layout_decl (decl, 0);
+
+  if (TREE_STATIC (decl))
+    {
+      /* This decl needs a name for the assembler output.  We also need
+        a unique suffix to be added to the name, for which DECL_CONTEXT
+        must be set.  */
+      DECL_NAME (decl) = get_identifier ("__compound_literal");
+      DECL_CONTEXT (decl) = complit;
+      rest_of_decl_compilation (decl, NULL, 1, 0);
+      DECL_CONTEXT (decl) = NULL_TREE;
+    }
+
+  return complit;
+}
+\f
 /* Make TYPE a complete type based on INITIAL_VALUE.
    Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
    2 if there was no information (in which case assume 1 if DO_DEFAULT).  */
@@ -3991,6 +4044,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     {
       tree id = TREE_VALUE (spec);
 
+      /* If the entire declaration is itself tagged as deprecated then
+         suppress reports of deprecated items.  */
+      if (id && TREE_DEPRECATED (id))
+        {
+         if (deprecated_state != DEPRECATED_SUPPRESS)
+           warn_deprecated_use (id);
+        }
+
       if (id == ridpointers[(int) RID_INT])
        explicit_int = 1;
       if (id == ridpointers[(int) RID_CHAR])
@@ -4024,9 +4085,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Actual typedefs come to us as TYPE_DECL nodes.  */
       else if (TREE_CODE (id) == TYPE_DECL)
        {
-         type = TREE_TYPE (id);
-         decl_attr = DECL_ATTRIBUTES (id);
-         typedef_decl = id;
+         if (TREE_TYPE (id) == error_mark_node)
+           ; /* Allow the type to default to int to avoid cascading errors.  */
+         else
+           {
+             type = TREE_TYPE (id);
+             decl_attr = DECL_ATTRIBUTES (id);
+             typedef_decl = id;
+           }
        }
       /* Built-in types come as identifiers.  */
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -4157,9 +4223,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
   if (specbits & 1 << (int) RID_UNSIGNED
-      /* Traditionally, all bitfields are unsigned.  */
-      || (bitfield && flag_traditional
-         && (! explicit_flag_signed_bitfields || !flag_signed_bitfields))
       || (bitfield && ! flag_signed_bitfields
          && (explicit_int || defaulted_int || explicit_char
              /* A typedef for plain `int' without `signed'
@@ -4375,9 +4438,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          if (inner_decl == NULL_TREE
              || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
            attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
-         if (TREE_CODE (inner_decl) == CALL_EXPR)
+         else if (TREE_CODE (inner_decl) == CALL_EXPR)
            attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
-         if (TREE_CODE (inner_decl) == ARRAY_REF)
+         else if (TREE_CODE (inner_decl) == ARRAY_REF)
            attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
          returned_attrs = decl_attributes (&type,
                                            chainon (returned_attrs, attrs),
@@ -4518,7 +4581,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
             Functions aren't allowed as array elements.  */
          if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
              && (constp || volatilep))
-           pedwarn ("ANSI C forbids const or volatile function types");
+           pedwarn ("ISO C forbids const or volatile function types");
 #endif
 
          /* Build the array type itself, then merge any constancy or
@@ -4573,13 +4636,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              type = integer_type_node;
            }
 
-#ifndef TRADITIONAL_RETURN_FLOAT
-         /* Traditionally, declaring return type float means double.  */
-
-         if (flag_traditional && TYPE_MAIN_VARIANT (type) == float_type_node)
-           type = double_type_node;
-#endif /* TRADITIONAL_RETURN_FLOAT */
-
          /* Construct the function type and go to the next
             inner layer of declarator.  */
 
@@ -4952,6 +5008,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        TREE_PUBLIC (decl)
          = !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
 
+       if (defaulted_int)
+         C_FUNCTION_IMPLICIT_INT (decl) = 1;
+
        /* Record presence of `inline', if it is reasonable.  */
        if (MAIN_NAME_P (declarator))
          {
@@ -4961,16 +5020,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        else if (inlinep)
          {
            /* Assume that otherwise the function can be inlined.  */
-           DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 1;
 
-           if (specbits & (1 << (int) RID_EXTERN))
-             current_extern_inline = 1;
+           /* Do not mark bare declarations as DECL_INLINE.  Doing so
+              in the presence of multiple declarations can result in
+              the abstract origin pointing between the declarations,
+              which will confuse dwarf2out.  */
+           if (initialized)
+             {
+               DECL_INLINE (decl) = 1;
+               if (specbits & (1 << (int) RID_EXTERN))
+                 current_extern_inline = 1;
+             }
          }
        /* If -finline-functions, assume it can be inlined.  This does
           two things: let the function be deferred until it is actually
           needed, and let dwarf2 know that the function is inlinable.  */
-       else if (flag_inline_trees == 2)
+       else if (flag_inline_trees == 2 && initialized)
          {
            DECL_INLINE (decl) = 1;
            DECL_DECLARED_INLINE_P (decl) = 0;
@@ -5298,7 +5364,7 @@ parmlist_tags_warning ()
        }
       if (! already)
        {
-         warning ("its scope is only this definition or declaration, 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;
        }
     }
@@ -5462,7 +5528,7 @@ finish_struct (t, fieldlist, attributes)
        if (pedantic)
          pedwarn ("%s defined inside parms",
                   TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
-       else if (! flag_traditional)
+       else
          warning ("%s defined inside parms",
                   TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
       }
@@ -5557,11 +5623,10 @@ finish_struct (t, fieldlist, attributes)
         field widths.  */
       if (DECL_INITIAL (x))
        {
-         int max_width;
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node)
-           max_width = CHAR_TYPE_SIZE;
-         else
-           max_width = TYPE_PRECISION (TREE_TYPE (x));
+         int max_width
+           = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
+              ? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
+
          if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
            error_with_decl (x, "negative width in bit-field `%s'");
          else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
@@ -5572,7 +5637,7 @@ finish_struct (t, fieldlist, attributes)
            {
              /* The test above has assured us that TREE_INT_CST_HIGH is 0.  */
              unsigned HOST_WIDE_INT width
-               = TREE_INT_CST_LOW (DECL_INITIAL (x));
+               = tree_low_cst (DECL_INITIAL (x), 1);
 
              if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
                  && (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
@@ -5587,7 +5652,8 @@ finish_struct (t, fieldlist, attributes)
              DECL_BIT_FIELD (x) = 1;
              SET_DECL_C_BIT_FIELD (x);
 
-             if (width == 0)
+             if (width == 0
+                 && ! (* targetm.ms_bitfield_layout_p) (t))
                {
                  /* field size 0 => force desired amount of alignment.  */
 #ifdef EMPTY_FIELD_BOUNDARY
@@ -5719,7 +5785,8 @@ finish_struct (t, fieldlist, attributes)
              rest_of_decl_compilation (decl, NULL, toplevel, 0);
              if (! toplevel)
                expand_decl (decl);
-             --current_binding_level->n_incomplete;
+             if (--current_binding_level->n_incomplete == 0)
+               break;
            }
          else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
                   && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
@@ -5728,7 +5795,19 @@ finish_struct (t, fieldlist, attributes)
              while (TREE_CODE (element) == ARRAY_TYPE)
                element = TREE_TYPE (element);
              if (element == t)
-               layout_array_type (TREE_TYPE (decl));
+               {
+                 layout_array_type (TREE_TYPE (decl));
+                 if (TREE_CODE (decl) != TYPE_DECL)
+                   {
+                     layout_decl (decl, 0);
+                     maybe_objc_check_decl (decl);
+                     rest_of_decl_compilation (decl, NULL, toplevel, 0);
+                     if (! toplevel)
+                       expand_decl (decl);
+                   }
+                 if (--current_binding_level->n_incomplete == 0)
+                   break;
+               }
            }
        }
     }
@@ -5987,8 +6066,7 @@ build_enumerator (name, value)
   type = TREE_TYPE (value);
   type = type_for_size (MAX (TYPE_PRECISION (type),
                             TYPE_PRECISION (integer_type_node)),
-                       ((flag_traditional
-                         || TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
+                       (TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node)
                         && TREE_UNSIGNED (type)));
 
   decl = build_decl (CONST_DECL, name, type);
@@ -6021,6 +6099,7 @@ start_function (declspecs, declarator, attributes)
 
   current_function_returns_value = 0;  /* Assume, until we see it does.  */
   current_function_returns_null = 0;
+  current_function_returns_abnormally = 0;
   warn_about_return_type = 0;
   current_extern_inline = 0;
   c_function_varargs = 0;
@@ -6216,12 +6295,10 @@ start_function (declspecs, declarator, attributes)
   /* Promote the value to int before returning it.  */
   if (c_promoting_integer_type_p (restype))
     {
-      /* It retains unsignedness if traditional
-        or if not really getting wider.  */
+      /* It retains unsignedness if not really getting wider.  */
       if (TREE_UNSIGNED (restype)
-         && (flag_traditional
-             || (TYPE_PRECISION (restype)
-                 == TYPE_PRECISION (integer_type_node))))
+         && (TYPE_PRECISION (restype)
+                 == TYPE_PRECISION (integer_type_node)))
        restype = unsigned_type_node;
       else
        restype = integer_type_node;
@@ -6279,11 +6356,16 @@ store_parm_decls ()
      then CONST_DECLs for foo and bar are put here.  */
   tree nonparms = 0;
 
+  /* The function containing FNDECL, if any.  */
+  tree context = decl_function_context (fndecl);
+
   /* Nonzero if this definition is written with a prototype.  */
   int prototype = 0;
 
-  /* The function containing FNDECL, if any.  */
-  tree context = decl_function_context (fndecl);
+  int saved_warn_shadow = warn_shadow;
+
+  /* Don't re-emit shadow warnings.  */
+  warn_shadow = 0;
 
   if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
     {
@@ -6435,15 +6517,6 @@ store_parm_decls ()
              layout_decl (found, 0);
            }
 
-         /* Traditionally, a parm declared float is actually a double.  */
-         if (found && flag_traditional
-             && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
-           {
-             TREE_TYPE (found) = double_type_node;
-             DECL_ARG_TYPE (found) = double_type_node;
-             layout_decl (found, 0);
-           }
-
          /* If no declaration found, default to int.  */
          if (!found)
            {
@@ -6577,11 +6650,7 @@ store_parm_decls ()
                             "prototype declaration");
                        }
                    }
-                 /* If -traditional, allow `int' argument to match
-                    `unsigned' prototype.  */
-                 else if (! (flag_traditional
-                             && TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == integer_type_node
-                             && TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node))
+                 else
                    {
                      error ("argument `%s' doesn't match prototype",
                             IDENTIFIER_POINTER (DECL_NAME (parm)));
@@ -6683,6 +6752,8 @@ store_parm_decls ()
      not safe to try to expand expressions involving them.  */
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
+
+  warn_shadow = saved_warn_shadow;
 }
 \f
 /* Finish up a function declaration and compile that function
@@ -6710,13 +6781,6 @@ finish_function (nested)
 
   DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
 
-  /* Obey `register' declarations if `setjmp' is called in this fn.  */
-  if (flag_traditional && current_function_calls_setjmp)
-    {
-      setjmp_protect (DECL_INITIAL (fndecl));
-      setjmp_protect_args ();
-    }
-
   if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
     {
       if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
@@ -6743,6 +6807,22 @@ finish_function (nested)
 
   /* Tie off the statement tree for this function.  */
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+
+  /* Complain if there's just no return statement.  */
+  if (warn_return_type
+      && TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
+      && !current_function_returns_value && !current_function_returns_null
+      /* Don't complain if we abort.  */
+      && !current_function_returns_abnormally
+      /* Don't warn for main().  */
+      && !MAIN_NAME_P (DECL_NAME (fndecl))
+      /* Or if they didn't actually specify a return type.  */
+      && !C_FUNCTION_IMPLICIT_INT (fndecl)
+      /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
+        inline function, as we might never be compiled separately.  */
+      && DECL_INLINE (fndecl))
+    warning ("no return statement in function returning non-void");
+
   /* Clear out memory we no longer need.  */
   free_after_parsing (cfun);
   /* Since we never call rest_of_compilation, we never clear
@@ -6767,8 +6847,13 @@ void
 c_expand_deferred_function (fndecl)
      tree fndecl;
 {
-  c_expand_body (fndecl, 0, 0);
-  current_function_decl = NULL;
+  /* DECL_INLINE or DECL_RESULT might got cleared after the inline
+     function was deferred, e.g. in duplicate_decls.  */
+  if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
+    {
+      c_expand_body (fndecl, 0, 0);
+      current_function_decl = NULL;
+    }
 }
 
 /* Generate the RTL for the body of FNDECL.  If NESTED_P is non-zero,
@@ -6802,7 +6887,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
              function could not be deferred.  */
          && defer_fn (fndecl))
        {
-         /* Let the back-end know that this funtion exists.  */
+         /* Let the back-end know that this function exists.  */
          (*debug_hooks->deferred_inline_function) (fndecl);
           timevar_pop (TV_INTEGRATION);
          return;
@@ -6826,6 +6911,7 @@ c_expand_body (fndecl, nested_p, can_defer_p)
 
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
+  input_filename = DECL_SOURCE_FILE (fndecl);
   init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
 
   /* This function is being processed in whole-function mode.  */
@@ -7026,6 +7112,7 @@ struct c_language_function
   tree shadowed_labels;
   int returns_value;
   int returns_null;
+  int returns_abnormally;
   int warn_about_return_type;
   int extern_inline;
   struct binding_level *binding_level;
@@ -7049,6 +7136,7 @@ push_c_function_context (f)
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
   p->returns_null = current_function_returns_null;
+  p->returns_abnormally = current_function_returns_abnormally;
   p->warn_about_return_type = warn_about_return_type;
   p->extern_inline = current_extern_inline;
   p->binding_level = current_binding_level;
@@ -7086,6 +7174,7 @@ pop_c_function_context (f)
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
   current_function_returns_null = p->returns_null;
+  current_function_returns_abnormally = p->returns_abnormally;
   warn_about_return_type = p->warn_about_return_type;
   current_extern_inline = p->extern_inline;
   current_binding_level = p->binding_level;
@@ -7112,10 +7201,10 @@ mark_c_function_context (f)
   mark_binding_level (&p->binding_level);
 }
 
-/* Copy the DECL_LANG_SPECIFIC data associated with NODE.  */
+/* Copy the DECL_LANG_SPECIFIC data associated with DECL.  */
 
 void
-copy_lang_decl (decl)
+c_dup_lang_specific_decl (decl)
      tree decl;
 {
   struct lang_decl *ld;