OSDN Git Service

* testsuite/g++.dg/charset/function.cc: New.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 3ba73dd..3cf1baa 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -42,6 +42,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-inline.h"
 #include "c-tree.h"
 #include "toplev.h"
+#include "tree-iterator.h"
+#include "hashtab.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -55,6 +57,10 @@ cpp_reader *parse_in;                /* Declared in c-pragma.h.  */
 #define SIZE_TYPE "long unsigned int"
 #endif
 
+#ifndef PID_TYPE
+#define PID_TYPE "int"
+#endif
+
 #ifndef WCHAR_TYPE
 #define WCHAR_TYPE "int"
 #endif
@@ -599,23 +605,6 @@ int flag_permissive;
 
 int flag_enforce_eh_specs = 1;
 
-/*  The version of the C++ ABI in use.  The following values are
-    allowed:
-
-    0: The version of the ABI believed most conformant with the
-       C++ ABI specification.  This ABI may change as bugs are
-       discovered and fixed.  Therefore, 0 will not necessarily
-       indicate the same ABI in different versions of G++.
-
-    1: The version of the ABI first used in G++ 3.2.
-
-    2: The version of the ABI first used in G++ 3.4.
-
-    Additional positive integers will be assigned as new versions of
-    the ABI become the default version of the ABI.  */
-
-int flag_abi_version = 2;
-
 /* Nonzero means warn about things that will change when compiling
    with an ABI-compliant compiler.  */
 
@@ -694,6 +683,15 @@ tree *ridpointers;
 
 tree (*make_fname_decl) (tree, int);
 
+/* If non-NULL, the address of a language-specific function that
+   returns 1 for language-specific statement codes.  */
+int (*lang_statement_code_p) (enum tree_code);
+
+/* If non-NULL, the address of a language-specific function that does any
+   language-specific gimplification for _STMT nodes and returns 1 iff
+   handled.  */
+int (*lang_gimplify_stmt) (tree *, tree *);
+
 /* If non-NULL, the address of a language-specific function that takes
    any action required right before expand_function_end is called.  */
 void (*lang_expand_function_end) (void);
@@ -784,7 +782,6 @@ static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
                                                 bool *);
-static tree vector_size_helper (tree, tree);
 
 static void check_function_nonnull (tree, tree);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -932,7 +929,7 @@ c_expand_end_cond (void)
   if_stack_pointer--;
   if (if_stack[if_stack_pointer].needs_warning)
     warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
-             &if_stack[if_stack_pointer].locus);
+            &if_stack[if_stack_pointer].locus);
   last_expr_type = NULL_TREE;
 }
 
@@ -1053,7 +1050,13 @@ finish_fname_decls (void)
       tree *p = &DECL_SAVED_TREE (current_function_decl);
       /* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK.  */
       while (TREE_CODE (*p) != COMPOUND_STMT)
-       p = &TREE_CHAIN (*p);
+       {
+         if (TREE_CODE (*p) == EXPR_STMT)
+           p = &TREE_CHAIN (*p);
+         else
+           p = &TREE_OPERAND(*p, 0);
+       }
+
       p = &COMPOUND_BODY (*p);
       if (TREE_CODE (*p) == SCOPE_STMT)
        p = &TREE_CHAIN (*p);
@@ -1083,12 +1086,13 @@ finish_fname_decls (void)
 }
 
 /* Return the text name of the current function, suitably prettified
-   by PRETTY_P.  */
+   by PRETTY_P.  Return string must be freed by caller.  */
 
 const char *
 fname_as_string (int pretty_p)
 {
   const char *name = "top level";
+  char *namep;
   int vrb = 2;
 
   if (! pretty_p)
@@ -1098,9 +1102,28 @@ fname_as_string (int pretty_p)
     }
 
   if (current_function_decl)
-    name = (*lang_hooks.decl_printable_name) (current_function_decl, vrb);
+    name = lang_hooks.decl_printable_name (current_function_decl, vrb);
+
+  if (c_lex_string_translate)
+    {
+      int len = strlen (name) + 3; /* Two for '"'s.  One for NULL.  */
+      cpp_string cstr = { 0, 0 }, strname;
+
+      namep = xmalloc (len);
+      snprintf (namep, len, "\"%s\"", name);
+      strname.text = (unsigned char *) namep;
+      strname.len = len - 1;
+
+      if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
+       return (char *) cstr.text;
+    }
+  else
+    {
+      namep = (char *) xcalloc (strlen (name) + 1, sizeof (char));
+      namep = xstrdup (name);
+    }
 
-  return name;
+  return namep;
 }
 
 /* Return the VAR_DECL for a const char array naming the current
@@ -1176,7 +1199,7 @@ fix_string_type (tree value)
      -Wwrite-strings says make the string constant an array of const char
      so that copying it to a non-const pointer will get a warning.
      For C++, this is the standard behavior.  */
-  if (flag_const_strings && ! flag_writable_strings)
+  if (flag_const_strings)
     {
       tree elements
        = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
@@ -1191,7 +1214,8 @@ fix_string_type (tree value)
                          build_index_type (build_int_2 (nchars - 1, 0)));
 
   TREE_CONSTANT (value) = 1;
-  TREE_READONLY (value) = ! flag_writable_strings;
+  TREE_INVARIANT (value) = 1;
+  TREE_READONLY (value) = 1;
   TREE_STATIC (value) = 1;
   return value;
 }
@@ -1260,7 +1284,7 @@ unsigned_conversion_warning (tree result, tree operand)
 
   if (TREE_CODE (operand) == INTEGER_CST
       && TREE_CODE (type) == INTEGER_TYPE
-      && TREE_UNSIGNED (type)
+      && TYPE_UNSIGNED (type)
       && skip_evaluation == 0
       && !int_fits_type_p (operand, type))
     {
@@ -1285,6 +1309,16 @@ constant_fits_type_p (tree c, tree type)
   return !TREE_OVERFLOW (c);
 }
 
+/* Nonzero if vector types T1 and T2 can be converted to each other
+   without an explicit cast.  */
+int
+vector_types_convertible_p (tree t1, tree t2)
+{
+  return targetm.vector_opaque_p (t1)
+        || targetm.vector_opaque_p (t2)
+        || TYPE_MODE (t1) == TYPE_MODE (t2);
+}
+
 /* Convert EXPR to TYPE, warning about conversion problems with constants.
    Invoke this function on every expression that is converted implicitly,
    i.e. because of language rules and not because of an explicit cast.  */
@@ -1304,16 +1338,16 @@ convert_and_check (tree type, tree expr)
          TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (expr);
 
          /* No warning for converting 0x80000000 to int.  */
-         if (!(TREE_UNSIGNED (type) < TREE_UNSIGNED (TREE_TYPE (expr))
+         if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr))
                && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
                && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
            /* If EXPR fits in the unsigned version of TYPE,
               don't warn unless pedantic.  */
            if ((pedantic
-                || TREE_UNSIGNED (type)
+                || TYPE_UNSIGNED (type)
                 || ! constant_fits_type_p (expr,
                                            c_common_unsigned_type (type)))
-               && skip_evaluation == 0)
+               && skip_evaluation == 0)
              warning ("overflow in implicit constant conversion");
        }
       else
@@ -1678,7 +1712,6 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
     case 'r':
     case '<':
     case '2':
-    case 'b':
     case 'e':
     case 's':
     case 'x':
@@ -1849,7 +1882,7 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 
   if (mode == TYPE_MODE (widest_integer_literal_type_node))
     return unsignedp ? widest_unsigned_literal_type_node
-                     : widest_integer_literal_type_node;
+                    : widest_integer_literal_type_node;
 
   if (mode == QImode)
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
@@ -1886,38 +1919,12 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
   if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
     return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
 
-  switch (mode)
-    {
-    case V16QImode:
-      return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
-    case V8HImode:
-      return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
-    case V4SImode:
-      return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
-    case V2DImode:
-      return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
-    case V2SImode:
-      return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
-    case V2HImode:
-      return unsignedp ? unsigned_V2HI_type_node : V2HI_type_node;
-    case V4HImode:
-      return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
-    case V8QImode:
-      return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
-    case V1DImode:
-      return unsignedp ? unsigned_V1DI_type_node : V1DI_type_node;
-    case V16SFmode:
-      return V16SF_type_node;
-    case V4SFmode:
-      return V4SF_type_node;
-    case V2SFmode:
-      return V2SF_type_node;
-    case V2DFmode:
-      return V2DF_type_node;
-    case V4DFmode:
-      return V4DF_type_node;
-    default:
-      break;
+  if (VECTOR_MODE_P (mode))
+    {
+      enum machine_mode inner_mode = GET_MODE_INNER (mode);
+      tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+      if (inner_type != NULL_TREE)
+       return build_vector_type_for_mode (inner_type, mode);
     }
 
   for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
@@ -2001,7 +2008,7 @@ tree
 c_common_signed_or_unsigned_type (int unsignedp, tree type)
 {
   if (! INTEGRAL_TYPE_P (type)
-      || TREE_UNSIGNED (type) == unsignedp)
+      || TYPE_UNSIGNED (type) == unsignedp)
     return type;
 
   /* Must check the mode of the types, not the precision.  Enumeral types
@@ -2186,9 +2193,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
      but it *requires* conversion to FINAL_TYPE.  */
 
   if (op0 == primop0 && TREE_TYPE (op0) != *restype_ptr)
-    unsignedp0 = TREE_UNSIGNED (TREE_TYPE (op0));
+    unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (op0));
   if (op1 == primop1 && TREE_TYPE (op1) != *restype_ptr)
-    unsignedp1 = TREE_UNSIGNED (TREE_TYPE (op1));
+    unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (op1));
 
   /* If one of the operands must be floated, we cannot optimize.  */
   real1 = TREE_CODE (TREE_TYPE (primop0)) == REAL_TYPE;
@@ -2260,14 +2267,14 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       int min_gt, max_gt, min_lt, max_lt;
       tree maxval, minval;
       /* 1 if comparison is nominally unsigned.  */
-      int unsignedp = TREE_UNSIGNED (*restype_ptr);
+      int unsignedp = TYPE_UNSIGNED (*restype_ptr);
       tree val;
 
       type = c_common_signed_or_unsigned_type (unsignedp0,
                                               TREE_TYPE (primop0));
 
       /* In C, if TYPE is an enumeration, then we need to get its
-        min/max values from it's underlying integral type, not the
+        min/max values from its underlying integral type, not the
         enumerated type itself.  In C++, TYPE_MAX_VALUE and
         TYPE_MIN_VALUE have already been set correctly on the
         enumeration type.  */
@@ -2417,7 +2424,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
     {
       type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
       type = c_common_signed_or_unsigned_type (unsignedp0
-                                              || TREE_UNSIGNED (*restype_ptr),
+                                              || TYPE_UNSIGNED (*restype_ptr),
                                               type);
       /* Make sure shorter operand is extended the right way
         to match the longer operand.  */
@@ -2439,7 +2446,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       primop1 = op1;
 
       if (!real1 && !real2 && integer_zerop (primop1)
-         && TREE_UNSIGNED (*restype_ptr))
+         && TYPE_UNSIGNED (*restype_ptr))
        {
          tree value = 0;
          switch (code)
@@ -2497,9 +2504,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 {
   tree size_exp;
 
-  tree result;
-  tree folded;
-
   /* The result is a pointer of the same type that is being added.  */
 
   tree result_type = TREE_TYPE (ptrop);
@@ -2522,12 +2526,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
        pedwarn ("pointer to member function used in arithmetic");
       size_exp = integer_one_node;
     }
-  else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
-    {
-      if (pedantic || warn_pointer_arith)
-       pedwarn ("pointer to a member used in arithmetic");
-      size_exp = integer_one_node;
-    }
   else
     size_exp = size_in_bytes (TREE_TYPE (result_type));
 
@@ -2546,7 +2544,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
       /* If the constant is unsigned, and smaller than the pointer size,
         then we must skip this optimization.  This is because it could cause
         an overflow error if the constant is negative but INTOP is not.  */
-      && (! TREE_UNSIGNED (TREE_TYPE (intop))
+      && (! TYPE_UNSIGNED (TREE_TYPE (intop))
          || (TYPE_PRECISION (TREE_TYPE (intop))
              == TYPE_PRECISION (TREE_TYPE (ptrop)))))
     {
@@ -2566,9 +2564,9 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      so the multiply won't overflow spuriously.  */
 
   if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
-      || TREE_UNSIGNED (TREE_TYPE (intop)) != TREE_UNSIGNED (sizetype))
+      || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
     intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
-                                            TREE_UNSIGNED (sizetype)), intop);
+                                            TYPE_UNSIGNED (sizetype)), intop);
 
   /* Replace the integer argument with a suitable product by the object size.
      Do this multiplication as signed, then convert to the appropriate
@@ -2579,13 +2577,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
                                    convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
-
-  result = build (resultcode, result_type, ptrop, intop);
-
-  folded = fold (result);
-  if (folded == result)
-    TREE_CONSTANT (folded) = TREE_CONSTANT (ptrop) & TREE_CONSTANT (intop);
-  return folded;
+  return fold (build (resultcode, result_type, ptrop, intop));
 }
 \f
 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
@@ -2608,32 +2600,12 @@ c_common_truthvalue_conversion (tree expr)
   if (TREE_CODE (expr) == FUNCTION_DECL)
     expr = build_unary_op (ADDR_EXPR, expr, 0);
 
-#if 0 /* This appears to be wrong for C++.  */
-  /* These really should return error_mark_node after 2.4 is stable.
-     But not all callers handle ERROR_MARK properly.  */
-  switch (TREE_CODE (TREE_TYPE (expr)))
-    {
-    case RECORD_TYPE:
-      error ("struct type value used where scalar is required");
-      return truthvalue_false_node;
-
-    case UNION_TYPE:
-      error ("union type value used where scalar is required");
-      return truthvalue_false_node;
-
-    case ARRAY_TYPE:
-      error ("array type value used where scalar is required");
-      return truthvalue_false_node;
-
-    default:
-      break;
-    }
-#endif /* 0 */
-
   switch (TREE_CODE (expr))
     {
-    case EQ_EXPR:
-    case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
+    case EQ_EXPR:   case NE_EXPR:   case UNEQ_EXPR: case LTGT_EXPR:
+    case LE_EXPR:   case GE_EXPR:   case LT_EXPR:   case GT_EXPR:
+    case UNLE_EXPR: case UNGE_EXPR: case UNLT_EXPR: case UNGT_EXPR:
+    case ORDERED_EXPR: case UNORDERED_EXPR:
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_AND_EXPR:
@@ -2680,15 +2652,15 @@ c_common_truthvalue_conversion (tree expr)
     case COMPLEX_EXPR:
       return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0)),
+               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 1)),
                              0);
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
-      return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+      return lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -2696,15 +2668,15 @@ c_common_truthvalue_conversion (tree expr)
         we can't ignore them if their second arg has side-effects.  */
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build (COMPOUND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 1),
-                     c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                     lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0)));
       else
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       return fold (build (COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2))));
+               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 2))));
 
     case CONVERT_EXPR:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -2717,7 +2689,7 @@ c_common_truthvalue_conversion (tree expr)
       /* If this is widening the argument, we can ignore it.  */
       if (TYPE_PRECISION (TREE_TYPE (expr))
          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0));
       break;
 
     case MINUS_EXPR:
@@ -2766,8 +2738,8 @@ c_common_truthvalue_conversion (tree expr)
       return (build_binary_op
              ((TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-       c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
-       c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+       lang_hooks.truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
+       lang_hooks.truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
               0));
     }
 
@@ -2848,6 +2820,49 @@ c_apply_type_quals_to_decl (int type_quals, tree decl)
     }
 }
 
+/* Hash function for the problem of multiple type definitions in
+   different files.  This must hash all types that will compare
+   equal via comptypes to the same value.  In practice it hashes
+   on some of the simple stuff and leaves the details to comptypes. */
+
+static hashval_t
+c_type_hash (const void *p)
+{
+  int i = 0;
+  int shift, size;
+  tree t = (tree)p;
+  tree t2;
+  switch (TREE_CODE (t))
+    {
+      /* For pointers, hash on pointee type plus some swizzling. */
+      case POINTER_TYPE:
+  return c_type_hash (TREE_TYPE (t)) ^ 0x3003003;
+      /* Hash on number of elements and total size.  */
+      case ENUMERAL_TYPE:
+  shift = 3;
+  t2 = TYPE_VALUES (t);
+  break;
+      case RECORD_TYPE:
+  shift = 0;
+  t2 = TYPE_FIELDS (t);
+  break;
+      case QUAL_UNION_TYPE:
+  shift = 1;
+  t2 = TYPE_FIELDS (t);
+  break;
+      case UNION_TYPE:
+  shift = 2;
+  t2 = TYPE_FIELDS (t);
+  break;
+      default:
+  abort ();
+    }
+  for (; t2; t2 = TREE_CHAIN (t2))
+    i++;
+  size = TREE_INT_CST_LOW (TYPE_SIZE (t));
+  return ((size << 24) | (i << shift));
+}
+
 /* Return the typed-based alias set for T, which may be an expression
    or a type.  Return -1 if we don't do anything special.  */
 
@@ -2855,6 +2870,8 @@ HOST_WIDE_INT
 c_common_get_alias_set (tree t)
 {
   tree u;
+  PTR *slot;
+  static htab_t type_hash_table;
 
   /* Permit type-punning when accessing a union, provided the access
      is directly through the union.  For example, this code does not
@@ -2887,7 +2904,7 @@ c_common_get_alias_set (tree t)
   /* The C standard specifically allows aliasing between signed and
      unsigned variants of the same type.  We treat the signed
      variant as canonical.  */
-  if (TREE_CODE (t) == INTEGER_TYPE && TREE_UNSIGNED (t))
+  if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
     {
       tree t1 = c_common_signed_type (t);
 
@@ -2911,14 +2928,14 @@ c_common_get_alias_set (tree t)
         technically, an `int **' and `const int **' cannot point at
         the same thing.
 
-         But, the standard is wrong.  In particular, this code is
+        But, the standard is wrong.  In particular, this code is
         legal C++:
 
             int *ip;
             int **ipp = &ip;
-            const int* const* cipp = &ipp;
+            const int* const* cipp = ipp;
 
-         And, it doesn't make sense for that to be legal unless you
+        And, it doesn't make sense for that to be legal unless you
         can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
         the pointed-to types.  This issue has been reported to the
         C++ committee.  */
@@ -2927,6 +2944,63 @@ c_common_get_alias_set (tree t)
        return get_alias_set (t1);
     }
 
+  /* Handle the case of multiple type nodes referring to "the same" type,
+     which occurs with IMA.  These share an alias set.  FIXME:  Currently only
+     C90 is handled.  (In C99 type compatibility is not transitive, which
+     complicates things mightily. The alias set splay trees can theoretically
+     represent this, but insertion is tricky when you consider all the
+     different orders things might arrive in.) */
+
+  if (c_language != clk_c || flag_isoc99)
+    return -1;
+
+  /* Save time if there's only one input file. */
+  if (!current_file_decl || TREE_CHAIN (current_file_decl) == NULL_TREE)
+    return -1;
+
+  /* Pointers need special handling if they point to any type that
+     needs special handling (below).  */
+  if (TREE_CODE (t) == POINTER_TYPE)
+    {
+      tree t2;
+      /* Find bottom type under any nested POINTERs.  */
+      for (t2 = TREE_TYPE (t); 
+     TREE_CODE (t2) == POINTER_TYPE;
+     t2 = TREE_TYPE (t2))
+  ;
+      if (TREE_CODE (t2) != RECORD_TYPE 
+    && TREE_CODE (t2) != ENUMERAL_TYPE
+    && TREE_CODE (t2) != QUAL_UNION_TYPE
+    && TREE_CODE (t2) != UNION_TYPE)
+  return -1;
+      if (TYPE_SIZE (t2) == 0)
+  return -1;
+    }
+  /* These are the only cases that need special handling.  */
+  if (TREE_CODE (t) != RECORD_TYPE 
+      && TREE_CODE (t) != ENUMERAL_TYPE
+      && TREE_CODE (t) != QUAL_UNION_TYPE
+      && TREE_CODE (t) != UNION_TYPE
+      && TREE_CODE (t) != POINTER_TYPE)
+    return -1;
+  /* Undefined? */
+  if (TYPE_SIZE (t) == 0)
+    return -1;
+
+  /* Look up t in hash table.  Only one of the compatible types within each 
+     alias set is recorded in the table.  */
+  if (!type_hash_table)
+    type_hash_table = htab_create (1021, c_type_hash,
+           (htab_eq) lang_hooks.types_compatible_p,
+           NULL);
+  slot = htab_find_slot (type_hash_table, t, INSERT);
+  if (*slot != NULL)
+    return TYPE_ALIAS_SET ((tree)*slot);
+  else
+    /* Our caller will assign and record (in t) a new alias set; all we need
+       to do is remember t in the hash table.  */
+    *slot = t;
+
   return -1;
 }
 \f
@@ -3133,43 +3207,43 @@ c_common_nodes_and_builtins (void)
 
   /* These are types that c_common_type_for_size and
      c_common_type_for_mode use.  */
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intQI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intHI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intSI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           intDI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intQI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intHI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intSI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("__int128_t"),
-                                           intTI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("__int128_t"),
+                                        intTI_type_node));
 #endif
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intQI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intHI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intSI_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           unsigned_intDI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intQI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intHI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intSI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("__uint128_t"),
-                                           unsigned_intTI_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("__uint128_t"),
+                                        unsigned_intTI_type_node));
 #endif
 
   /* Create the widest literal types.  */
   widest_integer_literal_type_node
     = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           widest_integer_literal_type_node));
+  lang_hooks.decls.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);
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, NULL_TREE,
-                                           widest_unsigned_literal_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
+                                        widest_unsigned_literal_type_node));
 
   /* `unsigned long' is the standard type for sizeof.
      Note that stddef.h uses `unsigned long',
@@ -3179,78 +3253,28 @@ c_common_nodes_and_builtins (void)
   signed_size_type_node = c_common_signed_type (size_type_node);
   set_sizetype (size_type_node);
 
+  pid_type_node =
+    TREE_TYPE (identifier_global_value (get_identifier (PID_TYPE)));
+
   build_common_tree_nodes_2 (flag_short_double);
 
   record_builtin_type (RID_FLOAT, NULL, float_type_node);
   record_builtin_type (RID_DOUBLE, NULL, double_type_node);
   record_builtin_type (RID_MAX, "long double", long_double_type_node);
 
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("complex int"),
-                                           complex_integer_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("complex float"),
-                                           complex_float_type_node));
-  (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                           get_identifier ("complex double"),
-                                           complex_double_type_node));
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("complex int"),
+                                        complex_integer_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("complex float"),
+                                        complex_float_type_node));
+  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                        get_identifier ("complex double"),
+                                        complex_double_type_node));
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("complex long double"),
                 complex_long_double_type_node));
 
-  /* Types which are common to the fortran compiler and libf2c.  When
-     changing these, you also need to be concerned with f/com.h.  */
-
-  if (TYPE_PRECISION (float_type_node)
-      == TYPE_PRECISION (long_integer_type_node))
-    {
-      g77_integer_type_node = long_integer_type_node;
-      g77_uinteger_type_node = long_unsigned_type_node;
-    }
-  else if (TYPE_PRECISION (float_type_node)
-          == TYPE_PRECISION (integer_type_node))
-    {
-      g77_integer_type_node = integer_type_node;
-      g77_uinteger_type_node = unsigned_type_node;
-    }
-  else
-    g77_integer_type_node = g77_uinteger_type_node = NULL_TREE;
-
-  if (g77_integer_type_node != NULL_TREE)
-    {
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_integer"),
-                                               g77_integer_type_node));
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_uinteger"),
-                                               g77_uinteger_type_node));
-    }
-
-  if (TYPE_PRECISION (float_type_node) * 2
-      == TYPE_PRECISION (long_integer_type_node))
-    {
-      g77_longint_type_node = long_integer_type_node;
-      g77_ulongint_type_node = long_unsigned_type_node;
-    }
-  else if (TYPE_PRECISION (float_type_node) * 2
-          == TYPE_PRECISION (long_long_integer_type_node))
-    {
-      g77_longint_type_node = long_long_integer_type_node;
-      g77_ulongint_type_node = long_long_unsigned_type_node;
-    }
-  else
-    g77_longint_type_node = g77_ulongint_type_node = NULL_TREE;
-
-  if (g77_longint_type_node != NULL_TREE)
-    {
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_longint"),
-                                               g77_longint_type_node));
-      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-                                               get_identifier ("__g77_ulongint"),
-                                               g77_ulongint_type_node));
-    }
-
   record_builtin_type (RID_VOID, NULL, void_type_node);
 
   void_zero_node = build_int_2 (0, 0);
@@ -3286,7 +3310,7 @@ c_common_nodes_and_builtins (void)
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
   if (c_dialect_cxx ())
     {
-      if (TREE_UNSIGNED (wchar_type_node))
+      if (TYPE_UNSIGNED (wchar_type_node))
        wchar_type_node = make_unsigned_type (wchar_type_size);
       else
        wchar_type_node = make_signed_type (wchar_type_size);
@@ -3315,15 +3339,15 @@ c_common_nodes_and_builtins (void)
     = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
   unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
 
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
                 va_list_type_node));
 
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_ptrdiff_t"),
                 ptrdiff_type_node));
 
-  (*lang_hooks.decls.pushdecl)
+  lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_size_t"),
                 sizetype));
 
@@ -3462,12 +3486,12 @@ c_common_nodes_and_builtins (void)
                                                                        \
       built_in_decls[(int) ENUM] = decl;                               \
       if (IMPLICIT)                                                    \
-        implicit_built_in_decls[(int) ENUM] = decl;                    \
+       implicit_built_in_decls[(int) ENUM] = decl;                     \
     }
 #include "builtins.def"
 #undef DEF_BUILTIN
 
-  (*targetm.init_builtins) ();
+  targetm.init_builtins ();
 
   main_identifier_node = get_identifier ("main");
 }
@@ -3892,19 +3916,12 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
   splay_tree_node node;
 
   /* Create the LABEL_DECL itself.  */
-  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-  DECL_CONTEXT (label) = current_function_decl;
+  label = create_artificial_label ();
 
   /* If there was an error processing the switch condition, bail now
      before we get more confused.  */
   if (!cond || cond == error_mark_node)
-    {
-      /* Add a label anyhow so that the back-end doesn't think that
-        the beginning of the switch is unreachable.  */
-      if (!cases->root)
-       add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
-      return error_mark_node;
-    }
+    goto error_out;
 
   if ((low_value && TREE_TYPE (low_value)
        && POINTER_TYPE_P (TREE_TYPE (low_value)))
@@ -3930,11 +3947,7 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
 
   /* If an error has occurred, bail out now.  */
   if (low_value == error_mark_node || high_value == error_mark_node)
-    {
-      if (!cases->root)
-       add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
-      return error_mark_node;
-    }
+    goto error_out;
 
   /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
      really a case range, even though it was written that way.  Remove
@@ -4007,8 +4020,7 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
          error ("multiple default labels in one switch");
          error ("%Jthis is the first default label", duplicate);
        }
-      if (!cases->root)
-       add_stmt (build_case_label (NULL_TREE, NULL_TREE, label));
+      goto error_out;
     }
 
   /* Add a CASE_LABEL to the statement-tree.  */
@@ -4019,6 +4031,160 @@ c_add_case_label (splay_tree cases, tree cond, tree low_value,
                     (splay_tree_value) case_label);
 
   return case_label;
+
+ error_out:
+  /* Add a label so that the back-end doesn't think that the beginning o
+     the switch is unreachable.  Note that we do not add a case label, as
+     that just leads to duplicates and thence to aborts later on.  */
+  if (!cases->root)
+    {
+      tree t = create_artificial_label ();
+      add_stmt (build_stmt (LABEL_STMT, t));
+    }
+  return error_mark_node;
+}
+
+/* Subroutines of c_do_switch_warnings, called via splay_tree_foreach.
+   Used to verify that case values match up with enumerator values.  */
+
+static void
+match_case_to_enum_1 (tree key, tree type, tree label)
+{
+  char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
+
+  /* ??? Not working too hard to print the double-word value.
+     Should perhaps be done with %lwd in the diagnostic routines?  */
+  if (TREE_INT_CST_HIGH (key) == 0)
+    snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
+             TREE_INT_CST_LOW (key));
+  else if (!TYPE_UNSIGNED (type)
+          && TREE_INT_CST_HIGH (key) == -1
+          && TREE_INT_CST_LOW (key) != 0)
+    snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
+             -TREE_INT_CST_LOW (key));
+  else
+    snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+             TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key));
+
+  if (TYPE_NAME (type) == 0)
+    warning ("%Jcase value `%s' not in enumerated type",
+            CASE_LABEL_DECL (label), buf);
+  else
+    warning ("%Jcase value `%s' not in enumerated type `%T'",
+            CASE_LABEL_DECL (label), buf, type);
+}
+
+static int
+match_case_to_enum (splay_tree_node node, void *data)
+{
+  tree label = (tree) node->value;
+  tree type = data;
+
+  /* Skip default case.  */
+  if (!CASE_LOW (label))
+    return 0;
+
+  /* If TREE_ADDRESSABLE is not set, that means CASE_LOW did not appear
+     when we did our enum->case scan.  Reset our scratch bit after.  */
+  if (!TREE_ADDRESSABLE (label))
+    match_case_to_enum_1 (CASE_LOW (label), type, label);
+  else
+    TREE_ADDRESSABLE (label) = 0;
+
+  /* If CASE_HIGH is non-null, we have a range.  Here we must search.
+     Note that the old code in stmt.c did not check for the values in
+     the range either, just the endpoints.  */
+  if (CASE_HIGH (label))
+    {
+      tree chain, key = CASE_HIGH (label);
+
+      for (chain = TYPE_VALUES (type);
+          chain && !tree_int_cst_equal (key, TREE_VALUE (chain));
+          chain = TREE_CHAIN (chain))
+       continue;
+      if (!chain)
+       match_case_to_enum_1 (key, type, label);
+    }
+
+  return 0;
+}
+
+/* Handle -Wswitch*.  Called from the front end after parsing the switch
+   construct.  */
+/* ??? Should probably be somewhere generic, since other languages besides
+   C and C++ would want this.  We'd want to agree on the datastructure,
+   however, which is a problem.  Alternately, we operate on gimplified
+   switch_exprs, which I don't especially like.  At the moment, however,
+   C/C++ are the only tree-ssa languages that support enumerations at all,
+   so the point is moot.  */
+
+void
+c_do_switch_warnings (splay_tree cases, tree switch_stmt)
+{
+  splay_tree_node default_node;  
+  location_t *switch_locus;
+  tree type;
+
+  if (!warn_switch && !warn_switch_enum && !warn_switch_default)
+    return;
+
+  switch_locus = EXPR_LOCUS (switch_stmt);
+  if (!switch_locus)
+    switch_locus = &input_location;
+  type = SWITCH_TYPE (switch_stmt);
+
+  default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
+  if (warn_switch_default && !default_node)
+    warning ("%Hswitch missing default case", switch_locus);
+
+  /* If the switch expression was an enumerated type, check that
+     exactly all enumeration literals are covered by the cases.
+     The check is made when -Wswitch was specified and there is no
+     default case, or when -Wswitch-enum was specified.  */
+  if (((warn_switch && !default_node) || warn_switch_enum)
+      && type && TREE_CODE (type) == ENUMERAL_TYPE
+      && TREE_CODE (SWITCH_COND (switch_stmt)) != INTEGER_CST)
+    {
+      tree chain;
+
+      /* The time complexity here is O(N*lg(N)) worst case, but for the
+        common case of monotonically increasing enumerators, it is 
+        O(N), since the nature of the splay tree will keep the next
+        element adjacent to the root at all times.  */
+
+      for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
+       {
+         splay_tree_node node
+           = splay_tree_lookup (cases, (splay_tree_key) TREE_VALUE (chain));
+
+         if (node)
+           {
+             /* Mark the CASE_LOW part of the case entry as seen, so
+                that we save time later.  Choose TREE_ADDRESSABLE 
+                randomly as a bit that won't have been set to-date.  */
+             tree label = (tree) node->value;
+             TREE_ADDRESSABLE (label) = 1;
+           }
+         else
+           {
+             /* Warn if there are enumerators that don't correspond to
+                case expressions.  */
+             warning ("%Henumeration value `%E' not handled in switch",
+                      switch_locus, TREE_PURPOSE (chain));
+           }
+       }
+
+      /* Warn if there are case expressions that don't correspond to
+        enumerators.  This can occur since C and C++ don't enforce
+        type-checking of assignments to enumeration variables.
+
+        The time complexity here is O(N**2) worst case, since we've
+        not sorted the enumeration values.  However, in the absence
+        of case ranges this is O(N), since all single cases that 
+        corresponded to enumerations have been marked above.  */
+
+      splay_tree_foreach (cases, match_case_to_enum, type);
+    }
 }
 
 /* Finish an expression taking the address of LABEL (an
@@ -4042,7 +4208,6 @@ finish_label_address_expr (tree label)
     {
       TREE_USED (label) = 1;
       result = build1 (ADDR_EXPR, ptr_type_node, label);
-      TREE_CONSTANT (result) = 1;
       /* The current function in not necessarily uninlinable.
         Computed gotos are incompatible with inlining, but the value
         here could be used only in a diagnostic, for example.  */
@@ -4052,123 +4217,29 @@ finish_label_address_expr (tree label)
 }
 
 /* Hook used by expand_expr to expand language-specific tree codes.  */
+/* The only things that should go here are bits needed to expand 
+   constant initalizers.  Everything else should be handled by the
+   gimplification routines.  */
 
 rtx
-c_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier)
-     /* Actually enum_modifier.  */
+c_expand_expr (tree exp, rtx target, enum machine_mode tmode, 
+              int modifier /* Actually enum_modifier.  */,
+              rtx *alt_rtl)
 {
   switch (TREE_CODE (exp))
     {
-    case STMT_EXPR:
-      {
-       tree rtl_expr;
-       rtx result;
-       bool preserve_result = false;
-       bool return_target = false;
-
-       if (STMT_EXPR_WARN_UNUSED_RESULT (exp) && target == const0_rtx)
-         {
-           tree stmt = STMT_EXPR_STMT (exp);
-           tree scope;
-
-           for (scope = COMPOUND_BODY (stmt);
-                scope && TREE_CODE (scope) != SCOPE_STMT;
-                scope = TREE_CHAIN (scope));
-
-           if (scope && SCOPE_STMT_BLOCK (scope))
-             warning ("%Hignoring return value of `%D', "
-                      "declared with attribute warn_unused_result",
-                      &expr_wfl_stack->location,
-                      BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope)));
-           else
-             warning ("%Hignoring return value of function "
-                      "declared with attribute warn_unused_result",
-                      &expr_wfl_stack->location);
-         }
-
-       /* Since expand_expr_stmt calls free_temp_slots after every
-          expression statement, we must call push_temp_slots here.
-          Otherwise, any temporaries in use now would be considered
-          out-of-scope after the first EXPR_STMT from within the
-          STMT_EXPR.  */
-       push_temp_slots ();
-       rtl_expr = expand_start_stmt_expr (!STMT_EXPR_NO_SCOPE (exp));
-
-       /* If we want the result of this expression, find the last
-           EXPR_STMT in the COMPOUND_STMT and mark it as addressable.  */
-       if (target != const0_rtx
-           && TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT
-           && TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT)
-         {
-           tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp));
-           tree last = TREE_CHAIN (expr);
-
-           while (TREE_CHAIN (last))
-             {
-               expr = last;
-               last = TREE_CHAIN (last);
-             }
-
-           if (TREE_CODE (last) == SCOPE_STMT
-               && TREE_CODE (expr) == EXPR_STMT)
-             {
-               if (target && TREE_CODE (EXPR_STMT_EXPR (expr)) == VAR_DECL
-                   && DECL_RTL_IF_SET (EXPR_STMT_EXPR (expr)) == target)
-                 /* If the last expression is a variable whose RTL is the
-                    same as our target, just return the target; if it
-                    isn't valid expanding the decl would produce different
-                    RTL, and store_expr would try to do a copy.  */
-                 return_target = true;
-               else
-                 {
-                   /* Otherwise, note that we want the value from the last
-                      expression.  */
-                   TREE_ADDRESSABLE (expr) = 1;
-                   preserve_result = true;
-                 }
-             }
-         }
-
-       expand_stmt (STMT_EXPR_STMT (exp));
-       expand_end_stmt_expr (rtl_expr);
-
-       result = expand_expr (rtl_expr, target, tmode, modifier);
-       if (return_target)
-         result = target;
-       else if (preserve_result && GET_CODE (result) == MEM)
-         {
-           if (GET_MODE (result) != BLKmode)
-             result = copy_to_reg (result);
-           else
-             preserve_temp_slots (result);
-         }
-
-       /* If the statment-expression does not have a scope, then the
-          new temporaries we created within it must live beyond the
-          statement-expression.  */
-       if (STMT_EXPR_NO_SCOPE (exp))
-         preserve_temp_slots (NULL_RTX);
-
-       pop_temp_slots ();
-       return result;
-      }
-      break;
-
     case COMPOUND_LITERAL_EXPR:
       {
        /* Initialize the anonymous variable declared in the compound
           literal, then return the variable.  */
        tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
        emit_local_var (decl);
-       return expand_expr (decl, target, tmode, modifier);
+       return expand_expr_real (decl, target, tmode, modifier, alt_rtl);
       }
 
     default:
       abort ();
     }
-
-  abort ();
-  return NULL;
 }
 
 /* Hook used by safe_from_p to handle language-specific tree codes.  */
@@ -4294,21 +4365,6 @@ c_init_attributes (void)
 #undef DEF_ATTR_TREE_LIST
 }
 
-/* Output a -Wshadow warning MSGCODE about NAME, and give the location
-   of the previous declaration DECL.  */
-void
-shadow_warning (enum sw_kind msgcode, const char *name, tree decl)
-{
-  static const char *const msgs[] = {
-    /* SW_PARAM  */ N_("declaration of \"%s\" shadows a parameter"),
-    /* SW_LOCAL  */ N_("declaration of \"%s\" shadows a previous local"),
-    /* SW_GLOBAL */ N_("declaration of \"%s\" shadows a global declaration")
-  };
-
-  warning (msgs[msgcode], name);
-  warning ("%Jshadowed declaration is here", decl);
-}
-
 /* Attribute handlers common to C front ends.  */
 
 /* Handle a "packed" attribute; arguments as in
@@ -4408,7 +4464,7 @@ handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
     TREE_TYPE (*node)
       = build_pointer_type
        (build_type_variant (TREE_TYPE (type),
-                            TREE_READONLY (TREE_TYPE (type)), 1));
+                            TYPE_READONLY (TREE_TYPE (type)), 1));
   else
     {
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
@@ -4689,13 +4745,25 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
            mode = (enum machine_mode) j;
 
       if (mode == VOIDmode)
-       error ("unknown machine mode `%s'", p);
-      else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
-                    (mode, TREE_UNSIGNED (type))))
+       {
+         error ("unknown machine mode `%s'", p);
+         return NULL_TREE;
+       }
+
+      if (VECTOR_MODE_P (mode))
+       {
+         warning ("specifying vector types with __attribute__ ((mode)) "
+                  "is deprecated");
+         warning ("use __attribute__ ((vector_size)) instead");
+       }
+
+      typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+      if (typefm == NULL_TREE)
        error ("no data type for mode `%s'", p);
+
       else if ((TREE_CODE (type) == POINTER_TYPE
                || TREE_CODE (type) == REFERENCE_TYPE)
-              && !(*targetm.valid_pointer_mode) (mode))
+              && !targetm.valid_pointer_mode (mode))
        error ("invalid pointer mode `%s'", p);
       else
        {
@@ -4710,17 +4778,17 @@ handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
          if (TREE_CODE (type) == POINTER_TYPE)
            {
              ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
-                                                     mode);
+                                                     mode, false);
              *node = ptr_type;
            }
          else if (TREE_CODE (type) == REFERENCE_TYPE)
            {
              ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
-                                                       mode);
+                                                       mode, false);
              *node = ptr_type;
            }
          else
-         *node = typefm;
+           *node = typefm;
          /* No need to layout the type here.  The caller should do this.  */
        }
     }
@@ -4748,7 +4816,7 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
              && ! TREE_STATIC (decl))
            {
              error ("%Jsection attribute cannot be specified for "
-                     "local variables", decl);
+                    "local variables", decl);
              *no_add_attrs = true;
            }
 
@@ -4759,7 +4827,7 @@ handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
                              TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
            {
              error ("%Jsection of '%D' conflicts with previous declaration",
-                     *node, *node);
+                    *node, *node);
              *no_add_attrs = true;
            }
          else
@@ -4888,7 +4956,13 @@ handle_alias_attribute (tree *node, tree name, tree args,
       error ("%J'%D' defined both normally and as an alias", decl, decl);
       *no_add_attrs = true;
     }
-  else if (decl_function_context (decl) == 0)
+
+  /* Note that the very first time we process a nested declaration,
+     decl_function_context will not be set.  Indeed, *would* never
+     be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
+     we do below.  After such frobbery, pushdecl would set the context.
+     In any case, this is never what we want.  */
+  else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
     {
       tree id;
 
@@ -4906,7 +4980,10 @@ handle_alias_attribute (tree *node, tree name, tree args,
       if (TREE_CODE (decl) == FUNCTION_DECL)
        DECL_INITIAL (decl) = error_mark_node;
       else
-       DECL_EXTERNAL (decl) = 0;
+       {
+         DECL_EXTERNAL (decl) = 0;
+         TREE_STATIC (decl) = 1;
+       }
     }
   else
     {
@@ -5145,13 +5222,6 @@ handle_deprecated_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
-/* Keep a list of vector type nodes we created in handle_vector_size_attribute,
-   to prevent us from duplicating type nodes unnecessarily.
-   The normal mechanism to prevent duplicates is to use type_hash_canon, but
-   since we want to distinguish types that are essentially identical (except
-   for their debug representation), we use a local list here.  */
-static GTY(()) tree vector_type_node_list = 0;
-
 /* Handle a "vector_size" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -5162,19 +5232,24 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 {
   unsigned HOST_WIDE_INT vecsize, nunits;
   enum machine_mode mode, orig_mode, new_mode;
-  tree type = *node, new_type = NULL_TREE;
-  tree type_list_node;
+  tree type = *node, new_type, size;
 
   *no_add_attrs = true;
 
-  if (! host_integerp (TREE_VALUE (args), 1))
+  /* Stripping NON_LVALUE_EXPR allows declarations such as
+     typedef short v4si __attribute__((vector_size (4 * sizeof(short)))).  */
+  size = TREE_VALUE (args);
+  if (TREE_CODE (size) == NON_LVALUE_EXPR)
+    size = TREE_OPERAND (size, 0);
+
+  if (! host_integerp (size, 1))
     {
       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
       return NULL_TREE;
     }
 
   /* Get the vector size (in bytes).  */
-  vecsize = tree_low_cst (TREE_VALUE (args), 1);
+  vecsize = tree_low_cst (size, 1);
 
   /* We need to provide for vector pointers, vector arrays, and
      functions returning vectors.  For example:
@@ -5220,126 +5295,20 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
        break;
       }
 
-    if (new_mode == VOIDmode)
+  if (new_mode == VOIDmode)
     {
       error ("no vector mode with the size and type specified could be found");
       return NULL_TREE;
     }
 
-  for (type_list_node = vector_type_node_list; type_list_node;
-       type_list_node = TREE_CHAIN (type_list_node))
-    {
-      tree other_type = TREE_VALUE (type_list_node);
-      tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
-      tree fields = TYPE_FIELDS (record);
-      tree field_type = TREE_TYPE (fields);
-      tree array_type = TREE_TYPE (field_type);
-      if (TREE_CODE (fields) != FIELD_DECL
-         || TREE_CODE (field_type) != ARRAY_TYPE)
-       abort ();
-
-      if (TYPE_MODE (other_type) == mode && type == array_type)
-       {
-         new_type = other_type;
-         break;
-       }
-    }
-
-  if (new_type == NULL_TREE)
-    {
-      tree index, array, rt, list_node;
-
-      new_type = (*lang_hooks.types.type_for_mode) (new_mode,
-                                                   TREE_UNSIGNED (type));
-
-      if (!new_type)
-       {
-         error ("no vector mode with the size and type specified could be found");
-         return NULL_TREE;
-       }
-
-      new_type = build_type_copy (new_type);
-
-      /* If this is a vector, make sure we either have hardware
-         support, or we can emulate it.  */
-      if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
-          || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
-         && !vector_mode_valid_p (mode))
-       {
-         error ("unable to emulate '%s'", GET_MODE_NAME (mode));
-         return NULL_TREE;
-       }
-
-      /* Set the debug information here, because this is the only
-        place where we know the underlying type for a vector made
-        with vector_size.  For debugging purposes we pretend a vector
-        is an array within a structure.  */
-      index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
-      array = build_array_type (type, build_index_type (index));
-      rt = make_node (RECORD_TYPE);
-
-      TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
-      DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
-      layout_type (rt);
-      TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
-
-      list_node = build_tree_list (NULL, new_type);
-      TREE_CHAIN (list_node) = vector_type_node_list;
-      vector_type_node_list = list_node;
-    }
+  new_type = build_vector_type_for_mode (type, new_mode);
 
   /* Build back pointers if needed.  */
-  *node = vector_size_helper (*node, new_type);
+  *node = reconstruct_complex_type (*node, new_type);
 
   return NULL_TREE;
 }
 
-/* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
-   better way.
-
-   If we requested a pointer to a vector, build up the pointers that
-   we stripped off while looking for the inner type.  Similarly for
-   return values from functions.
-
-   The argument "type" is the top of the chain, and "bottom" is the
-   new type which we will point to.  */
-
-static tree
-vector_size_helper (tree type, tree bottom)
-{
-  tree inner, outer;
-
-  if (POINTER_TYPE_P (type))
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_pointer_type (inner);
-    }
-  else if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_array_type (inner, TYPE_DOMAIN (type));
-    }
-  else if (TREE_CODE (type) == FUNCTION_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_function_type (inner, TYPE_ARG_TYPES (type));
-    }
-  else if (TREE_CODE (type) == METHOD_TYPE)
-    {
-      inner = vector_size_helper (TREE_TYPE (type), bottom);
-      outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
-                                         inner, 
-                                         TYPE_ARG_TYPES (type));
-    }
-  else
-    return bottom;
-
-  TREE_READONLY (outer) = TREE_READONLY (type);
-  TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
-
-  return outer;
-}
-
 /* Handle the "nonnull" attribute.  */
 static tree
 handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
@@ -5357,7 +5326,7 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
       if (! TYPE_ARG_TYPES (type))
        {
          error ("nonnull attribute without arguments on a non-prototype");
-          *no_add_attrs = true;
+         *no_add_attrs = true;
        }
       return NULL_TREE;
     }
@@ -5367,7 +5336,7 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
   for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
     {
       tree argument;
-      unsigned HOST_WIDE_INT arg_num, ck_num;
+      unsigned HOST_WIDE_INT arg_num = 0, ck_num;
 
       if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
        {
@@ -5387,7 +5356,7 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
              argument = TREE_CHAIN (argument);
            }
 
-          if (! argument
+         if (! argument
              || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
            {
              error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
@@ -5396,7 +5365,7 @@ handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
              return NULL_TREE;
            }
 
-          if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
+         if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
            {
              error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
                   (unsigned long) attr_arg_num, (unsigned long) arg_num);
@@ -5422,22 +5391,22 @@ check_function_nonnull (tree attrs, tree params)
     {
       if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
        {
-          args = TREE_VALUE (a);
+         args = TREE_VALUE (a);
 
-          /* Walk the argument list.  If we encounter an argument number we
-             should check for non-null, do it.  If the attribute has no args,
-             then every pointer argument is checked (in which case the check
+         /* Walk the argument list.  If we encounter an argument number we
+            should check for non-null, do it.  If the attribute has no args,
+            then every pointer argument is checked (in which case the check
             for pointer type is done in check_nonnull_arg).  */
-          for (param = params, param_num = 1; ;
-               param_num++, param = TREE_CHAIN (param))
-            {
-              if (! param)
+         for (param = params, param_num = 1; ;
+              param_num++, param = TREE_CHAIN (param))
+           {
+             if (! param)
        break;
-              if (! args || nonnull_check_p (args, param_num))
+             if (! args || nonnull_check_p (args, param_num))
        check_function_arguments_recurse (check_nonnull_arg, NULL,
                                          TREE_VALUE (param),
                                          param_num);
-            }
+           }
        }
     }
 }
@@ -5449,12 +5418,12 @@ check_function_nonnull (tree attrs, tree params)
 static bool
 nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
 {
-  unsigned HOST_WIDE_INT arg_num;
+  unsigned HOST_WIDE_INT arg_num = 0;
 
   for (; args; args = TREE_CHAIN (args))
     {
       if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
-        abort ();
+       abort ();
 
       if (arg_num == param_num)
        return true;
@@ -5479,7 +5448,7 @@ check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param,
 
   if (integer_zerop (param))
     warning ("null argument where non-null required (arg %lu)",
-             (unsigned long) param_num);
+            (unsigned long) param_num);
 }
 
 /* Helper for nonnull attribute handling; fetch the operand number
@@ -5613,7 +5582,7 @@ check_function_arguments_recurse (void (*callback)
     {
       /* Strip coercion.  */
       check_function_arguments_recurse (callback, ctx,
-                                       TREE_OPERAND (param, 0), param_num);
+                                       TREE_OPERAND (param, 0), param_num);
       return;
     }
 
@@ -5675,15 +5644,74 @@ check_function_arguments_recurse (void (*callback)
     {
       /* Check both halves of the conditional expression.  */
       check_function_arguments_recurse (callback, ctx,
-                                       TREE_OPERAND (param, 1), param_num);
+                                       TREE_OPERAND (param, 1), param_num);
       check_function_arguments_recurse (callback, ctx,
-                                       TREE_OPERAND (param, 2), param_num);
+                                       TREE_OPERAND (param, 2), param_num);
       return;
     }
 
   (*callback) (ctx, param, param_num);
 }
 
+/* C implementation of lang_hooks.tree_inlining.walk_subtrees.  Tracks the
+   locus from EXPR_LOCUS and handles DECL_STMT specially.  */
+
+tree 
+c_walk_subtrees (tree *tp, int *walk_subtrees_p ATTRIBUTE_UNUSED,
+                walk_tree_fn func, void *data, void *htab)
+{
+  enum tree_code code = TREE_CODE (*tp);
+  location_t save_locus;
+  tree result;
+
+#define WALK_SUBTREE(NODE)                             \
+  do                                                   \
+    {                                                  \
+      result = walk_tree (&(NODE), func, data, htab);  \
+      if (result) goto out;                            \
+    }                                                  \
+  while (0)
+
+  if (code != DECL_STMT)
+    return NULL_TREE;
+
+  /* Set input_location here so we get the right instantiation context
+     if we call instantiate_decl from inlinable_function_p.  */
+  save_locus = input_location;
+  if (EXPR_LOCUS (*tp))
+    input_location = *EXPR_LOCUS (*tp);
+
+  /* Walk the DECL_INITIAL and DECL_SIZE.  We don't want to walk
+     into declarations that are just mentioned, rather than
+     declared; they don't really belong to this part of the tree.
+     And, we can see cycles: the initializer for a declaration can
+     refer to the declaration itself.  */
+  WALK_SUBTREE (DECL_INITIAL (DECL_STMT_DECL (*tp)));
+  WALK_SUBTREE (DECL_SIZE (DECL_STMT_DECL (*tp)));
+  WALK_SUBTREE (DECL_SIZE_UNIT (DECL_STMT_DECL (*tp)));
+  WALK_SUBTREE (TREE_CHAIN (*tp));
+  *walk_subtrees_p = 0;
+
+  /* We didn't find what we were looking for.  */
+ out:
+  input_location = save_locus;
+  return result;
+
+#undef WALK_SUBTREE
+}
+
+/* C implementation of lang_hooks.tree_inlining.tree_chain_matters_p.
+   Apart from TREE_LISTs, the only trees whose TREE_CHAIN we care about are
+   _STMT nodes.  */
+
+int
+c_tree_chain_matters_p (tree t)
+{
+  /* For statements, we also walk the chain so that we cover the
+     entire statement tree.  */
+  return STATEMENT_CODE_P (TREE_CODE (t));
+}
+
 /* Function to help qsort sort FIELD_DECLs by name order.  */
 
 int
@@ -5739,155 +5767,15 @@ resort_field_decl_cmp (const void *x_p, const void *y_p)
 
 void
 resort_sorted_fields (void *obj,
-                      void *orig_obj ATTRIBUTE_UNUSED ,
-                      gt_pointer_operator new_value,
-                      void *cookie)
+                     void *orig_obj ATTRIBUTE_UNUSED ,
+                     gt_pointer_operator new_value,
+                     void *cookie)
 {
   struct sorted_fields_type *sf = obj;
   resort_data.new_value = new_value;
   resort_data.cookie = cookie;
   qsort (&sf->elts[0], sf->len, sizeof (tree),
-         resort_field_decl_cmp);
-}
-
-/* Used by estimate_num_insns.  Estimate number of instructions seen
-   by given statement.  */
-static tree
-c_estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
-{
-  int *count = data;
-  tree x = *tp;
-
-  if (TYPE_P (x) || DECL_P (x))
-    {
-      *walk_subtrees = 0;
-      return NULL;
-    }
-  /* Assume that constants and references counts nothing.  These should
-     be majorized by amount of operations among them we count later
-     and are common target of CSE and similar optimizations.  */
-  if (TREE_CODE_CLASS (TREE_CODE (x)) == 'c'
-      || TREE_CODE_CLASS (TREE_CODE (x)) == 'r')
-    return NULL;
-  switch (TREE_CODE (x))
-    { 
-    /* Recognize assignments of large structures and constructors of
-       big arrays.  */
-    case MODIFY_EXPR:
-    case CONSTRUCTOR:
-      {
-       int size = int_size_in_bytes (TREE_TYPE (x));
-
-       if (!size || size > MOVE_MAX_PIECES)
-         *count += 10;
-       else
-         *count += 2 * (size + MOVE_MAX - 1) / MOVE_MAX;
-       return NULL;
-      }
-      break;
-    /* Few special cases of expensive operations.  This is usefull
-       to avoid inlining on functions having too many of these.  */
-    case TRUNC_DIV_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case TRUNC_MOD_EXPR:
-    case CEIL_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-    case ROUND_MOD_EXPR:
-    case RDIV_EXPR:
-    case CALL_EXPR:
-      *count += 10;
-      break;
-    /* Various containers that will produce no code themselves.  */
-    case INIT_EXPR:
-    case TARGET_EXPR:
-    case BIND_EXPR:
-    case BLOCK:
-    case TREE_LIST:
-    case TREE_VEC:
-    case IDENTIFIER_NODE:
-    case PLACEHOLDER_EXPR:
-    case WITH_CLEANUP_EXPR:
-    case CLEANUP_POINT_EXPR:
-    case NOP_EXPR:
-    case VIEW_CONVERT_EXPR:
-    case SAVE_EXPR:
-    case UNSAVE_EXPR:
-    case COMPLEX_EXPR:
-    case REALPART_EXPR:
-    case IMAGPART_EXPR:
-    case TRY_CATCH_EXPR:
-    case TRY_FINALLY_EXPR:
-    case LABEL_EXPR:
-    case EXIT_EXPR:
-    case LABELED_BLOCK_EXPR:
-    case EXIT_BLOCK_EXPR:
-    case EXPR_WITH_FILE_LOCATION:
-
-    case EXPR_STMT:
-    case COMPOUND_STMT:
-    case RETURN_STMT:
-    case LABEL_STMT:
-    case SCOPE_STMT:
-    case FILE_STMT:
-    case CASE_LABEL:
-    case STMT_EXPR:
-    case CLEANUP_STMT:
-
-    case SIZEOF_EXPR:
-    case ARROW_EXPR:
-    case ALIGNOF_EXPR:
-      break;
-    case DECL_STMT:
-      /* Do not account static initializers.  */
-      if (TREE_STATIC (TREE_OPERAND (x, 0)))
-       *walk_subtrees = 0;
-      break;
-    default:
-      (*count)++;
-    }
-  return NULL;
-}
-
-/*  Estimate number of instructions that will be created by expanding the body.  */
-int
-c_estimate_num_insns (tree decl)
-{
-  int num = 0;
-  walk_tree_without_duplicates (&DECL_SAVED_TREE (decl), c_estimate_num_insns_1, &num);
-  return num;
-}
-
-/* Used by c_decl_uninit to find where expressions like x = x + 1; */
-
-static tree
-c_decl_uninit_1 (tree *t, int *walk_sub_trees, void *x)
-{
-  /* If x = EXP(&x)EXP, then do not warn about the use of x.  */
-  if (TREE_CODE (*t) == ADDR_EXPR && TREE_OPERAND (*t, 0) == x)
-    {
-      *walk_sub_trees = 0;
-      return NULL_TREE;
-    }
-  if (*t == x)
-    return *t;
-  return NULL_TREE;
-}
-
-/* Find out if a variable is uninitialized based on DECL_INITIAL.  */
-
-bool
-c_decl_uninit (tree t)
-{
-  /* int x = x; is GCC extension to turn off this warning, only if warn_init_self is zero.  */
-  if (DECL_INITIAL (t) == t)
-    return warn_init_self ? true : false;
-
-  /* Walk the trees looking for the variable itself.  */
-  if (walk_tree_without_duplicates (&DECL_INITIAL (t), c_decl_uninit_1, t))
-    return true;
-  return false;
+        resort_field_decl_cmp);
 }
 
 /* Issue the error given by MSGID, indicating that it occurred before
@@ -5922,4 +5810,74 @@ c_parse_error (const char *msgid, enum cpp_ttype token, tree value)
     error ("%s", string);
 }
 
+/* Walk a gimplified function and warn for functions whose return value is
+   ignored and attribute((warn_unused_result)) is set.  This is done before
+   inlining, so we don't have to worry about that.  */  
+   
+void
+c_warn_unused_result (tree *top_p)
+{
+  tree t = *top_p;
+  tree_stmt_iterator i;
+  tree fdecl, ftype;
+
+  switch (TREE_CODE (t))
+    {
+    case STATEMENT_LIST:
+      for (i = tsi_start (*top_p); !tsi_end_p (i); tsi_next (&i))
+       c_warn_unused_result (tsi_stmt_ptr (i));
+      break;
+
+    case COND_EXPR:
+      c_warn_unused_result (&COND_EXPR_THEN (t));
+      c_warn_unused_result (&COND_EXPR_ELSE (t));
+      break;
+    case BIND_EXPR:
+      c_warn_unused_result (&BIND_EXPR_BODY (t));
+      break;
+    case TRY_FINALLY_EXPR:
+    case TRY_CATCH_EXPR:
+      c_warn_unused_result (&TREE_OPERAND (t, 0));
+      c_warn_unused_result (&TREE_OPERAND (t, 1));
+      break;
+    case CATCH_EXPR:
+      c_warn_unused_result (&CATCH_BODY (t));
+      break;
+    case EH_FILTER_EXPR:
+      c_warn_unused_result (&EH_FILTER_FAILURE (t));
+      break;
+
+    case CALL_EXPR:
+      /* This is a naked call, as opposed to a CALL_EXPR nested inside
+        a MODIFY_EXPR.  All calls whose value is ignored should be
+        represented like this.  Look for the attribute.  */
+      fdecl = get_callee_fndecl (t);
+      if (fdecl)
+       ftype = TREE_TYPE (fdecl);
+      else
+       {
+         ftype = TREE_TYPE (TREE_OPERAND (t, 0));
+         /* Look past pointer-to-function to the function type itself.  */
+         ftype = TREE_TYPE (ftype);
+       }
+
+      if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
+       {
+         if (fdecl)
+           warning ("%Hignoring return value of `%D', "
+                    "declared with attribute warn_unused_result",
+                    EXPR_LOCUS (t), fdecl);
+         else
+           warning ("%Hignoring return value of function "
+                    "declared with attribute warn_unused_result",
+                    EXPR_LOCUS (t));
+       }
+      break;
+
+    default:
+      /* Not a container, not a call, or a call whose value is used.  */
+      break;
+    }
+}
+
 #include "gt-c-common.h"