OSDN Git Service

../svn-commit.tmp
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index cde90a7..2534c25 100644 (file)
@@ -1,6 +1,7 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,8 +17,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 /* This file is part of the C front end.
@@ -74,13 +75,13 @@ static int missing_braces_mentioned;
 static int require_constant_value;
 static int require_constant_elements;
 
+static bool null_pointer_constant_p (tree);
 static tree qualify_type (tree, tree);
 static int tagged_types_tu_compatible_p (tree, tree);
-static int comp_target_types (tree, tree, int);
+static int comp_target_types (tree, tree);
 static int function_types_compatible_p (tree, tree);
 static int type_lists_compatible_p (tree, tree);
 static tree decl_constant_value_for_broken_optimization (tree);
-static tree default_function_array_conversion (tree);
 static tree lookup_field (tree, tree);
 static tree convert_arguments (tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
@@ -89,7 +90,6 @@ static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
-static void push_array_bounds (int);
 static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (const char *);
@@ -106,7 +106,38 @@ static void readonly_error (tree, enum lvalue_use);
 static int lvalue_or_else (tree, enum lvalue_use);
 static int lvalue_p (tree);
 static void record_maybe_used_decl (tree);
+static int comptypes_internal (tree, tree);
 \f
+/* Return true if EXP is a null pointer constant, false otherwise.  */
+
+static bool
+null_pointer_constant_p (tree expr)
+{
+  /* This should really operate on c_expr structures, but they aren't
+     yet available everywhere required.  */
+  tree type = TREE_TYPE (expr);
+  return (TREE_CODE (expr) == INTEGER_CST
+         && !TREE_CONSTANT_OVERFLOW (expr)
+         && integer_zerop (expr)
+         && (INTEGRAL_TYPE_P (type)
+             || (TREE_CODE (type) == POINTER_TYPE
+                 && VOID_TYPE_P (TREE_TYPE (type))
+                 && TYPE_QUALS (TREE_TYPE (type)) == TYPE_UNQUALIFIED)));
+}
+\f/* This is a cache to hold if two types are compatible or not.  */
+
+struct tagged_tu_seen_cache {
+  const struct tagged_tu_seen_cache * next;
+  tree t1;
+  tree t2;
+  /* The return value of tagged_types_tu_compatible_p if we had seen
+     these two types already.  */
+  int val;
+};
+
+static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
+static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *);
+
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
 
@@ -205,8 +236,8 @@ c_type_promotes_to (tree type)
     {
       /* Preserve unsignedness if not really getting any wider.  */
       if (TYPE_UNSIGNED (type)
-          && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
-        return unsigned_type_node;
+         && (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)))
+       return unsigned_type_node;
       return integer_type_node;
     }
 
@@ -222,6 +253,17 @@ qualify_type (tree type, tree like)
   return c_build_qualified_type (type,
                                 TYPE_QUALS (type) | TYPE_QUALS (like));
 }
+
+/* Return true iff the given tree T is a variable length array.  */
+
+bool
+c_vla_type_p (tree t)
+{
+  if (TREE_CODE (t) == ARRAY_TYPE
+      && C_TYPE_VARIABLE_SIZE (t))
+    return true;
+  return false;
+}
 \f
 /* Return the composite type of two compatible types.
 
@@ -282,21 +324,39 @@ composite_type (tree t1, tree t2)
        tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
        int quals;
        tree unqual_elt;
+       tree d1 = TYPE_DOMAIN (t1);
+       tree d2 = TYPE_DOMAIN (t2);
+       bool d1_variable, d2_variable;
+       bool d1_zero, d2_zero;
 
        /* We should not have any type quals on arrays at all.  */
        gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
-       
+
+       d1_zero = d1 == 0 || !TYPE_MAX_VALUE (d1);
+       d2_zero = d2 == 0 || !TYPE_MAX_VALUE (d2);
+
+       d1_variable = (!d1_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d1)) != INTEGER_CST));
+       d2_variable = (!d2_zero
+                      && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
+                          || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
+       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
+
        /* Save space: see if the result is identical to one of the args.  */
-       if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
+       if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
+           && (d2_variable || d2_zero || !d1_variable))
          return build_type_attribute_variant (t1, attributes);
-       if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
+       if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
+           && (d1_variable || d1_zero || !d2_variable))
          return build_type_attribute_variant (t2, attributes);
-       
+
        if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t1, attributes);
        if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
          return build_type_attribute_variant (t2, attributes);
-       
+
        /* Merge the element types, and have a size if either arg has
           one.  We may have qualifiers on the element types.  To set
           up TYPE_MAIN_VARIANT correctly, we need to form the
@@ -305,11 +365,29 @@ composite_type (tree t1, tree t2)
        quals = TYPE_QUALS (strip_array_types (elt));
        unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
        t1 = build_array_type (unqual_elt,
-                              TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+                              TYPE_DOMAIN ((TYPE_DOMAIN (t1)
+                                            && (d2_variable
+                                                || d2_zero
+                                                || !d1_variable))
+                                           ? t1
+                                           : t2));
        t1 = c_build_qualified_type (t1, quals);
        return build_type_attribute_variant (t1, attributes);
       }
 
+    case ENUMERAL_TYPE:
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (attributes != NULL)
+       {
+         /* Try harder not to create a new aggregate type.  */
+         if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+           return t1;
+         if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+           return t2;
+       }
+      return build_type_attribute_variant (t1, attributes);
+
     case FUNCTION_TYPE:
       /* Function types: prefer the one that specified arg types.
         If both do, merge the arg types.  Also merge the return types.  */
@@ -465,7 +543,7 @@ common_pointer_type (tree t1, tree t2)
     return t1;
 
   gcc_assert (TREE_CODE (t1) == POINTER_TYPE
-             && TREE_CODE (t2) == POINTER_TYPE);
+             && TREE_CODE (t2) == POINTER_TYPE);
 
   /* Merge the attributes.  */
   attributes = targetm.merge_type_attributes (t1, t2);
@@ -531,6 +609,29 @@ c_common_type (tree t1, tree t2)
   gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
              || code2 == REAL_TYPE || code2 == INTEGER_TYPE);
 
+  /* When one operand is a decimal float type, the other operand cannot be
+     a generic float type or a complex type.  We also disallow vector types
+     here.  */
+  if ((DECIMAL_FLOAT_TYPE_P (t1) || DECIMAL_FLOAT_TYPE_P (t2))
+      && !(DECIMAL_FLOAT_TYPE_P (t1) && DECIMAL_FLOAT_TYPE_P (t2)))
+    {
+      if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and vector types");
+         return error_mark_node;
+       }
+      if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and complex types");
+         return error_mark_node;
+       }
+      if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+       {
+         error ("can%'t mix operands of decimal float and other float types");
+         return error_mark_node;
+       }
+    }
+
   /* If one type is a vector type, return that type.  (How the usual
      arithmetic conversions apply to the vector types extension is not
      precisely specified.)  */
@@ -565,6 +666,22 @@ c_common_type (tree t1, tree t2)
   if (code2 == REAL_TYPE && code1 != REAL_TYPE)
     return t2;
 
+  /* If both are real and either are decimal floating point types, use
+     the decimal floating point type with the greater precision. */
+
+  if (code1 == REAL_TYPE && code2 == REAL_TYPE)
+    {
+      if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node
+         || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node)
+       return dfloat128_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node)
+       return dfloat64_type_node;
+      else if (TYPE_MAIN_VARIANT (t1) == dfloat32_type_node
+              || TYPE_MAIN_VARIANT (t2) == dfloat32_type_node)
+       return dfloat32_type_node;
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
 
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
@@ -586,7 +703,7 @@ c_common_type (tree t1, tree t2)
       if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
        return long_long_unsigned_type_node;
       else
-        return long_long_integer_type_node;
+       return long_long_integer_type_node;
     }
 
   if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
@@ -617,8 +734,11 @@ c_common_type (tree t1, tree t2)
     return t2;
 }
 \f
-/* Wrapper around c_common_type that is used by c-common.c.  ENUMERAL_TYPEs
-   are allowed here and are converted to their compatible integer types.  */
+/* Wrapper around c_common_type that is used by c-common.c and other
+   front end optimizations that remove promotions.  ENUMERAL_TYPEs
+   are allowed here and are converted to their compatible integer types.
+   BOOLEAN_TYPEs are allowed here and return either boolean_type_node or
+   preferably a non-Boolean type as the common type.  */
 tree
 common_type (tree t1, tree t2)
 {
@@ -626,9 +746,21 @@ common_type (tree t1, tree t2)
     t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
   if (TREE_CODE (t2) == ENUMERAL_TYPE)
     t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
+
+  /* If both types are BOOLEAN_TYPE, then return boolean_type_node.  */
+  if (TREE_CODE (t1) == BOOLEAN_TYPE
+      && TREE_CODE (t2) == BOOLEAN_TYPE)
+    return boolean_type_node;
+
+  /* If either type is BOOLEAN_TYPE, then return the other.  */
+  if (TREE_CODE (t1) == BOOLEAN_TYPE)
+    return t2;
+  if (TREE_CODE (t2) == BOOLEAN_TYPE)
+    return t1;
+
   return c_common_type (t1, t2);
 }
-\f
+
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  */
@@ -636,6 +768,23 @@ common_type (tree t1, tree t2)
 int
 comptypes (tree type1, tree type2)
 {
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+\f
+/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
+   or various other operations.  Return 2 if they are compatible
+   but a warning may be needed if you use them together.  This
+   differs from comptypes, in that we don't free the seen types.  */
+
+static int
+comptypes_internal (tree type1, tree type2)
+{
   tree t1 = type1;
   tree t2 = type2;
   int attrval, val;
@@ -697,16 +846,12 @@ comptypes (tree type1, tree type2)
   switch (TREE_CODE (t1))
     {
     case POINTER_TYPE:
-      /* We must give ObjC the first crack at comparing pointers, since
-          protocol qualifiers may be involved.  */
-      if (c_dialect_objc () && (val = objc_comptypes (t1, t2, 0)) >= 0)
-       break;
       /* Do not remove mode or aliasing information.  */
       if (TYPE_MODE (t1) != TYPE_MODE (t2)
          || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-            ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
+            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)));
       break;
 
     case FUNCTION_TYPE:
@@ -723,7 +868,7 @@ comptypes (tree type1, tree type2)
 
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
-           && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
+           && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))))
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
@@ -739,6 +884,8 @@ comptypes (tree type1, tree type2)
        d2_variable = (!d2_zero
                       && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
                           || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
+       d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
+       d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
        if (d1_variable || d2_variable)
          break;
@@ -749,24 +896,30 @@ comptypes (tree type1, tree type2)
            || !tree_int_cst_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)))
          val = 0;
 
-        break;
+       break;
       }
 
-    case RECORD_TYPE:
-      /* We are dealing with two distinct structs.  In assorted Objective-C
-        corner cases, however, these can still be deemed equivalent.  */
-      if (c_dialect_objc () && objc_comptypes (t1, t2, 0) == 1)
-       val = 1;
-
     case ENUMERAL_TYPE:
+    case RECORD_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
-       val = tagged_types_tu_compatible_p (t1, t2);
+       {
+         tree a1 = TYPE_ATTRIBUTES (t1);
+         tree a2 = TYPE_ATTRIBUTES (t2);
+
+         if (! attribute_list_contained (a1, a2)
+             && ! attribute_list_contained (a2, a1))
+           break;
+
+         if (attrval != 2)
+           return tagged_types_tu_compatible_p (t1, t2);
+         val = tagged_types_tu_compatible_p (t1, t2);
+       }
       break;
 
     case VECTOR_TYPE:
       val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
-           && comptypes (TREE_TYPE (t1), TREE_TYPE (t2));
+           && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2));
       break;
 
     default:
@@ -776,22 +929,14 @@ comptypes (tree type1, tree type2)
 }
 
 /* Return 1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers.  REFLEXIVE is only used by ObjC - set it
-   to 1 or 0 depending if the check of the pointer types is meant to
-   be reflexive or not (typically, assignments are not reflexive,
-   while comparisons are reflexive).
-*/
+   ignoring their qualifiers.  */
 
 static int
-comp_target_types (tree ttl, tree ttr, int reflexive)
+comp_target_types (tree ttl, tree ttr)
 {
   int val;
   tree mvl, mvr;
 
-  /* Give objc_comptypes a crack at letting these types through.  */
-  if ((val = objc_comptypes (ttl, ttr, reflexive)) >= 0)
-    return val;
-
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
   mvl = TREE_TYPE (ttl);
@@ -843,21 +988,48 @@ same_translation_unit_p (tree t1, tree t2)
   return t1 == t2;
 }
 
-/* The C standard says that two structures in different translation
-   units are compatible with each other only if the types of their
-   fields are compatible (among other things).  So, consider two copies
-   of this structure:  */
+/* Allocate the seen two types, assuming that they are compatible. */
 
-struct tagged_tu_seen {
-  const struct tagged_tu_seen * next;
-  tree t1;
-  tree t2;
-};
+static struct tagged_tu_seen_cache *
+alloc_tagged_tu_seen_cache (tree t1, tree t2)
+{
+  struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
+  tu->next = tagged_tu_seen_base;
+  tu->t1 = t1;
+  tu->t2 = t2;
+
+  tagged_tu_seen_base = tu;
+
+  /* The C standard says that two structures in different translation
+     units are compatible with each other only if the types of their
+     fields are compatible (among other things).  We assume that they
+     are compatible until proven otherwise when building the cache.
+     An example where this can occur is:
+     struct a
+     {
+       struct a *next;
+     };
+     If we are comparing this against a similar struct in another TU,
+     and did not assume they were compatible, we end up with an infinite
+     loop.  */
+  tu->val = 1;
+  return tu;
+}
 
-/* Can they be compatible with each other?  We choose to break the
-   recursion by allowing those types to be compatible.  */
+/* Free the seen types until we get to TU_TIL. */
 
-static const struct tagged_tu_seen * tagged_tu_seen_base;
+static void
+free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
+{
+  const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
+  while (tu != tu_til)
+    {
+      struct tagged_tu_seen_cache *tu1 = (struct tagged_tu_seen_cache*)tu;
+      tu = tu1->next;
+      free (tu1);
+    }
+  tagged_tu_seen_base = tu_til;
+}
 
 /* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
    compatible.  If the two types are not the same (which has been
@@ -899,73 +1071,123 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
     return 1;
 
   {
-    const struct tagged_tu_seen * tts_i;
+    const struct tagged_tu_seen_cache * tts_i;
     for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
       if (tts_i->t1 == t1 && tts_i->t2 == t2)
-       return 1;
+       return tts_i->val;
   }
 
   switch (TREE_CODE (t1))
     {
     case ENUMERAL_TYPE:
       {
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
+       /* Speed up the case where the type values are in the same order.  */
+       tree tv1 = TYPE_VALUES (t1);
+       tree tv2 = TYPE_VALUES (t2);
 
-        /* Speed up the case where the type values are in the same order.  */
-        tree tv1 = TYPE_VALUES (t1);
-        tree tv2 = TYPE_VALUES (t2);
-
-        if (tv1 == tv2)
-          return 1;
+       if (tv1 == tv2)
+         {
+           return 1;
+         }
 
-        for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
-          {
-            if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
-              break;
-            if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
-              return 0;
-          }
+       for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
+         {
+           if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
+             break;
+           if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
 
-        if (tv1 == NULL_TREE && tv2 == NULL_TREE)
-          return 1;
-        if (tv1 == NULL_TREE || tv2 == NULL_TREE)
-          return 0;
+       if (tv1 == NULL_TREE && tv2 == NULL_TREE)
+         {
+           return 1;
+         }
+       if (tv1 == NULL_TREE || tv2 == NULL_TREE)
+         {
+           tu->val = 0;
+           return 0;
+         }
 
        if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
-         return 0;
+         {
+           tu->val = 0;
+           return 0;
+         }
 
        for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
          {
            s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
            if (s2 == NULL
                || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
-             return 0;
+             {
+               tu->val = 0;
+               return 0;
+             }
          }
        return 1;
       }
 
     case UNION_TYPE:
       {
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
        if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
-         return 0;
+         {
+           tu->val = 0;
+           return 0;
+         }
+
+       /*  Speed up the common case where the fields are in the same order. */
+       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
+            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+         {
+           int result;
+
+
+           if (DECL_NAME (s1) == NULL
+               || DECL_NAME (s1) != DECL_NAME (s2))
+             break;
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+           if (result == 0)
+             {
+               tu->val = 0;
+               return 0;
+             }
+           if (result == 2)
+             needs_warning = true;
+
+           if (TREE_CODE (s1) == FIELD_DECL
+               && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                    DECL_FIELD_BIT_OFFSET (s2)) != 1)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
+       if (!s1 && !s2)
+         {
+           tu->val = needs_warning ? 2 : 1;
+           return tu->val;
+         }
 
        for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
          {
            bool ok = false;
-           struct tagged_tu_seen tts;
-
-           tts.next = tagged_tu_seen_base;
-           tts.t1 = t1;
-           tts.t2 = t2;
-           tagged_tu_seen_base = &tts;
 
            if (DECL_NAME (s1) != NULL)
              for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
                if (DECL_NAME (s1) == DECL_NAME (s2))
                  {
                    int result;
-                   result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
+                   result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
                    if (result == 0)
-                     break;
+                     {
+                       tu->val = 0;
+                       return 0;
+                     }
                    if (result == 2)
                      needs_warning = true;
 
@@ -977,21 +1199,19 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
                    ok = true;
                    break;
                  }
-           tagged_tu_seen_base = tts.next;
            if (!ok)
-             return 0;
+             {
+               tu->val = 0;
+               return 0;
+             }
          }
-       return needs_warning ? 2 : 1;
+       tu->val = needs_warning ? 2 : 10;
+       return tu->val;
       }
 
     case RECORD_TYPE:
       {
-       struct tagged_tu_seen tts;
-
-       tts.next = tagged_tu_seen_base;
-       tts.t1 = t1;
-       tts.t2 = t2;
-       tagged_tu_seen_base = &tts;
+       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
@@ -1001,7 +1221,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
            if (result == 0)
              break;
            if (result == 2)
@@ -1012,10 +1232,11 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
                                     DECL_FIELD_BIT_OFFSET (s2)) != 1)
              break;
          }
-       tagged_tu_seen_base = tts.next;
        if (s1 && s2)
-         return 0;
-       return needs_warning ? 2 : 1;
+         tu->val = 0;
+       else
+         tu->val = needs_warning ? 2 : 1;
+       return tu->val;
       }
 
     default:
@@ -1052,7 +1273,7 @@ function_types_compatible_p (tree f1, tree f2)
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes (ret1, ret2);
+  val = comptypes_internal (ret1, ret2);
   if (val == 0)
     return 0;
 
@@ -1068,7 +1289,7 @@ function_types_compatible_p (tree f1, tree f2)
        return 0;
       /* If one of these types comes from a non-prototype fn definition,
         compare that with the other type's arglist.
-        If they don't match, ask for a warning (0, but no error).  */
+        If they don't match, ask for a warning (but no error).  */
       if (TYPE_ACTUAL_ARG_TYPES (f1)
          && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1)))
        val = 2;
@@ -1133,7 +1354,7 @@ type_lists_compatible_p (tree args1, tree args2)
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
-      else if (!(newval = comptypes (mv1, mv2)))
+      else if (!(newval = comptypes_internal (mv1, mv2)))
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
@@ -1152,7 +1373,7 @@ type_lists_compatible_p (tree args1, tree args2)
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes (mv3, mv2))
+                 if (comptypes_internal (mv3, mv2))
                    break;
                }
              if (memb == 0)
@@ -1173,7 +1394,7 @@ type_lists_compatible_p (tree args1, tree args2)
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes (mv3, mv1))
+                 if (comptypes_internal (mv3, mv1))
                    break;
                }
              if (memb == 0)
@@ -1249,109 +1470,131 @@ decl_constant_value (tree decl)
 static tree
 decl_constant_value_for_broken_optimization (tree decl)
 {
+  tree ret;
+
   if (pedantic || DECL_MODE (decl) == BLKmode)
     return decl;
-  else
-    return decl_constant_value (decl);
-}
 
+  ret = decl_constant_value (decl);
+  /* Avoid unwanted tree sharing between the initializer and current
+     function's body where the tree can be modified e.g. by the
+     gimplifier.  */
+  if (ret != decl && TREE_STATIC (decl))
+    ret = unshare_expr (ret);
+  return ret;
+}
 
-/* Perform the default conversion of arrays and functions to pointers.
-   Return the result of converting EXP.  For any other expression, just
-   return EXP.  */
-
+/* Convert the array expression EXP to a pointer.  */
 static tree
-default_function_array_conversion (tree exp)
+array_to_pointer_conversion (tree exp)
 {
-  tree orig_exp;
+  tree orig_exp = exp;
   tree type = TREE_TYPE (exp);
-  enum tree_code code = TREE_CODE (type);
-  int not_lvalue = 0;
+  tree adr;
+  tree restype = TREE_TYPE (type);
+  tree ptrtype;
 
-  /* Strip NON_LVALUE_EXPRs and no-op conversions, since we aren't using as
-     an lvalue.
+  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
 
-     Do not use STRIP_NOPS here!  It will remove conversions from pointer
-     to integer and cause infinite recursion.  */
-  orig_exp = exp;
-  while (TREE_CODE (exp) == NON_LVALUE_EXPR
-        || (TREE_CODE (exp) == NOP_EXPR
-            && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
-    {
-      if (TREE_CODE (exp) == NON_LVALUE_EXPR)
-       not_lvalue = 1;
-      exp = TREE_OPERAND (exp, 0);
-    }
+  STRIP_TYPE_NOPS (exp);
 
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  if (code == FUNCTION_TYPE)
+  ptrtype = build_pointer_type (restype);
+
+  if (TREE_CODE (exp) == INDIRECT_REF)
+    return convert (ptrtype, TREE_OPERAND (exp, 0));
+
+  if (TREE_CODE (exp) == VAR_DECL)
     {
-      return build_unary_op (ADDR_EXPR, exp, 0);
+      /* We are making an ADDR_EXPR of ptrtype.  This is a valid
+        ADDR_EXPR because it's the best way of representing what
+        happens in C when we take the address of an array and place
+        it in a pointer to the element type.  */
+      adr = build1 (ADDR_EXPR, ptrtype, exp);
+      if (!c_mark_addressable (exp))
+       return error_mark_node;
+      TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
+      return adr;
     }
-  if (code == ARRAY_TYPE)
-    {
-      tree adr;
-      tree restype = TREE_TYPE (type);
-      tree ptrtype;
-      int constp = 0;
-      int volatilep = 0;
-      int lvalue_array_p;
 
-      if (REFERENCE_CLASS_P (exp) || DECL_P (exp))
-       {
-         constp = TREE_READONLY (exp);
-         volatilep = TREE_THIS_VOLATILE (exp);
-       }
+  /* This way is better for a COMPONENT_REF since it can
+     simplify the offset for a component.  */
+  adr = build_unary_op (ADDR_EXPR, exp, 1);
+  return convert (ptrtype, adr);
+}
 
-      if (TYPE_QUALS (type) || constp || volatilep)
-       restype
-         = c_build_qualified_type (restype,
-                                   TYPE_QUALS (type)
-                                   | (constp * TYPE_QUAL_CONST)
-                                   | (volatilep * TYPE_QUAL_VOLATILE));
+/* Convert the function expression EXP to a pointer.  */
+static tree
+function_to_pointer_conversion (tree exp)
+{
+  tree orig_exp = exp;
 
-      if (TREE_CODE (exp) == INDIRECT_REF)
-       return convert (build_pointer_type (restype),
-                       TREE_OPERAND (exp, 0));
+  gcc_assert (TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE);
 
-      if (TREE_CODE (exp) == COMPOUND_EXPR)
-       {
-         tree op1 = default_conversion (TREE_OPERAND (exp, 1));
-         return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
-                        TREE_OPERAND (exp, 0), op1);
-       }
+  STRIP_TYPE_NOPS (exp);
 
-      lvalue_array_p = !not_lvalue && lvalue_p (exp);
-      if (!flag_isoc99 && !lvalue_array_p)
-       {
-         /* Before C99, non-lvalue arrays do not decay to pointers.
-            Normally, using such an array would be invalid; but it can
-            be used correctly inside sizeof or as a statement expression.
-            Thus, do not give an error here; an error will result later.  */
-         return exp;
-       }
+  if (TREE_NO_WARNING (orig_exp))
+    TREE_NO_WARNING (exp) = 1;
 
-      ptrtype = build_pointer_type (restype);
+  return build_unary_op (ADDR_EXPR, exp, 0);
+}
 
-      if (TREE_CODE (exp) == VAR_DECL)
-       {
-         /* We are making an ADDR_EXPR of ptrtype.  This is a valid
-            ADDR_EXPR because it's the best way of representing what
-            happens in C when we take the address of an array and place
-            it in a pointer to the element type.  */
-         adr = build1 (ADDR_EXPR, ptrtype, exp);
-         if (!c_mark_addressable (exp))
-           return error_mark_node;
-         TREE_SIDE_EFFECTS (adr) = 0;   /* Default would be, same as EXP.  */
-         return adr;
-       }
-      /* This way is better for a COMPONENT_REF since it can
-        simplify the offset for a component.  */
-      adr = build_unary_op (ADDR_EXPR, exp, 1);
-      return convert (ptrtype, adr);
+/* Perform the default conversion of arrays and functions to pointers.
+   Return the result of converting EXP.  For any other expression, just
+   return EXP after removing NOPs.  */
+
+struct c_expr
+default_function_array_conversion (struct c_expr exp)
+{
+  tree orig_exp = exp.value;
+  tree type = TREE_TYPE (exp.value);
+  enum tree_code code = TREE_CODE (type);
+
+  switch (code)
+    {
+    case ARRAY_TYPE:
+      {
+       bool not_lvalue = false;
+       bool lvalue_array_p;
+
+       while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
+               || TREE_CODE (exp.value) == NOP_EXPR
+               || TREE_CODE (exp.value) == CONVERT_EXPR)
+              && TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
+         {
+           if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
+             not_lvalue = true;
+           exp.value = TREE_OPERAND (exp.value, 0);
+         }
+
+       if (TREE_NO_WARNING (orig_exp))
+         TREE_NO_WARNING (exp.value) = 1;
+
+       lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
+       if (!flag_isoc99 && !lvalue_array_p)
+         {
+           /* Before C99, non-lvalue arrays do not decay to pointers.
+              Normally, using such an array would be invalid; but it can
+              be used correctly inside sizeof or as a statement expression.
+              Thus, do not give an error here; an error will result later.  */
+           return exp;
+         }
+
+       exp.value = array_to_pointer_conversion (exp.value);
+      }
+      break;
+    case FUNCTION_TYPE:
+      exp.value = function_to_pointer_conversion (exp.value);
+      break;
+    default:
+      STRIP_TYPE_NOPS (exp.value);
+      if (TREE_NO_WARNING (orig_exp))
+       TREE_NO_WARNING (exp.value) = 1;
+      break;
     }
+
   return exp;
 }
 
@@ -1405,8 +1648,7 @@ perform_integral_promotions (tree exp)
 
 
 /* Perform default promotions for C data used in expressions.
-   Arrays and functions are converted to pointers;
-   enumeral types or short or char, to int.
+   Enumeral types or short or char are converted to int.
    In addition, manifest constants symbols are replaced by their values.  */
 
 tree
@@ -1416,8 +1658,10 @@ default_conversion (tree exp)
   tree type = TREE_TYPE (exp);
   enum tree_code code = TREE_CODE (type);
 
-  if (code == FUNCTION_TYPE || code == ARRAY_TYPE)
-    return default_function_array_conversion (exp);
+  /* Functions and arrays have been converted during parsing.  */
+  gcc_assert (code != FUNCTION_TYPE);
+  if (code == ARRAY_TYPE)
+    return exp;
 
   /* Constants can be used directly unless they're not loadable.  */
   if (TREE_CODE (exp) == CONST_DECL)
@@ -1585,11 +1829,17 @@ build_component_ref (tree datum, tree component)
       do
        {
          tree subdatum = TREE_VALUE (field);
+         int quals;
+         tree subtype;
 
          if (TREE_TYPE (subdatum) == error_mark_node)
            return error_mark_node;
 
-         ref = build3 (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum,
+         quals = TYPE_QUALS (strip_array_types (TREE_TYPE (subdatum)));
+         quals |= TYPE_QUALS (TREE_TYPE (datum));
+         subtype = c_build_qualified_type (TREE_TYPE (subdatum), quals);
+
+         ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
                        NULL_TREE);
          if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
            TREE_READONLY (ref) = 1;
@@ -1633,12 +1883,9 @@ build_indirect_ref (tree ptr, const char *errorstring)
       else
        {
          tree t = TREE_TYPE (type);
-         tree mvt = t;
          tree ref;
 
-         if (TREE_CODE (mvt) != ARRAY_TYPE)
-           mvt = TYPE_MAIN_VARIANT (mvt);
-         ref = build1 (INDIRECT_REF, mvt, pointer);
+         ref = build1 (INDIRECT_REF, t, pointer);
 
          if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
            {
@@ -1712,16 +1959,10 @@ build_array_ref (tree array, tree index)
       return error_mark_node;
     }
 
-  /* Subscripting with type char is likely to lose on a machine where
-     chars are signed.  So warn on any machine, but optionally.  Don't
-     warn for unsigned char since that type is safe.  Don't warn for
-     signed char because anyone who uses that must have done so
-     deliberately.  ??? Existing practice has also been to warn only
-     when the char index is syntactically the index, not for
-     char[array].  */
-  if (warn_char_subscripts && !swapped
-      && TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
-    warning (0, "array subscript has type %<char%>");
+  /* ??? Existing practice has been to warn only when the char
+     index is syntactically the index, not for char[array].  */
+  if (!swapped)
+     warn_array_subscript_with_type_char (index);
 
   /* Apply default promotions *after* noticing character types.  */
   index = default_conversion (index);
@@ -1771,7 +2012,7 @@ build_array_ref (tree array, tree index)
        type = TYPE_MAIN_VARIANT (type);
       rval = build4 (ARRAY_REF, type, array, index, NULL_TREE, NULL_TREE);
       /* Array ref is const/volatile if the array elements are
-         or if the array is.  */
+        or if the array is.  */
       TREE_READONLY (rval)
        |= (TYPE_READONLY (TREE_TYPE (TREE_TYPE (array)))
            | TREE_READONLY (array));
@@ -1852,6 +2093,7 @@ build_external_ref (tree id, int fun, location_t loc)
 
   if (TREE_CODE (ref) == CONST_DECL)
     {
+      used_types_insert (TREE_TYPE (ref));
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
       TREE_INVARIANT (ref) = 1;
@@ -1940,6 +2182,11 @@ c_expr_sizeof_expr (struct c_expr expr)
     {
       ret.value = c_sizeof (TREE_TYPE (expr.value));
       ret.original_code = ERROR_MARK;
+      if (c_vla_type_p (TREE_TYPE (expr.value)))
+       {
+         /* sizeof is evaluated when given a vla (C99 6.5.3.4p2).  */
+         ret.value = build2 (COMPOUND_EXPR, TREE_TYPE (ret.value), expr.value, ret.value);
+       }
       pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (expr.value)));
     }
   return ret;
@@ -1956,7 +2203,8 @@ c_expr_sizeof_type (struct c_type_name *t)
   type = groktypename (t);
   ret.value = c_sizeof (type);
   ret.original_code = ERROR_MARK;
-  pop_maybe_used (C_TYPE_VARIABLE_SIZE (type));
+  pop_maybe_used (type != error_mark_node
+                 ? C_TYPE_VARIABLE_SIZE (type) : false);
   return ret;
 }
 
@@ -1979,26 +2227,23 @@ build_function_call (tree function, tree params)
   /* Convert anything with function type to a pointer-to-function.  */
   if (TREE_CODE (function) == FUNCTION_DECL)
     {
-      if (DECL_BUILT_IN_CLASS (function) == BUILT_IN_NORMAL)
-       {
-         tem = resolve_overloaded_builtin (function, params);
-         if (tem)
-           return tem;
-       }
+      /* Implement type-directed function overloading for builtins.
+        resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
+        handle all the type checking.  The result is a complete expression
+        that implements this function call.  */
+      tem = resolve_overloaded_builtin (function, params);
+      if (tem)
+       return tem;
 
       name = DECL_NAME (function);
-
-      /* Differs from default_conversion by not setting TREE_ADDRESSABLE
-        (because calling an inline function does not mean the function
-        needs to be separately compiled).  */
-      fntype = build_type_variant (TREE_TYPE (function),
-                                  TREE_READONLY (function),
-                                  TREE_THIS_VOLATILE (function));
       fundecl = function;
-      function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
     }
-  else
-    function = default_conversion (function);
+  if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
+    function = function_to_pointer_conversion (function);
+
+  /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
+     expressions, like those used for ObjC messenger dispatches.  */
+  function = objc_rewrite_function_call (function, params);
 
   fntype = TREE_TYPE (function);
 
@@ -2022,13 +2267,9 @@ build_function_call (tree function, tree params)
      If it is not, replace the call by a trap, wrapped up in a compound
      expression if necessary.  This has the nice side-effect to prevent
      the tree-inliner from generating invalid assignment trees which may
-     blow up in the RTL expander later.
-
-     ??? This doesn't work for Objective-C because objc_comptypes
-     refuses to compare function prototypes, yet the compiler appears
-     to build calls that are flagged as invalid by C's comptypes.  */
-  if (!c_dialect_objc ()
-      && TREE_CODE (function) == NOP_EXPR
+     blow up in the RTL expander later.  */
+  if ((TREE_CODE (function) == NOP_EXPR
+       || TREE_CODE (function) == CONVERT_EXPR)
       && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
       && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
       && !comptypes (fntype, TREE_TYPE (tem)))
@@ -2054,10 +2295,9 @@ build_function_call (tree function, tree params)
 
          if (AGGREGATE_TYPE_P (return_type))
            rhs = build_compound_literal (return_type,
-                                         build_constructor (return_type,
-                                                            NULL_TREE));
+                                         build_constructor (return_type, 0));
          else
-           rhs = fold (build1 (NOP_EXPR, return_type, integer_zero_node));
+           rhs = fold_convert (return_type, integer_zero_node);
 
          return build2 (COMPOUND_EXPR, return_type, trap, rhs);
        }
@@ -2074,15 +2314,13 @@ build_function_call (tree function, tree params)
 
   /* Check that the arguments to the function are valid.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params);
-
-  result = build3 (CALL_EXPR, TREE_TYPE (fntype),
-                  function, coerced_params, NULL_TREE);
-  TREE_SIDE_EFFECTS (result) = 1;
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+                           TYPE_ARG_TYPES (fntype));
 
   if (require_constant_value)
     {
-      result = fold_initializer (result);
+      result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype),
+                                       function, coerced_params, NULL_TREE);
 
       if (TREE_CONSTANT (result)
          && (name == NULL_TREE
@@ -2090,7 +2328,8 @@ build_function_call (tree function, tree params)
        pedwarn_init ("initializer element is not constant");
     }
   else
-    result = fold (result);
+    result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype),
+                         function, coerced_params, NULL_TREE);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     return result;
@@ -2161,8 +2400,6 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
 
       STRIP_TYPE_NOPS (val);
 
-      val = default_function_array_conversion (val);
-
       val = require_complete_type (val);
 
       if (type != 0)
@@ -2221,10 +2458,37 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                    {
                      /* Warn if any argument is passed as `float',
                         since without a prototype it would be `double'.  */
-                     if (formal_prec == TYPE_PRECISION (float_type_node))
+                     if (formal_prec == TYPE_PRECISION (float_type_node)
+                         && type != dfloat32_type_node)
                        warning (0, "passing argument %d of %qE as %<float%> "
                                 "rather than %<double%> due to prototype",
                                 argnum, rname);
+
+                     /* Warn if mismatch between argument and prototype
+                        for decimal float types.  Warn of conversions with
+                        binary float types and of precision narrowing due to
+                        prototype. */
+                     else if (type != TREE_TYPE (val)
+                              && (type == dfloat32_type_node
+                                  || type == dfloat64_type_node
+                                  || type == dfloat128_type_node
+                                  || TREE_TYPE (val) == dfloat32_type_node
+                                  || TREE_TYPE (val) == dfloat64_type_node
+                                  || TREE_TYPE (val) == dfloat128_type_node)
+                              && (formal_prec
+                                  <= TYPE_PRECISION (TREE_TYPE (val))
+                                  || (type == dfloat128_type_node
+                                      && (TREE_TYPE (val)
+                                          != dfloat64_type_node
+                                          && (TREE_TYPE (val)
+                                              != dfloat32_type_node)))
+                                  || (type == dfloat64_type_node
+                                      && (TREE_TYPE (val)
+                                          != dfloat32_type_node))))
+                       warning (0, "passing argument %d of %qE as %qT "
+                                "rather than %qT due to prototype",
+                                argnum, rname, type, TREE_TYPE (val));
+
                    }
                  /* Detect integer changing in width or signedness.
                     These warnings are only activated with
@@ -2242,8 +2506,9 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
-                       warning (0, "passing argument %d of %qE with different "
-                                "width due to prototype", argnum, rname);
+                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                                "with different width due to prototype",
+                                argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
                        ;
                      /* Don't complain if the formal parameter type
@@ -2264,11 +2529,12 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                               && TYPE_UNSIGNED (TREE_TYPE (val)))
                        ;
                      else if (TYPE_UNSIGNED (type))
-                       warning (0, "passing argument %d of %qE as unsigned "
-                                "due to prototype", argnum, rname);
+                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                                "as unsigned due to prototype",
+                                argnum, rname);
                      else
-                       warning (0, "passing argument %d of %qE as signed "
-                                "due to prototype", argnum, rname);
+                       warning (OPT_Wconversion, "passing argument %d of %qE "
+                                "as signed due to prototype", argnum, rname);
                    }
                }
 
@@ -2284,15 +2550,16 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
          result = tree_cons (NULL_TREE, parmval, result);
        }
       else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
-               && (TYPE_PRECISION (TREE_TYPE (val))
-                  < TYPE_PRECISION (double_type_node)))
+              && (TYPE_PRECISION (TREE_TYPE (val))
+                  < TYPE_PRECISION (double_type_node))
+              && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
        /* Convert `float' to `double'.  */
        result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
-      else if ((invalid_func_diag = 
-               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
+      else if ((invalid_func_diag =
+               targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
        {
          error (invalid_func_diag);
-         return error_mark_node; 
+         return error_mark_node;
        }
       else
        /* Convert `short' and `char' to full-size `int'.  */
@@ -2311,11 +2578,27 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
   return nreverse (result);
 }
 \f
-/* This is the entry point used by the parser
-   for binary operators in the input.
-   In addition to constructing the expression,
-   we check for operands that were written with other binary operators
-   in a way that is likely to confuse the user.  */
+/* This is the entry point used by the parser to build unary operators
+   in the input.  CODE, a tree_code, specifies the unary operator, and
+   ARG is the operand.  For unary plus, the C parser currently uses
+   CONVERT_EXPR for code.  */
+
+struct c_expr
+parser_build_unary_op (enum tree_code code, struct c_expr arg)
+{
+  struct c_expr result;
+
+  result.original_code = ERROR_MARK;
+  result.value = build_unary_op (code, arg.value, 0);
+  overflow_warning (result.value);
+  return result;
+}
+
+/* This is the entry point used by the parser to build binary operators
+   in the input.  CODE, a tree_code, specifies the binary operator, and
+   ARG1 and ARG2 are the operands.  In addition to constructing the
+   expression, we check for operands that were written with other binary
+   operators in a way that is likely to confuse the user.  */
 
 struct c_expr
 parser_build_binary_op (enum tree_code code, struct c_expr arg1,
@@ -2340,14 +2623,16 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
        {
          if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (0, "suggest parentheses around + or - inside shift");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around + or - inside shift");
        }
 
       if (code == TRUTH_ORIF_EXPR)
        {
          if (code1 == TRUTH_ANDIF_EXPR
              || code2 == TRUTH_ANDIF_EXPR)
-           warning (0, "suggest parentheses around && within ||");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around && within ||");
        }
 
       if (code == BIT_IOR_EXPR)
@@ -2356,11 +2641,13 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (0, "suggest parentheses around arithmetic in operand of |");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around arithmetic in operand of |");
          /* Check cases like x|y==z */
          if (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning (0, "suggest parentheses around comparison in operand of |");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around comparison in operand of |");
        }
 
       if (code == BIT_XOR_EXPR)
@@ -2369,33 +2656,50 @@ parser_build_binary_op (enum tree_code code, struct c_expr arg1,
              || code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == BIT_AND_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (0, "suggest parentheses around arithmetic in operand of ^");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around arithmetic in operand of ^");
          /* Check cases like x^y==z */
          if (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning (0, "suggest parentheses around comparison in operand of ^");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around comparison in operand of ^");
        }
 
       if (code == BIT_AND_EXPR)
        {
          if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
              || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
-           warning (0, "suggest parentheses around + or - in operand of &");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around + or - in operand of &");
          /* Check cases like x&y==z */
          if (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison)
-           warning (0, "suggest parentheses around comparison in operand of &");
+           warning (OPT_Wparentheses,
+                    "suggest parentheses around comparison in operand of &");
        }
       /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
       if (TREE_CODE_CLASS (code) == tcc_comparison
          && (TREE_CODE_CLASS (code1) == tcc_comparison
              || TREE_CODE_CLASS (code2) == tcc_comparison))
-       warning (0, "comparisons like X<=Y<=Z do not have their mathematical meaning");
+       warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
+                "have their mathematical meaning");
 
     }
 
-  unsigned_conversion_warning (result.value, arg1.value);
-  unsigned_conversion_warning (result.value, arg2.value);
+  /* Warn about comparisons against string literals, with the exception
+     of testing for equality or inequality of a string literal with NULL.  */
+  if (code == EQ_EXPR || code == NE_EXPR)
+    {
+      if ((code1 == STRING_CST && !integer_zerop (arg2.value))
+         || (code2 == STRING_CST && !integer_zerop (arg1.value)))
+       warning (OPT_Wstring_literal_comparison,
+                "comparison with string literal");
+    }
+  else if (TREE_CODE_CLASS (code) == tcc_comparison
+          && (code1 == STRING_CST || code2 == STRING_CST))
+    warning (OPT_Wstring_literal_comparison,
+            "comparison with string literal");
+
   overflow_warning (result.value);
 
   return result;
@@ -2429,8 +2733,18 @@ pointer_diff (tree op0, tree op1)
      different mode in place.)
      So first try to find a common term here 'by hand'; we want to cover
      at least the cases that occur in legal static initializers.  */
-  con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0;
-  con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1;
+  if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
+      && (TYPE_PRECISION (TREE_TYPE (op0))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
+    con0 = TREE_OPERAND (op0, 0);
+  else
+    con0 = op0;
+  if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR)
+      && (TYPE_PRECISION (TREE_TYPE (op1))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
+    con1 = TREE_OPERAND (op1, 0);
+  else
+    con1 = op1;
 
   if (TREE_CODE (con0) == PLUS_EXPR)
     {
@@ -2470,7 +2784,7 @@ pointer_diff (tree op0, tree op1)
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-  return fold (build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)));
+  return fold_build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -2491,12 +2805,20 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
   enum tree_code typecode = TREE_CODE (TREE_TYPE (arg));
   tree val;
   int noconvert = flag;
+  const char *invalid_op_diag;
 
   if (typecode == ERROR_MARK)
     return error_mark_node;
   if (typecode == ENUMERAL_TYPE || typecode == BOOLEAN_TYPE)
     typecode = INTEGER_TYPE;
 
+  if ((invalid_op_diag
+       = targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
+    {
+      error (invalid_op_diag);
+      return error_mark_node;
+    }
+
   switch (code)
     {
     case CONVERT_EXPR:
@@ -2571,13 +2893,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       break;
 
     case TRUTH_NOT_EXPR:
-      /* ??? Why do most validation here but that for non-lvalue arrays
-        in c_objc_common_truthvalue_conversion?  */
       if (typecode != INTEGER_TYPE
          && typecode != REAL_TYPE && typecode != POINTER_TYPE
-         && typecode != COMPLEX_TYPE
-         /* These will convert to a pointer.  */
-         && typecode != ARRAY_TYPE && typecode != FUNCTION_TYPE)
+         && typecode != COMPLEX_TYPE)
        {
          error ("wrong type argument to unary exclamation mark");
          return error_mark_node;
@@ -2585,14 +2903,11 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       arg = c_objc_common_truthvalue_conversion (arg);
       return invert_truthvalue (arg);
 
-    case NOP_EXPR:
-      break;
-
     case REALPART_EXPR:
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+       return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        return arg;
 
@@ -2600,7 +2915,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       if (TREE_CODE (arg) == COMPLEX_CST)
        return TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+       return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        return convert (TREE_TYPE (arg), integer_zero_node);
 
@@ -2632,9 +2947,9 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
          && typecode != INTEGER_TYPE && typecode != REAL_TYPE)
        {
          if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-            error ("wrong type argument to increment");
-          else
-            error ("wrong type argument to decrement");
+           error ("wrong type argument to increment");
+         else
+           error ("wrong type argument to decrement");
 
          return error_mark_node;
        }
@@ -2662,7 +2977,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
            else if ((pedantic || warn_pointer_arith)
                     && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
                         || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
-              {
+             {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
                  pedwarn ("wrong type argument to increment");
                else
@@ -2685,10 +3000,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
 
        /* Report a read-only lvalue.  */
        if (TREE_READONLY (arg))
-         readonly_error (arg,
-                         ((code == PREINCREMENT_EXPR
-                           || code == POSTINCREMENT_EXPR)
-                          ? lv_increment : lv_decrement));
+         {
+           readonly_error (arg,
+                           ((code == PREINCREMENT_EXPR
+                             || code == POSTINCREMENT_EXPR)
+                            ? lv_increment : lv_decrement));
+           return error_mark_node;
+         }
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
@@ -2716,9 +3034,13 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       /* For &x[y], return x+y */
       if (TREE_CODE (arg) == ARRAY_REF)
        {
-         if (!c_mark_addressable (TREE_OPERAND (arg, 0)))
+         tree op0 = TREE_OPERAND (arg, 0);
+         if (!c_mark_addressable (op0))
            return error_mark_node;
-         return build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
+         return build_binary_op (PLUS_EXPR,
+                                 (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
+                                  ? array_to_pointer_conversion (op0)
+                                  : op0),
                                  TREE_OPERAND (arg, 1), 1);
        }
 
@@ -2732,7 +3054,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
       argtype = TREE_TYPE (arg);
 
       /* If the lvalue is const or volatile, merge that into the type
-         to which the address will point.  Note that you can't get a
+        to which the address will point.  Note that you can't get a
         restricted pointer by taking the address of something, so we
         only have to deal with `const' and `volatile' here.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
@@ -2753,24 +3075,26 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
         when we have proper support for integer constant expressions.  */
       val = get_base_address (arg);
       if (val && TREE_CODE (val) == INDIRECT_REF
-         && integer_zerop (TREE_OPERAND (val, 0)))
-       return fold_convert (argtype, fold_offsetof (arg));
+          && TREE_CONSTANT (TREE_OPERAND (val, 0)))
+       {
+         tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1;
 
-      val = build1 (ADDR_EXPR, argtype, arg);
+         op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
+         return fold_build2 (PLUS_EXPR, argtype, op0, op1);
+       }
 
-      if (TREE_CODE (arg) == COMPOUND_LITERAL_EXPR)
-       TREE_INVARIANT (val) = TREE_CONSTANT (val) = 1;
+      val = build1 (ADDR_EXPR, argtype, arg);
 
       return val;
 
     default:
-      break;
+      gcc_unreachable ();
     }
 
   if (argtype == 0)
     argtype = TREE_TYPE (arg);
-  val = build1 (code, argtype, arg);
-  return require_constant_value ? fold_initializer (val) : fold (val);
+  return require_constant_value ? fold_build1_initializer (code, argtype, arg)
+                               : fold_build1 (code, argtype, arg);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language.
@@ -2815,32 +3139,36 @@ lvalue_p (tree ref)
 static void
 readonly_error (tree arg, enum lvalue_use use)
 {
-  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement);
+  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
+             || use == lv_asm);
   /* Using this macro rather than (for example) arrays of messages
      ensures that all the format strings are checked at compile
      time.  */
-#define READONLY_MSG(A, I, D) (use == lv_assign                                \
-                              ? (A)                                    \
-                              : (use == lv_increment ? (I) : (D)))
+#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A)              \
+                                  : (use == lv_increment ? (I)         \
+                                  : (use == lv_decrement ? (D) : (AS))))
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
        readonly_error (TREE_OPERAND (arg, 0), use);
       else
-       error (READONLY_MSG (N_("assignment of read-only member %qD"),
-                            N_("increment of read-only member %qD"),
-                            N_("decrement of read-only member %qD")),
+       error (READONLY_MSG (G_("assignment of read-only member %qD"),
+                            G_("increment of read-only member %qD"),
+                            G_("decrement of read-only member %qD"),
+                            G_("read-only member %qD used as %<asm%> output")),
               TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (N_("assignment of read-only variable %qD"),
-                        N_("increment of read-only variable %qD"),
-                        N_("decrement of read-only variable %qD")),
+    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
+                        G_("increment of read-only variable %qD"),
+                        G_("decrement of read-only variable %qD"),
+                        G_("read-only variable %qD used as %<asm%> output")),
           arg);
   else
-    error (READONLY_MSG (N_("assignment of read-only location"),
-                        N_("increment of read-only location"),
-                        N_("decrement of read-only location")));
+    error (READONLY_MSG (G_("assignment of read-only location"),
+                        G_("increment of read-only location"),
+                        G_("decrement of read-only location"),
+                        G_("read-only location used as %<asm%> output")));
 }
 
 
@@ -2973,9 +3301,9 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
        result_type = TYPE_MAIN_VARIANT (type1);
     }
   else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
-            || code1 == COMPLEX_TYPE)
-           && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
-               || code2 == COMPLEX_TYPE))
+           || code1 == COMPLEX_TYPE)
+          && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
+              || code2 == COMPLEX_TYPE))
     {
       result_type = c_common_type (type1, type2);
 
@@ -3015,13 +3343,11 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
-      if (comp_target_types (type1, type2, 1))
+      if (comp_target_types (type1, type2))
        result_type = common_pointer_type (type1, type2);
-      else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
-              && TREE_CODE (orig_op1) != NOP_EXPR)
+      else if (null_pointer_constant_p (orig_op1))
        result_type = qualify_type (type2, type1);
-      else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
-              && TREE_CODE (orig_op2) != NOP_EXPR)
+      else if (null_pointer_constant_p (orig_op2))
        result_type = qualify_type (type1, type2);
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
@@ -3047,7 +3373,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
-      if (!integer_zerop (op2))
+      if (!null_pointer_constant_p (orig_op2))
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
@@ -3057,7 +3383,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
     }
   else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
     {
-      if (!integer_zerop (op1))
+      if (!null_pointer_constant_p (orig_op1))
        pedwarn ("pointer/integer type mismatch in conditional expression");
       else
        {
@@ -3088,10 +3414,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
   if (result_type != TREE_TYPE (op2))
     op2 = convert_and_check (result_type, op2);
 
-  if (TREE_CODE (ifexp) == INTEGER_CST)
-    return non_lvalue (integer_zerop (ifexp) ? op2 : op1);
-
-  return fold (build3 (COND_EXPR, result_type, ifexp, op1, op2));
+  return fold_build3 (COND_EXPR, result_type, ifexp, op1, op2);
 }
 \f
 /* Return a compound expression that performs two expressions and
@@ -3100,18 +3423,25 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
 tree
 build_compound_expr (tree expr1, tree expr2)
 {
-  /* Convert arrays and functions to pointers.  */
-  expr2 = default_function_array_conversion (expr2);
-
   if (!TREE_SIDE_EFFECTS (expr1))
     {
       /* The left-hand operand of a comma expression is like an expression
-         statement: with -Wextra or -Wunused, we should warn if it doesn't have
+        statement: with -Wextra or -Wunused, we should warn if it doesn't have
         any side-effects, unless it was explicitly cast to (void).  */
-      if (warn_unused_value
-           && !(TREE_CODE (expr1) == CONVERT_EXPR
-                && VOID_TYPE_P (TREE_TYPE (expr1))))
-        warning (0, "left-hand operand of comma expression has no effect");
+      if (warn_unused_value)
+       {
+         if (VOID_TYPE_P (TREE_TYPE (expr1))
+             && (TREE_CODE (expr1) == NOP_EXPR
+                 || TREE_CODE (expr1) == CONVERT_EXPR))
+           ; /* (void) a, b */
+         else if (VOID_TYPE_P (TREE_TYPE (expr1))
+                  && TREE_CODE (expr1) == COMPOUND_EXPR
+                  && (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR
+                      || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
+           ; /* (void) a, (void) b, c */
+         else
+           warning (0, "left-hand operand of comma expression has no effect");
+       }
     }
 
   /* With -Wunused, we should also warn if the left-hand operand does have
@@ -3121,6 +3451,9 @@ build_compound_expr (tree expr1, tree expr2)
   else if (warn_unused_value)
     warn_if_unused_value (expr1, input_location);
 
+  if (expr2 == error_mark_node)
+    return error_mark_node;
+
   return build2 (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
 }
 
@@ -3166,7 +3499,6 @@ build_c_cast (tree type, tree expr)
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
-      value = default_function_array_conversion (value);
 
       for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
        if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
@@ -3180,8 +3512,7 @@ build_c_cast (tree type, tree expr)
          if (pedantic)
            pedwarn ("ISO C forbids casts to union type");
          t = digest_init (type,
-                          build_constructor (type,
-                                             build_tree_list (field, value)),
+                          build_constructor_single (type, field, value),
                           true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          TREE_INVARIANT (t) = TREE_INVARIANT (value);
@@ -3194,14 +3525,9 @@ build_c_cast (tree type, tree expr)
     {
       tree otype, ovalue;
 
-      /* If casting to void, avoid the error that would come
-        from default_conversion in the case of a non-lvalue array.  */
       if (type == void_type_node)
        return build1 (CONVERT_EXPR, type, value);
 
-      /* Convert functions and arrays to pointers,
-        but don't convert any other types.  */
-      value = default_function_array_conversion (value);
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
@@ -3247,7 +3573,7 @@ build_c_cast (tree type, tree expr)
        }
 
       /* Warn about possible alignment problems.  */
-      if (STRICT_ALIGNMENT && warn_cast_align
+      if (STRICT_ALIGNMENT
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
@@ -3258,52 +3584,34 @@ build_c_cast (tree type, tree expr)
                || TREE_CODE (TREE_TYPE (otype)) == RECORD_TYPE)
               && TYPE_MODE (TREE_TYPE (otype)) == VOIDmode)
          && TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
-       warning (0, "cast increases required alignment of target type");
+       warning (OPT_Wcast_align,
+                "cast increases required alignment of target type");
 
-      if (warn_pointer_to_int_cast
-         && TREE_CODE (type) == INTEGER_TYPE
+      if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
-         && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
-         && !TREE_CONSTANT (value))
-       warning (0, "cast from pointer to integer of different size");
-
-      if (warn_bad_function_cast
-         && TREE_CODE (value) == CALL_EXPR
+         && TYPE_PRECISION (type) != TYPE_PRECISION (otype))
+      /* Unlike conversion of integers to pointers, where the
+         warning is disabled for converting constants because
+         of cases such as SIG_*, warn about converting constant
+         pointers to integers. In some cases it may cause unwanted
+         sign extension, and a warning is appropriate.  */
+       warning (OPT_Wpointer_to_int_cast,
+                "cast from pointer to integer of different size");
+
+      if (TREE_CODE (value) == CALL_EXPR
          && TREE_CODE (type) != TREE_CODE (otype))
-       warning (0, "cast from function call of type %qT to non-matching "
-                "type %qT", otype, type);
+       warning (OPT_Wbad_function_cast, "cast from function call of type %qT "
+                "to non-matching type %qT", otype, type);
 
-      if (warn_int_to_pointer_cast
-         && TREE_CODE (type) == POINTER_TYPE
+      if (TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == INTEGER_TYPE
          && TYPE_PRECISION (type) != TYPE_PRECISION (otype)
          /* Don't warn about converting any constant.  */
          && !TREE_CONSTANT (value))
-       warning (0, "cast to pointer from integer of different size");
+       warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
+                "of different size");
 
-      if (TREE_CODE (type) == POINTER_TYPE
-         && TREE_CODE (otype) == POINTER_TYPE
-         && TREE_CODE (expr) == ADDR_EXPR
-         && DECL_P (TREE_OPERAND (expr, 0))
-         && flag_strict_aliasing && warn_strict_aliasing
-         && !VOID_TYPE_P (TREE_TYPE (type)))
-       {
-         /* Casting the address of a decl to non void pointer. Warn
-            if the cast breaks type based aliasing.  */
-         if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
-           warning (0, "type-punning to incomplete type might break strict-aliasing rules");
-         else
-           {
-             HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
-             HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
-
-             if (!alias_sets_conflict_p (set1, set2))
-               warning (0, "dereferencing type-punned pointer will break strict-aliasing rules");
-             else if (warn_strict_aliasing > 1
-                      && !alias_sets_might_conflict_p (set1, set2))
-               warning (0, "dereferencing type-punned pointer might break strict-aliasing rules");
-           }
-       }
+      strict_aliasing_warning (otype, type, expr);
 
       /* If pedantic, warn for conversions between function and object
         pointer types, except for converting a null pointer constant
@@ -3320,8 +3628,7 @@ build_c_cast (tree type, tree expr)
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
-         && !(integer_zerop (value) && TREE_TYPE (otype) == void_type_node
-              && TREE_CODE (expr) != NOP_EXPR))
+         && !null_pointer_constant_p (value))
        pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
 
       ovalue = value;
@@ -3330,17 +3637,19 @@ build_c_cast (tree type, tree expr)
       /* Ignore any integer overflow caused by the cast.  */
       if (TREE_CODE (value) == INTEGER_CST)
        {
-         if (EXPR_P (ovalue))
-           /* If OVALUE had overflow set, then so will VALUE, so it
-              is safe to overwrite.  */
-           TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
-         else
-           TREE_OVERFLOW (value) = 0;
-         
-         if (CONSTANT_CLASS_P (ovalue))
-           /* Similarly, constant_overflow cannot have become
-              cleared.  */
-           TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+         if (CONSTANT_CLASS_P (ovalue)
+             && (TREE_OVERFLOW (ovalue) || TREE_CONSTANT_OVERFLOW (ovalue)))
+           {
+             /* Avoid clobbering a shared constant.  */
+             value = copy_node (value);
+             TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+             TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+           }
+         else if (TREE_OVERFLOW (value) || TREE_CONSTANT_OVERFLOW (value))
+           /* Reset VALUE's overflow flags, ensuring constant sharing.  */
+           value = build_int_cst_wide (TREE_TYPE (value),
+                                       TREE_INT_CST_LOW (value),
+                                       TREE_INT_CST_HIGH (value));
        }
     }
 
@@ -3367,7 +3676,6 @@ c_cast_expr (struct c_type_name *type_name, tree expr)
 
   return build_c_cast (type, expr);
 }
-
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
    MODIFYCODE is the code for a binary operator that we use
@@ -3389,6 +3697,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
+  if (!lvalue_or_else (lhs, lv_assign))
+    return error_mark_node;
+
   STRIP_TYPE_NOPS (rhs);
 
   newrhs = rhs;
@@ -3402,16 +3713,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
       newrhs = build_binary_op (modifycode, lhs, rhs, 1);
     }
 
-  if (!lvalue_or_else (lhs, lv_assign))
-    return error_mark_node;
-
   /* Give an error for storing in something that is 'const'.  */
 
   if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
-    readonly_error (lhs, lv_assign);
+    {
+      readonly_error (lhs, lv_assign);
+      return error_mark_node;
+    }
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
@@ -3441,6 +3752,14 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
+  /* Emit ObjC write barrier, if necessary.  */
+  if (c_dialect_objc () && flag_objc_gc)
+    {
+      result = objc_generate_write_barrier (lhs, modifycode, newrhs);
+      if (result)
+       return result;
+    }
+
   /* Scan operands.  */
 
   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
@@ -3476,6 +3795,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   tree rhstype;
   enum tree_code coder;
   tree rname = NULL_TREE;
+  bool objc_ok = false;
 
   if (errtype == ic_argpass || errtype == ic_argpass_nonproto)
     {
@@ -3525,10 +3845,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 
   STRIP_TYPE_NOPS (rhs);
 
-  if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
-      || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE)
-    rhs = default_conversion (rhs);
-  else if (optimize && TREE_CODE (rhs) == VAR_DECL)
+  if (optimize && TREE_CODE (rhs) == VAR_DECL
+          && TREE_CODE (TREE_TYPE (rhs)) != ARRAY_TYPE)
     rhs = decl_constant_value_for_broken_optimization (rhs);
 
   rhstype = TREE_TYPE (rhs);
@@ -3537,14 +3855,35 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   if (coder == ERROR_MARK)
     return error_mark_node;
 
+  if (c_dialect_objc ())
+    {
+      int parmno;
+
+      switch (errtype)
+       {
+       case ic_return:
+         parmno = 0;
+         break;
+
+       case ic_assign:
+         parmno = -1;
+         break;
+
+       case ic_init:
+         parmno = -2;
+         break;
+
+       default:
+         parmno = parmnum;
+         break;
+       }
+
+      objc_ok = objc_compare_types (type, rhstype, parmno, rname);
+    }
+
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
     {
       overflow_warning (rhs);
-      /* Check for Objective-C protocols.  This will automatically
-        issue a warning if there are protocol violations.  No need to
-        use the return value.  */
-      if (c_dialect_objc ())
-       objc_comptypes (type, rhstype, 0);
       return rhs;
     }
 
@@ -3586,7 +3925,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     }
   /* Some types can interconvert without explicit casts.  */
   else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
-           && vector_types_convertible_p (type, TREE_TYPE (rhs)))
+          && vector_types_convertible_p (type, TREE_TYPE (rhs)))
     return convert (type, rhs);
   /* Arithmetic types all interconvert, and enum is treated like int.  */
   else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
@@ -3602,13 +3941,11 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
           && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
     {
-      tree memb_types;
-      tree marginal_memb_type = 0;
+      tree memb, marginal_memb = NULL_TREE;
 
-      for (memb_types = TYPE_FIELDS (type); memb_types;
-          memb_types = TREE_CHAIN (memb_types))
+      for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb))
        {
-         tree memb_type = TREE_TYPE (memb_types);
+         tree memb_type = TREE_TYPE (memb);
 
          if (comptypes (TYPE_MAIN_VARIANT (memb_type),
                         TYPE_MAIN_VARIANT (rhstype)))
@@ -3627,7 +3964,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                 Meanwhile, the lhs target must have all the qualifiers of
                 the rhs.  */
              if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-                 || comp_target_types (memb_type, rhstype, 0))
+                 || comp_target_types (memb_type, rhstype))
                {
                  /* If this type won't generate any warnings, use it.  */
                  if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
@@ -3640,28 +3977,26 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                    break;
 
                  /* Keep looking for a better type, but remember this one.  */
-                 if (!marginal_memb_type)
-                   marginal_memb_type = memb_type;
+                 if (!marginal_memb)
+                   marginal_memb = memb;
                }
            }
 
          /* Can convert integer zero to any pointer type.  */
-         if (integer_zerop (rhs)
-             || (TREE_CODE (rhs) == NOP_EXPR
-                 && integer_zerop (TREE_OPERAND (rhs, 0))))
+         if (null_pointer_constant_p (rhs))
            {
              rhs = null_pointer_node;
              break;
            }
        }
 
-      if (memb_types || marginal_memb_type)
+      if (memb || marginal_memb)
        {
-         if (!memb_types)
+         if (!memb)
            {
              /* We have only a marginally acceptable member type;
                 it needs a warning.  */
-             tree ttl = TREE_TYPE (marginal_memb_type);
+             tree ttl = TREE_TYPE (TREE_TYPE (marginal_memb));
              tree ttr = TREE_TYPE (rhstype);
 
              /* Const and volatile mean something different for function
@@ -3675,33 +4010,35 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
                  if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-                   WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE "
+                   WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE "
                                            "makes qualified function "
                                            "pointer from unqualified"),
-                                        N_("assignment makes qualified "
+                                        G_("assignment makes qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        N_("initialization makes qualified "
+                                        G_("initialization makes qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        N_("return makes qualified function "
+                                        G_("return makes qualified function "
                                            "pointer from unqualified"));
                }
              else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
+               WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
                                        "qualifiers from pointer target type"),
-                                    N_("assignment discards qualifiers "
+                                    G_("assignment discards qualifiers "
                                        "from pointer target type"),
-                                    N_("initialization discards qualifiers "
+                                    G_("initialization discards qualifiers "
                                        "from pointer target type"),
-                                    N_("return discards qualifiers from "
+                                    G_("return discards qualifiers from "
                                        "pointer target type"));
+
+             memb = marginal_memb;
            }
 
-         if (pedantic && !DECL_IN_SYSTEM_HEADER (fundecl))
+         if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
            pedwarn ("ISO C prohibits argument conversion to union type");
 
-         return build1 (NOP_EXPR, type, rhs);
+         return build_constructor_single (type, memb, rhs);
        }
     }
 
@@ -3722,15 +4059,60 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
        mvr = TYPE_MAIN_VARIANT (mvr);
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = (targetm.vector_opaque_p (type)
-                           || targetm.vector_opaque_p (rhstype))
-        && TREE_CODE (ttl) == VECTOR_TYPE
-        && TREE_CODE (ttr) == VECTOR_TYPE;
+                          || targetm.vector_opaque_p (rhstype))
+       && TREE_CODE (ttl) == VECTOR_TYPE
+       && TREE_CODE (ttr) == VECTOR_TYPE;
+
+      /* C++ does not allow the implicit conversion void* -> T*.  However,
+        for the purpose of reducing the number of false positives, we
+        tolerate the special case of
+
+               int *p = NULL;
+
+        where NULL is typically defined in C to be '(void *) 0'.  */
+      if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
+       warning (OPT_Wc___compat, "request for implicit conversion from "
+                "%qT to %qT not permitted in C++", rhstype, type);
+
+      /* Check if the right-hand side has a format attribute but the
+        left-hand side doesn't.  */
+      if (warn_missing_format_attribute
+         && check_missing_format_attribute (type, rhstype))
+       {
+         switch (errtype)
+         {
+         case ic_argpass:
+         case ic_argpass_nonproto:
+           warning (OPT_Wmissing_format_attribute,
+                    "argument %d of %qE might be "
+                    "a candidate for a format attribute",
+                    parmnum, rname);
+           break;
+         case ic_assign:
+           warning (OPT_Wmissing_format_attribute,
+                    "assignment left-hand side might be "
+                    "a candidate for a format attribute");
+           break;
+         case ic_init:
+           warning (OPT_Wmissing_format_attribute,
+                    "initialization left-hand side might be "
+                    "a candidate for a format attribute");
+           break;
+         case ic_return:
+           warning (OPT_Wmissing_format_attribute,
+                    "return type might be "
+                    "a candidate for a format attribute");
+           break;
+         default:
+           gcc_unreachable ();
+         }
+       }
 
       /* Any non-function converts to a [const][volatile] void *
         and vice versa; otherwise, targets must be the same.
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
       if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
-         || (target_cmp = comp_target_types (type, rhstype, 0))
+         || (target_cmp = comp_target_types (type, rhstype))
          || is_opaque_pointer
          || (c_common_unsigned_type (mvl)
              == c_common_unsigned_type (mvr)))
@@ -3739,18 +4121,16 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
                  ||
                  (VOID_TYPE_P (ttr)
-                  /* Check TREE_CODE to catch cases like (void *) (char *) 0
-                     which are not ANSI null ptr constants.  */
-                  && (!integer_zerop (rhs) || TREE_CODE (rhs) == NOP_EXPR)
+                  && !null_pointer_constant_p (rhs)
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (N_("ISO C forbids passing argument %d of "
+           WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
                                    "and %<void *%>"),
-                                N_("ISO C forbids assignment between "
+                                G_("ISO C forbids assignment between "
                                    "function pointer and %<void *%>"),
-                                N_("ISO C forbids initialization between "
+                                G_("ISO C forbids initialization between "
                                    "function pointer and %<void *%>"),
-                                N_("ISO C forbids return between function "
+                                G_("ISO C forbids return between function "
                                    "pointer and %<void *%>"));
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
@@ -3758,14 +4138,20 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
              if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE discards "
-                                       "qualifiers from pointer target type"),
-                                    N_("assignment discards qualifiers "
-                                       "from pointer target type"),
-                                    N_("initialization discards qualifiers "
-                                       "from pointer target type"),
-                                    N_("return discards qualifiers from "
-                                       "pointer target type"));
+               {
+                 /* Types differing only by the presence of the 'volatile'
+                    qualifier are acceptable if the 'volatile' has been added
+                    in by the Objective-C EH machinery.  */
+                 if (!objc_type_quals_match (ttl, ttr))
+                   WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
+                                           "qualifiers from pointer target type"),
+                                        G_("assignment discards qualifiers "
+                                           "from pointer target type"),
+                                        G_("initialization discards qualifiers "
+                                           "from pointer target type"),
+                                        G_("return discards qualifiers from "
+                                           "pointer target type"));
+               }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
              else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
@@ -3773,13 +4159,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                ;
              /* If there is a mismatch, do warn.  */
              else if (warn_pointer_sign)
-               WARN_FOR_ASSIGNMENT (N_("pointer targets in passing argument "
+               WARN_FOR_ASSIGNMENT (G_("pointer targets in passing argument "
                                        "%d of %qE differ in signedness"),
-                                    N_("pointer targets in assignment "
+                                    G_("pointer targets in assignment "
                                        "differ in signedness"),
-                                    N_("pointer targets in initialization "
+                                    G_("pointer targets in initialization "
                                        "differ in signedness"),
-                                    N_("pointer targets in return differ "
+                                    G_("pointer targets in return differ "
                                        "in signedness"));
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
@@ -3790,24 +4176,27 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
-               WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+               WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
                                        "qualified function pointer "
                                        "from unqualified"),
-                                    N_("assignment makes qualified function "
+                                    G_("assignment makes qualified function "
                                        "pointer from unqualified"),
-                                    N_("initialization makes qualified "
+                                    G_("initialization makes qualified "
                                        "function pointer from unqualified"),
-                                    N_("return makes qualified function "
+                                    G_("return makes qualified function "
                                        "pointer from unqualified"));
            }
        }
       else
-       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE from "
-                               "incompatible pointer type"),
-                            N_("assignment from incompatible pointer type"),
-                            N_("initialization from incompatible "
-                               "pointer type"),
-                            N_("return from incompatible pointer type"));
+       /* Avoid warning about the volatile ObjC EH puts on decls.  */
+       if (!objc_ok)
+         WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from "
+                                 "incompatible pointer type"),
+                              G_("assignment from incompatible pointer type"),
+                              G_("initialization from incompatible "
+                                 "pointer type"),
+                              G_("return from incompatible pointer type"));
+
       return convert (type, rhs);
     }
   else if (codel == POINTER_TYPE && coder == ARRAY_TYPE)
@@ -3822,32 +4211,27 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       /* An explicit constant 0 can convert to a pointer,
         or one that results from arithmetic, even including
         a cast to integer type.  */
-      if (!(TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs))
-         &&
-         !(TREE_CODE (rhs) == NOP_EXPR
-           && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE
-           && TREE_CODE (TREE_OPERAND (rhs, 0)) == INTEGER_CST
-           && integer_zerop (TREE_OPERAND (rhs, 0))))
-       WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes "
+      if (!null_pointer_constant_p (rhs))
+       WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
-                            N_("assignment makes pointer from integer "
+                            G_("assignment makes pointer from integer "
                                "without a cast"),
-                            N_("initialization makes pointer from "
+                            G_("initialization makes pointer from "
                                "integer without a cast"),
-                            N_("return makes pointer from integer "
+                            G_("return makes pointer from integer "
                                "without a cast"));
 
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (N_("passing argument %d of %qE makes integer "
+      WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer "
                              "from pointer without a cast"),
-                          N_("assignment makes integer from pointer "
+                          G_("assignment makes integer from pointer "
                              "without a cast"),
-                          N_("initialization makes integer from pointer "
+                          G_("initialization makes integer from pointer "
                              "without a cast"),
-                          N_("return makes integer from pointer "
+                          G_("return makes integer from pointer "
                              "without a cast"));
       return convert (type, rhs);
     }
@@ -3879,7 +4263,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 }
 
 /* Convert VALUE for assignment into inlined parameter PARM.  ARGNUM
-   is used for error and waring reporting and indicates which argument
+   is used for error and warning reporting and indicates which argument
    is being processed.  */
 
 tree
@@ -3887,9 +4271,15 @@ c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
 {
   tree ret, type;
 
-  /* If FN was prototyped, the value has been converted already
-     in convert_arguments.  */
-  if (!value || TYPE_ARG_TYPES (TREE_TYPE (fn)))
+  /* If FN was prototyped at the call site, the value has been converted
+     already in convert_arguments.
+     However, we might see a prototype now that was not in place when
+     the function call was seen, so check that the VALUE actually matches
+     PARM before taking an early exit.  */
+  if (!value
+      || (TYPE_ARG_TYPES (TREE_TYPE (fn))
+         && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+             == TYPE_MAIN_VARIANT (TREE_TYPE (value)))))
     return value;
 
   type = TREE_TYPE (parm);
@@ -3948,9 +4338,10 @@ store_init_value (tree decl, tree init)
 
   /* Store the expression if valid; else report error.  */
 
-  if (warn_traditional && !in_system_header
+  if (!in_system_header
       && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl))
-    warning (0, "traditional C rejects automatic aggregate initialization");
+    warning (OPT_Wtraditional, "traditional C rejects automatic "
+            "aggregate initialization");
 
   DECL_INITIAL (decl) = value;
 
@@ -3970,16 +4361,18 @@ store_init_value (tree decl, tree init)
 
       if (TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
        {
-         tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
+         tree cldecl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
 
-         if (TYPE_DOMAIN (TREE_TYPE (decl)))
+         if (TYPE_DOMAIN (TREE_TYPE (cldecl)))
            {
              /* For int foo[] = (int [3]){1}; we need to set array size
                 now since later on array initializer will be just the
                 brace enclosed list of the compound literal.  */
-             TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (decl));
+             type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+             TREE_TYPE (decl) = type;
+             TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
              layout_type (type);
-             layout_decl (decl, 0);
+             layout_decl (cldecl, 0);
            }
        }
     }
@@ -3995,7 +4388,7 @@ struct spelling
   int kind;
   union
     {
-      int i;
+      unsigned HOST_WIDE_INT i;
       const char *s;
     } u;
 };
@@ -4055,7 +4448,7 @@ push_member_name (tree decl)
 /* Push an array bounds on the stack.  Printed as [BOUNDS].  */
 
 static void
-push_array_bounds (int bounds)
+push_array_bounds (unsigned HOST_WIDE_INT bounds)
 {
   PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
 }
@@ -4090,7 +4483,7 @@ print_spelling (char *buffer)
   for (p = spelling_base; p < spelling; p++)
     if (p->kind == SPELLING_BOUNDS)
       {
-       sprintf (d, "[%d]", p->u.i);
+       sprintf (d, "[" HOST_WIDE_INT_PRINT_UNSIGNED "]", p->u.i);
        d += strlen (d);
       }
     else
@@ -4181,6 +4574,7 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
   tree inside_init = init;
 
   if (type == error_mark_node
+      || !init
       || init == error_mark_node
       || TREE_TYPE (init) == error_mark_node)
     return error_mark_node;
@@ -4271,18 +4665,22 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
 
       if (TREE_CODE (inside_init) == CONSTRUCTOR)
        {
-         tree link;
+         unsigned HOST_WIDE_INT ix;
+         tree value;
+         bool constant_p = true;
 
          /* Iterate through elements and check if all constructor
             elements are *_CSTs.  */
-         for (link = CONSTRUCTOR_ELTS (inside_init);
-              link;
-              link = TREE_CHAIN (link))
-           if (! CONSTANT_CLASS_P (TREE_VALUE (link)))
-             break;
+         FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (inside_init), ix, value)
+           if (!CONSTANT_CLASS_P (value))
+             {
+               constant_p = false;
+               break;
+             }
 
-         if (link == NULL)
-           return build_vector (type, CONSTRUCTOR_ELTS (inside_init));
+         if (constant_p)
+           return build_vector_from_ctor (type,
+                                          CONSTRUCTOR_ELTS (inside_init));
        }
     }
 
@@ -4299,34 +4697,36 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
          || (code == POINTER_TYPE
              && TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE
              && comptypes (TREE_TYPE (TREE_TYPE (inside_init)),
-                           TREE_TYPE (type)))
-         || (code == POINTER_TYPE
-             && TREE_CODE (TREE_TYPE (inside_init)) == FUNCTION_TYPE
-             && comptypes (TREE_TYPE (inside_init),
                            TREE_TYPE (type)))))
     {
       if (code == POINTER_TYPE)
        {
-         inside_init = default_function_array_conversion (inside_init);
-
          if (TREE_CODE (TREE_TYPE (inside_init)) == ARRAY_TYPE)
            {
-             error_init ("invalid use of non-lvalue array");
-             return error_mark_node;
+             if (TREE_CODE (inside_init) == STRING_CST
+                 || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
+               inside_init = array_to_pointer_conversion (inside_init);
+             else
+               {
+                 error_init ("invalid use of non-lvalue array");
+                 return error_mark_node;
+               }
            }
-        }
+       }
 
       if (code == VECTOR_TYPE)
        /* Although the types are compatible, we may require a
           conversion.  */
        inside_init = convert (type, inside_init);
 
-      if (require_constant && !flag_isoc99
+      if (require_constant
+         && (code == VECTOR_TYPE || !flag_isoc99)
          && TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
        {
          /* As an extension, allow initializing objects with static storage
             duration with compound literals (which are then treated just as
-            the brace enclosed list they contain).  */
+            the brace enclosed list they contain).  Also allow this for
+            vectors, as we can only assign them with compound literals.  */
          tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
          inside_init = DECL_INITIAL (decl);
        }
@@ -4365,6 +4765,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
          inside_init = error_mark_node;
        }
 
+      /* Added to enable additional -Wmissing-format-attribute warnings.  */
+      if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
+       inside_init = convert_for_assignment (type, inside_init, ic_init, NULL_TREE,
+                                             NULL_TREE, 0);
       return inside_init;
     }
 
@@ -4374,9 +4778,10 @@ digest_init (tree type, tree init, bool strict_string, int require_constant)
       || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
       || code == VECTOR_TYPE)
     {
-      /* Note that convert_for_assignment calls default_conversion
-        for arrays and functions.  We must not call it in the
-        case where inside_init is a null pointer constant.  */
+      if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
+         && (TREE_CODE (init) == STRING_CST
+             || TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
+       init = array_to_pointer_conversion (init);
       inside_init
        = convert_for_assignment (type, init, ic_init,
                                  NULL_TREE, NULL_TREE, 0);
@@ -4443,7 +4848,7 @@ static tree constructor_bit_index;
 /* If we are saving up the elements rather than allocating them,
    this is the list of elements so far (in reverse order,
    most recent first).  */
-static tree constructor_elements;
+static VEC(constructor_elt,gc) *constructor_elements;
 
 /* 1 if constructor should be incrementally stored into a constructor chain,
    0 if all the elements should be kept in AVL tree.  */
@@ -4495,7 +4900,7 @@ static int constructor_designated;
 static int designator_depth;
 
 /* Nonzero if there were diagnosed errors in this designator list.  */
-static int designator_errorneous;
+static int designator_erroneous;
 
 \f
 /* This stack has a level for each implicit or explicit level of
@@ -4514,7 +4919,7 @@ struct constructor_stack
   tree unfilled_index;
   tree unfilled_fields;
   tree bit_index;
-  tree elements;
+  VEC(constructor_elt,gc) *elements;
   struct init_node *pending_elts;
   int offset;
   int depth;
@@ -4558,7 +4963,7 @@ struct initializer_stack
   tree decl;
   struct constructor_stack *constructor_stack;
   struct constructor_range_stack *constructor_range_stack;
-  tree elements;
+  VEC(constructor_elt,gc) *elements;
   struct spelling *spelling;
   struct spelling *spelling_base;
   int spelling_size;
@@ -4575,7 +4980,7 @@ void
 start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
 {
   const char *locus;
-  struct initializer_stack *p = xmalloc (sizeof (struct initializer_stack));
+  struct initializer_stack *p = XNEW (struct initializer_stack);
 
   p->decl = constructor_decl;
   p->require_constant_value = require_constant_value;
@@ -4709,7 +5114,7 @@ really_start_incremental_init (tree type)
   constructor_incremental = 1;
   constructor_designated = 0;
   designator_depth = 0;
-  designator_errorneous = 0;
+  designator_erroneous = 0;
 
   if (TREE_CODE (constructor_type) == RECORD_TYPE
       || TREE_CODE (constructor_type) == UNION_TYPE)
@@ -4759,7 +5164,7 @@ really_start_incremental_init (tree type)
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
        build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
-      constructor_index = convert (bitsizetype, bitsize_zero_node);
+      constructor_index = bitsize_zero_node;
       constructor_unfilled_index = constructor_index;
     }
   else
@@ -4782,19 +5187,27 @@ push_init_level (int implicit)
   tree value = NULL_TREE;
 
   /* If we've exhausted any levels that didn't have braces,
-     pop them now.  */
-  while (constructor_stack->implicit)
+     pop them now.  If implicit == 1, this will have been done in
+     process_init_element; do not repeat it here because in the case
+     of excess initializers for an empty aggregate this leads to an
+     infinite cycle of popping a level and immediately recreating
+     it.  */
+  if (implicit != 1)
     {
-      if ((TREE_CODE (constructor_type) == RECORD_TYPE
-          || TREE_CODE (constructor_type) == UNION_TYPE)
-         && constructor_fields == 0)
-       process_init_element (pop_init_level (1));
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE
-              && constructor_max_index
-              && tree_int_cst_lt (constructor_max_index, constructor_index))
-       process_init_element (pop_init_level (1));
-      else
-       break;
+      while (constructor_stack->implicit)
+       {
+         if ((TREE_CODE (constructor_type) == RECORD_TYPE
+              || TREE_CODE (constructor_type) == UNION_TYPE)
+             && constructor_fields == 0)
+           process_init_element (pop_init_level (1));
+         else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+                  && constructor_max_index
+                  && tree_int_cst_lt (constructor_max_index,
+                                      constructor_index))
+           process_init_element (pop_init_level (1));
+         else
+           break;
+       }
     }
 
   /* Unless this is an explicit brace, we need to preserve previous
@@ -4845,7 +5258,7 @@ push_init_level (int implicit)
       p->range_stack = constructor_range_stack;
       constructor_range_stack = 0;
       designator_depth = 0;
-      designator_errorneous = 0;
+      designator_erroneous = 0;
     }
 
   /* Don't die if an entire brace-pair level is superfluous
@@ -4868,7 +5281,7 @@ push_init_level (int implicit)
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     {
       constructor_type = TREE_TYPE (constructor_type);
-      push_array_bounds (tree_low_cst (constructor_index, 0));
+      push_array_bounds (tree_low_cst (constructor_index, 1));
       constructor_depth++;
     }
 
@@ -4885,7 +5298,7 @@ push_init_level (int implicit)
       constructor_constant = TREE_CONSTANT (value);
       constructor_simple = TREE_STATIC (value);
       constructor_elements = CONSTRUCTOR_ELTS (value);
-      if (constructor_elements
+      if (!VEC_empty (constructor_elt, constructor_elements)
          && (TREE_CODE (constructor_type) == RECORD_TYPE
              || TREE_CODE (constructor_type) == ARRAY_TYPE))
        set_nonincremental_init ();
@@ -5010,7 +5423,7 @@ pop_init_level (int implicit)
       else
        {
          gcc_assert (!TYPE_SIZE (constructor_type));
-         
+
          if (constructor_depth > 2)
            error_init ("initialization of flexible array member in a nested context");
          else if (pedantic)
@@ -5060,19 +5473,19 @@ pop_init_level (int implicit)
     {
       /* A nonincremental scalar initializer--just return
         the element, after verifying there is just one.  */
-      if (constructor_elements == 0)
+      if (VEC_empty (constructor_elt,constructor_elements))
        {
          if (!constructor_erroneous)
            error_init ("empty scalar initializer");
          ret.value = error_mark_node;
        }
-      else if (TREE_CHAIN (constructor_elements) != 0)
+      else if (VEC_length (constructor_elt,constructor_elements) != 1)
        {
          error_init ("extra elements in scalar initializer");
-         ret.value = TREE_VALUE (constructor_elements);
+         ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
        }
       else
-       ret.value = TREE_VALUE (constructor_elements);
+       ret.value = VEC_index (constructor_elt,constructor_elements,0)->value;
     }
   else
     {
@@ -5081,7 +5494,7 @@ pop_init_level (int implicit)
       else
        {
          ret.value = build_constructor (constructor_type,
-                                        nreverse (constructor_elements));
+                                        constructor_elements);
          if (constructor_constant)
            TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
          if (constructor_constant && constructor_simple)
@@ -5111,15 +5524,8 @@ pop_init_level (int implicit)
   constructor_stack = p->next;
   free (p);
 
-  if (ret.value == 0)
-    {
-      if (constructor_stack == 0)
-       {
-         ret.value = error_mark_node;
-         return ret;
-       }
-      return ret;
-    }
+  if (ret.value == 0 && constructor_stack == 0)
+    ret.value = error_mark_node;
   return ret;
 }
 
@@ -5139,7 +5545,7 @@ set_designator (int array)
 
   /* If there were errors in this designator list already, bail out
      silently.  */
-  if (designator_errorneous)
+  if (designator_erroneous)
     return 1;
 
   if (!designator_depth)
@@ -5218,7 +5624,7 @@ set_init_index (tree first, tree last)
   if (set_designator (1))
     return;
 
-  designator_errorneous = 1;
+  designator_erroneous = 1;
 
   if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
       || (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
@@ -5264,7 +5670,7 @@ set_init_index (tree first, tree last)
        }
 
       designator_depth++;
-      designator_errorneous = 0;
+      designator_erroneous = 0;
       if (constructor_range_stack || last)
        push_range_stack (last);
     }
@@ -5280,7 +5686,7 @@ set_init_label (tree fieldname)
   if (set_designator (0))
     return;
 
-  designator_errorneous = 1;
+  designator_erroneous = 1;
 
   if (TREE_CODE (constructor_type) != RECORD_TYPE
       && TREE_CODE (constructor_type) != UNION_TYPE)
@@ -5302,7 +5708,7 @@ set_init_label (tree fieldname)
     {
       constructor_fields = tail;
       designator_depth++;
-      designator_errorneous = 0;
+      designator_erroneous = 0;
       if (constructor_range_stack)
        push_range_stack (NULL_TREE);
     }
@@ -5333,6 +5739,8 @@ add_pending_init (tree purpose, tree value)
            {
              if (TREE_SIDE_EFFECTS (p->value))
                warning_init ("initialized field with side-effects overwritten");
+             else if (warn_override_init)
+               warning_init ("initialized field overwritten");
              p->value = value;
              return;
            }
@@ -5354,6 +5762,8 @@ add_pending_init (tree purpose, tree value)
            {
              if (TREE_SIDE_EFFECTS (p->value))
                warning_init ("initialized field with side-effects overwritten");
+             else if (warn_override_init)
+               warning_init ("initialized field overwritten");
              p->value = value;
              return;
            }
@@ -5530,14 +5940,15 @@ add_pending_init (tree purpose, tree value)
 static void
 set_nonincremental_init (void)
 {
-  tree chain;
+  unsigned HOST_WIDE_INT ix;
+  tree index, value;
 
   if (TREE_CODE (constructor_type) != RECORD_TYPE
       && TREE_CODE (constructor_type) != ARRAY_TYPE)
     return;
 
-  for (chain = constructor_elements; chain; chain = TREE_CHAIN (chain))
-    add_pending_init (TREE_PURPOSE (chain), TREE_VALUE (chain));
+  FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
+    add_pending_init (index, value);
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -5626,7 +6037,7 @@ set_nonincremental_init_from_string (tree str)
          else if (bitpos == HOST_BITS_PER_WIDE_INT)
            {
              if (val[1] < 0)
-               val[0] = -1;
+               val[0] = -1;
            }
          else if (val[0] & (((HOST_WIDE_INT) 1)
                             << (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
@@ -5689,9 +6100,10 @@ find_init_member (tree field)
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     {
-      if (constructor_elements
-         && TREE_PURPOSE (constructor_elements) == field)
-       return TREE_VALUE (constructor_elements);
+      if (!VEC_empty (constructor_elt, constructor_elements)
+         && (VEC_last (constructor_elt, constructor_elements)->index
+             == field))
+       return VEC_last (constructor_elt, constructor_elements)->value;
     }
   return 0;
 }
@@ -5713,19 +6125,22 @@ static void
 output_init_element (tree value, bool strict_string, tree type, tree field,
                     int pending)
 {
+  constructor_elt *celt;
+
   if (type == error_mark_node || value == error_mark_node)
     {
       constructor_erroneous = 1;
       return;
     }
-  if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
-      || (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
-         && !(TREE_CODE (value) == STRING_CST
-              && TREE_CODE (type) == ARRAY_TYPE
-              && INTEGRAL_TYPE_P (TREE_TYPE (type)))
-         && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
-                        TYPE_MAIN_VARIANT (type))))
-    value = default_conversion (value);
+  if (TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
+      && (TREE_CODE (value) == STRING_CST
+         || TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
+      && !(TREE_CODE (value) == STRING_CST
+          && TREE_CODE (type) == ARRAY_TYPE
+          && INTEGRAL_TYPE_P (TREE_TYPE (type)))
+      && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
+                    TYPE_MAIN_VARIANT (type)))
+    value = array_to_pointer_conversion (value);
 
   if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
       && require_constant_value && !flag_isoc99 && pending)
@@ -5816,10 +6231,13 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
-          && constructor_elements)
+          && !VEC_empty (constructor_elt, constructor_elements))
     {
-      if (TREE_SIDE_EFFECTS (TREE_VALUE (constructor_elements)))
+      if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+                                      constructor_elements)->value))
        warning_init ("initialized field with side-effects overwritten");
+      else if (warn_override_init)
+       warning_init ("initialized field overwritten");
 
       /* We can have just one union field set.  */
       constructor_elements = 0;
@@ -5828,10 +6246,9 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
   /* Otherwise, output this element either to
      constructor_elements or to the assembler file.  */
 
-  if (field && TREE_CODE (field) == INTEGER_CST)
-    field = copy_node (field);
-  constructor_elements
-    = tree_cons (field, value, constructor_elements);
+  celt = VEC_safe_push (constructor_elt, gc, constructor_elements, NULL);
+  celt->index = field;
+  celt->value = value;
 
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -6017,7 +6434,7 @@ process_init_element (struct c_expr value)
   bool strict_string = value.original_code == STRING_CST;
 
   designator_depth = 0;
-  designator_errorneous = 0;
+  designator_erroneous = 0;
 
   /* Handle superfluous braces around string cst as in
      char x[] = {"foo"}; */
@@ -6028,7 +6445,7 @@ process_init_element (struct c_expr value)
       && integer_zerop (constructor_unfilled_index))
     {
       if (constructor_stack->replacement_value.value)
-        error_init ("excess elements in char array initializer");
+       error_init ("excess elements in char array initializer");
       constructor_stack->replacement_value = value;
       return;
     }
@@ -6131,10 +6548,10 @@ process_init_element (struct c_expr value)
            {
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
-               constructor_bit_index
+               constructor_bit_index
                  = size_binop (PLUS_EXPR,
-                               bit_position (constructor_fields),
-                               DECL_SIZE (constructor_fields));
+                               bit_position (constructor_fields),
+                               DECL_SIZE (constructor_fields));
 
              /* If the current field was the first one not yet written out,
                 it isn't now, so update.  */
@@ -6183,10 +6600,11 @@ process_init_element (struct c_expr value)
             again on the assumption that this must be conditional on
             __STDC__ anyway (and we've already complained about the
             member-designator already).  */
-         if (warn_traditional && !in_system_header && !constructor_designated
+         if (!in_system_header && !constructor_designated
              && !(value.value && (integer_zerop (value.value)
                                   || real_zerop (value.value))))
-           warning (0, "traditional C rejects initialization of unions");
+           warning (OPT_Wtraditional, "traditional C rejects initialization "
+                    "of unions");
 
          /* Accept a string constant to initialize a subarray.  */
          if (value.value != 0
@@ -6257,7 +6675,7 @@ process_init_element (struct c_expr value)
          /* Now output the actual element.  */
          if (value.value)
            {
-             push_array_bounds (tree_low_cst (constructor_index, 0));
+             push_array_bounds (tree_low_cst (constructor_index, 1));
              output_init_element (value.value, strict_string,
                                   elttype, constructor_index, 1);
              RESTORE_SPELLING_DEPTH (constructor_depth);
@@ -6276,8 +6694,8 @@ process_init_element (struct c_expr value)
        {
          tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
 
-         /* Do a basic check of initializer size.  Note that vectors
-            always have a fixed size derived from their type.  */
+        /* Do a basic check of initializer size.  Note that vectors
+           always have a fixed size derived from their type.  */
          if (tree_int_cst_lt (constructor_max_index, constructor_index))
            {
              pedwarn_init ("excess elements in vector initializer");
@@ -6420,6 +6838,14 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       if (!lvalue_or_else (output, lv_asm))
        output = error_mark_node;
 
+      if (output != error_mark_node
+         && (TREE_READONLY (output)
+             || TYPE_READONLY (TREE_TYPE (output))
+             || ((TREE_CODE (TREE_TYPE (output)) == RECORD_TYPE
+                  || TREE_CODE (TREE_TYPE (output)) == UNION_TYPE)
+                 && C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
+       readonly_error (output, lv_asm);
+
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       oconstraints[i] = constraint;
 
@@ -6432,14 +6858,11 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
            output = error_mark_node;
        }
       else
-        output = error_mark_node;
+       output = error_mark_node;
 
       TREE_VALUE (tail) = output;
     }
 
-  /* Perform default conversions on array and function inputs.
-     Don't do this for other types as it would screw up operands
-     expected to be in memory.  */
   for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
     {
       tree input;
@@ -6447,8 +6870,6 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
       input = TREE_VALUE (tail);
 
-      input = default_function_array_conversion (input);
-
       if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
                                  oconstraints, &allows_mem, &allows_reg))
        {
@@ -6471,12 +6892,10 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
 
   args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
 
-  /* Simple asm statements are treated as volatile.  */
-  if (simple)
-    {
-      ASM_VOLATILE_P (args) = 1;
-      ASM_INPUT_P (args) = 1;
-    }
+  /* asm statements without outputs, including simple ones, are treated
+     as volatile.  */
+  ASM_INPUT_P (args) = simple;
+  ASM_VOLATILE_P (args) = (noutputs == 0);
 
   return args;
 }
@@ -6546,7 +6965,8 @@ c_finish_goto_ptr (tree expr)
 tree
 c_finish_return (tree retval)
 {
-  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+  tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
+  bool no_warning = false;
 
   if (TREE_THIS_VOLATILE (current_function_decl))
     warning (0, "function declared %<noreturn%> has a %<return%> statement");
@@ -6556,8 +6976,11 @@ c_finish_return (tree retval)
       current_function_returns_null = 1;
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
-       pedwarn_c99 ("%<return%> with no value, in "
-                    "function returning non-void");
+       {
+         pedwarn_c99 ("%<return%> with no value, in "
+                      "function returning non-void");
+         no_warning = true;
+       }
     }
   else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
     {
@@ -6613,7 +7036,7 @@ c_finish_return (tree retval)
              inner = TREE_OPERAND (inner, 0);
 
              while (REFERENCE_CLASS_P (inner)
-                    && TREE_CODE (inner) != INDIRECT_REF)
+                    && TREE_CODE (inner) != INDIRECT_REF)
                inner = TREE_OPERAND (inner, 0);
 
              if (DECL_P (inner)
@@ -6633,7 +7056,9 @@ c_finish_return (tree retval)
       retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
     }
 
-  return add_stmt (build_stmt (RETURN_EXPR, retval));
+  ret_stmt = build_stmt (RETURN_EXPR, retval);
+  TREE_NO_WARNING (ret_stmt) |= no_warning;
+  return add_stmt (ret_stmt);
 }
 \f
 struct c_switch {
@@ -6679,34 +7104,33 @@ struct c_switch *c_switch_stack;
 tree
 c_start_case (tree exp)
 {
-  enum tree_code code;
-  tree type, orig_type = error_mark_node;
+  tree orig_type = error_mark_node;
   struct c_switch *cs;
 
   if (exp != error_mark_node)
     {
-      code = TREE_CODE (TREE_TYPE (exp));
       orig_type = TREE_TYPE (exp);
 
-      if (!INTEGRAL_TYPE_P (orig_type)
-         && code != ERROR_MARK)
+      if (!INTEGRAL_TYPE_P (orig_type))
        {
-         error ("switch quantity not an integer");
+         if (orig_type != error_mark_node)
+           {
+             error ("switch quantity not an integer");
+             orig_type = error_mark_node;
+           }
          exp = integer_zero_node;
-         orig_type = error_mark_node;
        }
       else
        {
-         type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
+         tree type = TYPE_MAIN_VARIANT (orig_type);
 
-         if (warn_traditional && !in_system_header
+         if (!in_system_header
              && (type == long_integer_type_node
                  || type == long_unsigned_type_node))
-           warning (0, "%<long%> switch expression not converted to "
-                    "%<int%> in ISO C");
+           warning (OPT_Wtraditional, "%<long%> switch expression not "
+                    "converted to %<int%> in ISO C");
 
          exp = default_conversion (exp);
-         type = TREE_TYPE (exp);
        }
     }
 
@@ -6837,31 +7261,14 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
     found:
 
       if (COND_EXPR_ELSE (inner_if))
-        warning (0, "%Hsuggest explicit braces to avoid ambiguous %<else%>",
+        warning (OPT_Wparentheses,
+                 "%Hsuggest explicit braces to avoid ambiguous %<else%>",
                  &if_locus);
     }
 
-  /* Diagnose ";" via the special empty statement node that we create.  */
-  if (extra_warnings)
-    {
-      if (TREE_CODE (then_block) == NOP_EXPR && !TREE_TYPE (then_block))
-       {
-         if (!else_block)
-           warning (0, "%Hempty body in an if-statement",
-                    EXPR_LOCUS (then_block));
-         then_block = alloc_stmt_list ();
-       }
-      if (else_block
-         && TREE_CODE (else_block) == NOP_EXPR
-         && !TREE_TYPE (else_block))
-       {
-         warning (0, "%Hempty body in an else-statement",
-                  EXPR_LOCUS (else_block));
-         else_block = alloc_stmt_list ();
-       }
-    }
+  empty_body_warning (then_block, else_block);
 
-  stmt = build3 (COND_EXPR, NULL_TREE, cond, then_block, else_block);
+  stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
   SET_EXPR_LOCATION (stmt, if_locus);
   add_stmt (stmt);
 }
@@ -6891,42 +7298,41 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
   else
     {
       tree top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+
       /* If we have an exit condition, then we build an IF with gotos either
-         out of the loop, or to the top of it.  If there's no exit condition,
-         then we just build a jump back to the top.  */
+        out of the loop, or to the top of it.  If there's no exit condition,
+        then we just build a jump back to the top.  */
       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
+
       if (cond && !integer_nonzerop (cond))
-        {
-          /* Canonicalize the loop condition to the end.  This means
-             generating a branch to the loop condition.  Reuse the
-             continue label, if possible.  */
-          if (cond_is_first)
-            {
-              if (incr || !clab)
-                {
-                  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
-                  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
-                }
-              else
-                t = build1 (GOTO_EXPR, void_type_node, clab);
+       {
+         /* Canonicalize the loop condition to the end.  This means
+            generating a branch to the loop condition.  Reuse the
+            continue label, if possible.  */
+         if (cond_is_first)
+           {
+             if (incr || !clab)
+               {
+                 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+                 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+               }
+             else
+               t = build1 (GOTO_EXPR, void_type_node, clab);
              SET_EXPR_LOCATION (t, start_locus);
-              add_stmt (t);
-            }
+             add_stmt (t);
+           }
+
          t = build_and_jump (&blab);
-          exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
-          exit = fold (exit);
+         exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
          if (cond_is_first)
-            SET_EXPR_LOCATION (exit, start_locus);
+           SET_EXPR_LOCATION (exit, start_locus);
          else
-            SET_EXPR_LOCATION (exit, input_location);
-        }
+           SET_EXPR_LOCATION (exit, input_location);
+       }
+
       add_stmt (top);
     }
+
   if (body)
     add_stmt (body);
   if (clab)
@@ -6961,13 +7367,24 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
       if (!skip)
        *label_p = label = create_artificial_label ();
     }
-  else if (TREE_CODE (label) != LABEL_DECL)
+  else if (TREE_CODE (label) == LABEL_DECL)
+    ;
+  else switch (TREE_INT_CST_LOW (label))
     {
+    case 0:
       if (is_break)
        error ("break statement not within loop or switch");
       else
-        error ("continue statement not within a loop");
+       error ("continue statement not within a loop");
+      return NULL_TREE;
+
+    case 1:
+      gcc_assert (is_break);
+      error ("break statement used with OpenMP for loop");
       return NULL_TREE;
+
+    default:
+      gcc_unreachable ();
     }
 
   if (skip)
@@ -7002,13 +7419,6 @@ c_process_expr_stmt (tree expr)
   if (!expr)
     return NULL_TREE;
 
-  /* Do default conversion if safe and possibly important,
-     in case within ({...}).  */
-  if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
-       && (flag_isoc99 || lvalue_p (expr)))
-      || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
-    expr = default_conversion (expr);
-
   if (warn_sequence_point)
     verify_sequence_points (expr);
 
@@ -7163,7 +7573,13 @@ c_finish_stmt_expr (tree body)
   if (last == error_mark_node
       || (last == BIND_EXPR_BODY (body)
          && BIND_EXPR_VARS (body) == NULL))
-    return last;
+    {
+      /* Do not warn if the return value of a statement expression is
+        unused.  */
+      if (EXPR_P (last))
+       TREE_NO_WARNING (last) = 1;
+      return last;
+    }
 
   /* Extract the type of said expression.  */
   type = TREE_TYPE (last);
@@ -7202,6 +7618,11 @@ c_begin_vm_scope (unsigned int scope)
   struct c_label_list *glist;
 
   gcc_assert (scope > 0);
+
+  /* At file_scope, we don't have to do any processing.  */
+  if (label_context_stack_vm == NULL)
+    return;
+
   if (c_switch_stack && !c_switch_stack->blocked_vm)
     c_switch_stack->blocked_vm = scope;
   for (glist = label_context_stack_vm->labels_used;
@@ -7345,6 +7766,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   tree type0, type1;
   enum tree_code code0, code1;
   tree op0, op1;
+  const char *invalid_op_diag;
 
   /* Expression code to give to the expression when it is built.
      Normally this is CODE, which is what the caller asked for,
@@ -7388,6 +7810,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   /* Nonzero means set RESULT_TYPE to the common type of the args.  */
   int common = 0;
 
+  /* True means types are compatible as far as ObjC is concerned.  */
+  bool objc_ok;
+
   if (convert_p)
     {
       op0 = default_conversion (orig_op0);
@@ -7417,6 +7842,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     return error_mark_node;
 
+  if ((invalid_op_diag
+       = targetm.invalid_binary_op (code, type0, type1)))
+    {
+      error (invalid_op_diag);
+      return error_mark_node;
+    }
+
+  objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -7433,7 +7867,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       /* Subtraction of two similar pointers.
         We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
-         && comp_target_types (type0, type1, 1))
+         && comp_target_types (type0, type1))
        return pointer_diff (op0, op1);
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -7453,20 +7887,22 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     case EXACT_DIV_EXPR:
       /* Floating point division by zero is a legitimate way to obtain
         infinities and NaNs.  */
-      if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
-       warning (0, "division by zero");
+      if (skip_evaluation == 0 && integer_zerop (op1))
+       warning (OPT_Wdiv_by_zero, "division by zero");
 
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
        {
+         enum tree_code tcode0 = code0, tcode1 = code1;
+
          if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
-           code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+           tcode0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
          if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
-           code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+           tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
 
-         if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
+         if (!(tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE))
            resultcode = RDIV_EXPR;
          else
            /* Although it would be tempting to shorten always here, that
@@ -7492,8 +7928,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case TRUNC_MOD_EXPR:
     case FLOOR_MOD_EXPR:
-      if (warn_div_by_zero && skip_evaluation == 0 && integer_zerop (op1))
-       warning (0, "division by zero");
+      if (skip_evaluation == 0 && integer_zerop (op1))
+       warning (OPT_Wdiv_by_zero, "division by zero");
 
       if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -7585,8 +8021,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
     case EQ_EXPR:
     case NE_EXPR:
-      if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE))
-       warning (0, "comparing floating point with == or != is unsafe");
+      if (code0 == REAL_TYPE || code1 == REAL_TYPE)
+       warning (OPT_Wfloat_equal,
+                "comparing floating point with == or != is unsafe");
       /* Result of comparison is always int,
         but don't convert the args to int!  */
       build_type = integer_type_node;
@@ -7602,36 +8039,54 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
-         if (comp_target_types (type0, type1, 1))
+         if (comp_target_types (type0, type1))
            result_type = common_pointer_type (type0, type1);
          else if (VOID_TYPE_P (tt0))
            {
              /* op0 != orig_op0 detects the case of something
                 whose value is 0 but which isn't a valid null ptr const.  */
-             if (pedantic && (!integer_zerop (op0) || op0 != orig_op0)
+             if (pedantic && !null_pointer_constant_p (orig_op0)
                  && TREE_CODE (tt1) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids comparison of %<void *%>"
                         " with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
-             if (pedantic && (!integer_zerop (op1) || op1 != orig_op1)
+             if (pedantic && !null_pointer_constant_p (orig_op1)
                  && TREE_CODE (tt0) == FUNCTION_TYPE)
                pedwarn ("ISO C forbids comparison of %<void *%>"
                         " with function pointer");
            }
          else
-           pedwarn ("comparison of distinct pointer types lacks a cast");
+           /* Avoid warning about the volatile ObjC EH puts on decls.  */
+           if (!objc_ok)
+             pedwarn ("comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
            result_type = ptr_type_node;
        }
-      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
-              && integer_zerop (op1))
-       result_type = type0;
-      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
-              && integer_zerop (op0))
-       result_type = type1;
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+       {
+         if (TREE_CODE (op0) == ADDR_EXPR
+             && DECL_P (TREE_OPERAND (op0, 0))
+             && (TREE_CODE (TREE_OPERAND (op0, 0)) == PARM_DECL
+                 || TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
+                 || !DECL_WEAK (TREE_OPERAND (op0, 0))))
+           warning (OPT_Walways_true, "the address of %qD will never be NULL",
+                    TREE_OPERAND (op0, 0));
+         result_type = type0;
+       }
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+       {
+         if (TREE_CODE (op1) == ADDR_EXPR
+             && DECL_P (TREE_OPERAND (op1, 0))
+             && (TREE_CODE (TREE_OPERAND (op1, 0)) == PARM_DECL
+                 || TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL
+                 || !DECL_WEAK (TREE_OPERAND (op1, 0))))
+           warning (OPT_Walways_true, "the address of %qD will never be NULL",
+                    TREE_OPERAND (op1, 0));
+         result_type = type1;
+       }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          result_type = type0;
@@ -7654,7 +8109,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (comp_target_types (type0, type1, 1))
+         if (comp_target_types (type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
              if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
@@ -7670,15 +8125,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
              pedwarn ("comparison of distinct pointer types lacks a cast");
            }
        }
-      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
-              && integer_zerop (op1))
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
          result_type = type0;
          if (pedantic || extra_warnings)
            pedwarn ("ordered comparison of pointer with integer zero");
        }
-      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
-              && integer_zerop (op0))
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
          if (pedantic)
@@ -7703,6 +8156,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     return error_mark_node;
 
+  if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+      && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
+         || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
+                                                   TREE_TYPE (type1))))
+    {
+      binary_op_error (code);
+      return error_mark_node;
+    }
+
   if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
        || code0 == VECTOR_TYPE)
       &&
@@ -7728,12 +8190,35 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
       if (shorten && none_complex)
        {
          int unsigned0, unsigned1;
-         tree arg0 = get_narrower (op0, &unsigned0);
-         tree arg1 = get_narrower (op1, &unsigned1);
-         /* UNS is 1 if the operation to be done is an unsigned one.  */
-         int uns = TYPE_UNSIGNED (result_type);
+         tree arg0, arg1;
+         int uns;
          tree type;
 
+         /* Cast OP0 and OP1 to RESULT_TYPE.  Doing so prevents
+            excessive narrowing when we call get_narrower below.  For
+            example, suppose that OP0 is of unsigned int extended
+            from signed char and that RESULT_TYPE is long long int.
+            If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
+            like
+
+              (long long int) (unsigned int) signed_char
+
+            which get_narrower would narrow down to
+
+              (unsigned int) signed char
+
+            If we do not cast OP0 first, get_narrower would return
+            signed_char, which is inconsistent with the case of the
+            explicit cast.  */
+         op0 = convert (result_type, op0);
+         op1 = convert (result_type, op1);
+
+         arg0 = get_narrower (op0, &unsigned0);
+         arg1 = get_narrower (op1, &unsigned1);
+
+         /* UNS is 1 if the operation to be done is an unsigned one.  */
+         uns = TYPE_UNSIGNED (result_type);
+
          final_type = result_type;
 
          /* Handle the case that OP0 (or OP1) does not *contain* a conversion
@@ -7770,7 +8255,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
              && (unsigned0 || !uns))
            result_type
              = c_common_signed_or_unsigned_type
-             (unsigned0, c_common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+             (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
          else if (TREE_CODE (arg0) == INTEGER_CST
                   && (unsigned1 || !uns)
                   && (TYPE_PRECISION (TREE_TYPE (arg1))
@@ -7866,9 +8351,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
                 all the values of the unsigned type.  */
              if (!TYPE_UNSIGNED (result_type))
                /* OK */;
-              /* Do not warn if both operands are the same signedness.  */
-              else if (op0_signed == op1_signed)
-                /* OK */;
+             /* Do not warn if both operands are the same signedness.  */
+             else if (op0_signed == op1_signed)
+               /* OK */;
              else
                {
                  tree sop, uop;
@@ -7978,9 +8463,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (!converted)
     {
       if (TREE_TYPE (op0) != result_type)
-       op0 = convert (result_type, op0);
+       op0 = convert_and_check (result_type, op0);
       if (TREE_TYPE (op1) != result_type)
-       op1 = convert (result_type, op1);
+       op1 = convert_and_check (result_type, op1);
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
@@ -7992,11 +8477,12 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
     build_type = result_type;
 
   {
-    tree result = build2 (resultcode, build_type, op0, op1);
-
     /* Treat expressions in initializers specially as they can't trap.  */
-    result = require_constant_value ? fold_initializer (result)
-                                   : fold (result);
+    tree result = require_constant_value ? fold_build2_initializer (resultcode,
+                                                                   build_type,
+                                                                   op0, op1)
+                                        : fold_build2 (resultcode, build_type,
+                                                       op0, op1);
 
     if (final_type != 0)
       result = convert (final_type, result);
@@ -8006,12 +8492,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
 
 
 /* Convert EXPR to be a truth-value, validating its type for this
-   purpose.  Passes EXPR to default_function_array_conversion.  */
+   purpose.  */
 
 tree
 c_objc_common_truthvalue_conversion (tree expr)
 {
-  expr = default_function_array_conversion (expr);
   switch (TREE_CODE (TREE_TYPE (expr)))
     {
     case ARRAY_TYPE:
@@ -8026,6 +8511,9 @@ c_objc_common_truthvalue_conversion (tree expr)
       error ("used union type value where scalar is required");
       return error_mark_node;
 
+    case FUNCTION_TYPE:
+      gcc_unreachable ();
+
     default:
       break;
     }
@@ -8034,3 +8522,268 @@ c_objc_common_truthvalue_conversion (tree expr)
      leaving those to give errors later?  */
   return c_common_truthvalue_conversion (expr);
 }
+\f
+
+/* Convert EXPR to a contained DECL, updating *TC, *TI and *SE as
+   required.  */
+
+tree
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
+               bool *ti ATTRIBUTE_UNUSED, bool *se)
+{
+  if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
+    {
+      tree decl = COMPOUND_LITERAL_EXPR_DECL (expr);
+      /* Executing a compound literal inside a function reinitializes
+        it.  */
+      if (!TREE_STATIC (decl))
+       *se = true;
+      return decl;
+    }
+  else
+    return expr;
+}
+\f
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK.  */
+
+tree
+c_begin_omp_parallel (void)
+{
+  tree block;
+
+  keep_next_level ();
+  block = c_begin_compound_stmt (true);
+
+  return block;
+}
+
+tree
+c_finish_omp_parallel (tree clauses, tree block)
+{
+  tree stmt;
+
+  block = c_end_compound_stmt (block, true);
+
+  stmt = make_node (OMP_PARALLEL);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_PARALLEL_CLAUSES (stmt) = clauses;
+  OMP_PARALLEL_BODY (stmt) = block;
+
+  return add_stmt (stmt);
+}
+
+/* For all elements of CLAUSES, validate them vs OpenMP constraints.
+   Remove any elements from the list that are invalid.  */
+
+tree
+c_finish_omp_clauses (tree clauses)
+{
+  bitmap_head generic_head, firstprivate_head, lastprivate_head;
+  tree c, t, *pc = &clauses;
+  const char *name;
+
+  bitmap_obstack_initialize (NULL);
+  bitmap_initialize (&generic_head, &bitmap_default_obstack);
+  bitmap_initialize (&firstprivate_head, &bitmap_default_obstack);
+  bitmap_initialize (&lastprivate_head, &bitmap_default_obstack);
+
+  for (pc = &clauses, c = clauses; c ; c = *pc)
+    {
+      bool remove = false;
+      bool need_complete = false;
+      bool need_implicitly_determined = false;
+
+      switch (OMP_CLAUSE_CODE (c))
+       {
+       case OMP_CLAUSE_SHARED:
+         name = "shared";
+         need_implicitly_determined = true;
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_PRIVATE:
+         name = "private";
+         need_complete = true;
+         need_implicitly_determined = true;
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_REDUCTION:
+         name = "reduction";
+         need_implicitly_determined = true;
+         t = OMP_CLAUSE_DECL (c);
+         if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+             || POINTER_TYPE_P (TREE_TYPE (t)))
+           {
+             error ("%qE has invalid type for %<reduction%>", t);
+             remove = true;
+           }
+         else if (FLOAT_TYPE_P (TREE_TYPE (t)))
+           {
+             enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
+             const char *r_name = NULL;
+
+             switch (r_code)
+               {
+               case PLUS_EXPR:
+               case MULT_EXPR:
+               case MINUS_EXPR:
+                 break;
+               case BIT_AND_EXPR:
+                 r_name = "&";
+                 break;
+               case BIT_XOR_EXPR:
+                 r_name = "^";
+                 break;
+               case BIT_IOR_EXPR:
+                 r_name = "|";
+                 break;
+               case TRUTH_ANDIF_EXPR:
+                 r_name = "&&";
+                 break;
+               case TRUTH_ORIF_EXPR:
+                 r_name = "||";
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             if (r_name)
+               {
+                 error ("%qE has invalid type for %<reduction(%s)%>",
+                        t, r_name);
+                 remove = true;
+               }
+           }
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_COPYPRIVATE:
+         name = "copyprivate";
+         goto check_dup_generic;
+
+       case OMP_CLAUSE_COPYIN:
+         name = "copyin";
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
+           {
+             error ("%qE must be %<threadprivate%> for %<copyin%>", t);
+             remove = true;
+           }
+         goto check_dup_generic;
+
+       check_dup_generic:
+         t = OMP_CLAUSE_DECL (c);
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error ("%qE is not a variable in clause %qs", t, name);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&generic_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_FIRSTPRIVATE:
+         name = "firstprivate";
+         t = OMP_CLAUSE_DECL (c);
+         need_complete = true;
+         need_implicitly_determined = true;
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error ("%qE is not a variable in clause %<firstprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&firstprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_LASTPRIVATE:
+         name = "lastprivate";
+         t = OMP_CLAUSE_DECL (c);
+         need_complete = true;
+         need_implicitly_determined = true;
+         if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+           {
+             error ("%qE is not a variable in clause %<lastprivate%>", t);
+             remove = true;
+           }
+         else if (bitmap_bit_p (&generic_head, DECL_UID (t))
+                  || bitmap_bit_p (&lastprivate_head, DECL_UID (t)))
+           {
+             error ("%qE appears more than once in data clauses", t);
+             remove = true;
+           }
+         else
+           bitmap_set_bit (&lastprivate_head, DECL_UID (t));
+         break;
+
+       case OMP_CLAUSE_IF:
+       case OMP_CLAUSE_NUM_THREADS:
+       case OMP_CLAUSE_SCHEDULE:
+       case OMP_CLAUSE_NOWAIT:
+       case OMP_CLAUSE_ORDERED:
+       case OMP_CLAUSE_DEFAULT:
+         pc = &OMP_CLAUSE_CHAIN (c);
+         continue;
+
+       default:
+         gcc_unreachable ();
+       }
+
+      if (!remove)
+       {
+         t = OMP_CLAUSE_DECL (c);
+
+         if (need_complete)
+           {
+             t = require_complete_type (t);
+             if (t == error_mark_node)
+               remove = true;
+           }
+
+         if (need_implicitly_determined)
+           {
+             const char *share_name = NULL;
+
+             if (TREE_CODE (t) == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+               share_name = "threadprivate";
+             else switch (c_omp_predetermined_sharing (t))
+               {
+               case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+                 break;
+               case OMP_CLAUSE_DEFAULT_SHARED:
+                 share_name = "shared";
+                 break;
+               case OMP_CLAUSE_DEFAULT_PRIVATE:
+                 share_name = "private";
+                 break;
+               default:
+                 gcc_unreachable ();
+               }
+             if (share_name)
+               {
+                 error ("%qE is predetermined %qs for %qs",
+                        t, share_name, name);
+                 remove = true;
+               }
+           }
+       }
+
+      if (remove)
+       *pc = OMP_CLAUSE_CHAIN (c);
+      else
+       pc = &OMP_CLAUSE_CHAIN (c);
+    }
+
+  bitmap_obstack_release (NULL);
+  return clauses;
+}