OSDN Git Service

PR c/42708
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index c6bb9f8..17bdbf9 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
+#include "c-lang.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "output.h"
@@ -70,9 +71,6 @@ int in_sizeof;
 /* The level of nesting inside "typeof".  */
 int in_typeof;
 
-struct c_label_context_se *label_context_stack_se;
-struct c_label_context_vm *label_context_stack_vm;
-
 /* Nonzero if we've already printed a "missing braces around initializer"
    message within this initializer.  */
 static int missing_braces_mentioned;
@@ -82,35 +80,36 @@ static int require_constant_elements;
 
 static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree);
-static int comp_target_types (tree, tree);
-static int function_types_compatible_p (const_tree, const_tree);
-static int type_lists_compatible_p (const_tree, const_tree);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *);
+static int comp_target_types (location_t, tree, tree);
+static int function_types_compatible_p (const_tree, const_tree, bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *);
 static tree lookup_field (tree, tree);
-static int convert_arguments (int, tree *, tree, tree, tree, tree);
-static tree pointer_diff (tree, tree);
-static tree convert_for_assignment (tree, tree, enum impl_conv, bool,
-                                   tree, tree, int);
+static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
+                             tree);
+static tree pointer_diff (location_t, tree, tree);
+static tree convert_for_assignment (location_t, tree, tree, tree,
+                                   enum impl_conv, bool, tree, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
 static void push_string (const char *);
 static void push_member_name (tree);
 static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (int, const char *);
-static tree digest_init (tree, tree, bool, bool, int);
-static void output_init_element (tree, bool, tree, tree, int, bool);
+static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
+static void output_init_element (tree, tree, bool, tree, tree, int, bool);
 static void output_pending_init_elements (int);
 static int set_designator (int);
 static void push_range_stack (tree);
-static void add_pending_init (tree, tree, bool);
+static void add_pending_init (tree, tree, tree, bool);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
 static void readonly_error (tree, enum lvalue_use);
+static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (const_tree, enum lvalue_use);
-static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree);
+static int comptypes_internal (const_tree, const_tree, bool *);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -285,14 +284,55 @@ c_type_promotes_to (tree type)
   return type;
 }
 
+/* Return true if between two named address spaces, whether there is a superset
+   named address space that encompasses both address spaces.  If there is a
+   superset, return which address space is the superset.  */
+
+static bool
+addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
+{
+  if (as1 == as2)
+    {
+      *common = as1;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as1, as2))
+    {
+      *common = as2;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as2, as1))
+    {
+      *common = as1;
+      return true;
+    }
+  else
+    return false;
+}
+
 /* Return a variant of TYPE which has all the type qualifiers of LIKE
    as well as those of TYPE.  */
 
 static tree
 qualify_type (tree type, tree like)
 {
+  addr_space_t as_type = TYPE_ADDR_SPACE (type);
+  addr_space_t as_like = TYPE_ADDR_SPACE (like);
+  addr_space_t as_common;
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  If there isn't one, raise an error.  */
+  if (!addr_space_superset (as_type, as_like, &as_common))
+    {
+      as_common = as_type;
+      error ("%qT and %qT are in disjoint named address spaces",
+            type, like);
+    }
+
   return c_build_qualified_type (type,
-                                TYPE_QUALS (type) | TYPE_QUALS (like));
+                                TYPE_QUALS_NO_ADDR_SPACE (type)
+                                | TYPE_QUALS_NO_ADDR_SPACE (like)
+                                | ENCODE_QUAL_ADDR_SPACE (as_common));
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -372,7 +412,8 @@ composite_type (tree t1, tree t2)
        bool t1_complete, t2_complete;
 
        /* We should not have any type quals on arrays at all.  */
-       gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
+       gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
+                   && !TYPE_QUALS_NO_ADDR_SPACE (t2));
 
        t1_complete = COMPLETE_TYPE_P (t1);
        t2_complete = COMPLETE_TYPE_P (t2);
@@ -525,7 +566,7 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p2));
-                       pedwarn (input_location, OPT_pedantic, 
+                       pedwarn (input_location, OPT_pedantic,
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -550,7 +591,7 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p1));
-                       pedwarn (input_location, OPT_pedantic, 
+                       pedwarn (input_location, OPT_pedantic,
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -586,6 +627,8 @@ common_pointer_type (tree t1, tree t2)
   tree pointed_to_2, mv2;
   tree target;
   unsigned target_quals;
+  addr_space_t as1, as2, as_common;
+  int quals1, quals2;
 
   /* Save time if the two types are the same.  */
 
@@ -617,10 +660,24 @@ common_pointer_type (tree t1, tree t2)
   /* For function types do not merge const qualifiers, but drop them
      if used inconsistently.  The middle-end uses these to mark const
      and noreturn functions.  */
+  quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
+  quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
+
   if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
-    target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+    target_quals = (quals1 & quals2);
   else
-    target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+    target_quals = (quals1 | quals2);
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  This is guaranteed to exist due to the
+     assumption that comp_target_type returned non-zero.  */
+  as1 = TYPE_ADDR_SPACE (pointed_to_1);
+  as2 = TYPE_ADDR_SPACE (pointed_to_2);
+  if (!addr_space_superset (as1, as2, &as_common))
+    gcc_unreachable ();
+
+  target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
+
   t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
@@ -918,7 +975,22 @@ 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);
+  val = comptypes_internal (type1, type2, NULL);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+
+/* Like comptypes, but if it returns non-zero because enum and int are
+   compatible, it sets *ENUM_AND_INT_P to true.  */
+
+static int
+comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
+{
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2, enum_and_int_p);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -926,11 +998,14 @@ comptypes (tree type1, tree type2)
 \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.  */
+   but a warning may be needed if you use them together.  If
+   ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
+   compatible integer type, then this sets *ENUM_AND_INT_P to true;
+   *ENUM_AND_INT_P is never set to false.  This differs from
+   comptypes, in that we don't free the seen types.  */
 
 static int
-comptypes_internal (const_tree type1, const_tree type2)
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
@@ -958,9 +1033,17 @@ comptypes_internal (const_tree type1, const_tree type2)
      are compatible with each other only if they are the same type.  */
 
   if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
-    t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
+    {
+      t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
+      if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE)
+       *enum_and_int_p = true;
+    }
   else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
-    t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
+    {
+      t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
+      if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
+       *enum_and_int_p = true;
+    }
 
   if (t1 == t2)
     return 1;
@@ -998,11 +1081,12 @@ comptypes_internal (const_tree type1, const_tree type2)
          || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)));
+            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+                                      enum_and_int_p));
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2);
+      val = function_types_compatible_p (t1, t2, enum_and_int_p);
       break;
 
     case ARRAY_TYPE:
@@ -1015,7 +1099,8 @@ comptypes_internal (const_tree type1, const_tree type2)
 
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
-           && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))))
+           && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+                                              enum_and_int_p)))
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
@@ -1059,14 +1144,15 @@ comptypes_internal (const_tree type1, const_tree type2)
            break;
 
          if (attrval != 2)
-           return tagged_types_tu_compatible_p (t1, t2);
-         val = tagged_types_tu_compatible_p (t1, t2);
+           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
        }
       break;
 
     case VECTOR_TYPE:
-      val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
-           && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2));
+      val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
+            && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+                                   enum_and_int_p));
       break;
 
     default:
@@ -1075,27 +1161,42 @@ comptypes_internal (const_tree type1, const_tree type2)
   return attrval == 2 && val == 1 ? 2 : val;
 }
 
-/* Return 1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers.  */
+/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
+   their qualifiers, except for named address spaces.  If the pointers point to
+   different named addresses, then we must determine if one address space is a
+   subset of the other.  */
 
 static int
-comp_target_types (tree ttl, tree ttr)
+comp_target_types (location_t location, tree ttl, tree ttr)
 {
   int val;
-  tree mvl, mvr;
+  tree mvl = TREE_TYPE (ttl);
+  tree mvr = TREE_TYPE (ttr);
+  addr_space_t asl = TYPE_ADDR_SPACE (mvl);
+  addr_space_t asr = TYPE_ADDR_SPACE (mvr);
+  addr_space_t as_common;
+  bool enum_and_int_p;
+
+  /* Fail if pointers point to incompatible address spaces.  */
+  if (!addr_space_superset (asl, asr, &as_common))
+    return 0;
 
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  mvl = TREE_TYPE (ttl);
-  mvr = TREE_TYPE (ttr);
   if (TREE_CODE (mvl) != ARRAY_TYPE)
     mvl = TYPE_MAIN_VARIANT (mvl);
   if (TREE_CODE (mvr) != ARRAY_TYPE)
     mvr = TYPE_MAIN_VARIANT (mvr);
-  val = comptypes (mvl, mvr);
+  enum_and_int_p = false;
+  val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
 
   if (val == 2)
-    pedwarn (input_location, OPT_pedantic, "types are not quite compatible");
+    pedwarn (location, OPT_pedantic, "types are not quite compatible");
+
+  if (val == 1 && enum_and_int_p && warn_cxx_compat)
+    warning_at (location, OPT_Wc___compat,
+               "pointer target types incompatible in C++");
+
   return val;
 }
 \f
@@ -1183,10 +1284,11 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
    compatible.  If the two types are not the same (which has been
    checked earlier), this can only happen when multiple translation
    units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
-   rules.  */
+   rules.  ENUM_AND_INT_P is as in comptypes_internal.  */
 
 static int
-tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
+tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
+                             bool *enum_and_int_p)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1296,7 +1398,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
 
            if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
+                                        enum_and_int_p);
 
            if (result != 1 && !DECL_NAME (s1))
              break;
@@ -1331,7 +1434,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
                {
                  int result;
 
-                 result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+                 result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
+                                              enum_and_int_p);
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
@@ -1373,7 +1477,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
+                                        enum_and_int_p);
            if (result == 0)
              break;
            if (result == 2)
@@ -1401,10 +1506,12 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2)
    the other must specify a fixed number of self-promoting arg types.
    Otherwise, if one type specifies only the number of arguments,
    the other must specify that number of self-promoting arg types.
-   Otherwise, the argument types must match.  */
+   Otherwise, the argument types must match.
+   ENUM_AND_INT_P is as in comptypes_internal.  */
 
 static int
-function_types_compatible_p (const_tree f1, const_tree f2)
+function_types_compatible_p (const_tree f1, const_tree f2,
+                            bool *enum_and_int_p)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1425,7 +1532,7 @@ function_types_compatible_p (const_tree f1, const_tree f2)
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes_internal (ret1, ret2);
+  val = comptypes_internal (ret1, ret2, enum_and_int_p);
   if (val == 0)
     return 0;
 
@@ -1443,7 +1550,8 @@ function_types_compatible_p (const_tree f1, const_tree f2)
         compare that with the other type's arglist.
         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)))
+         && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
+                                          enum_and_int_p))
        val = 2;
       return val;
     }
@@ -1452,22 +1560,24 @@ function_types_compatible_p (const_tree f1, const_tree f2)
       if (!self_promoting_args_p (args1))
        return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
-         && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2)))
+         && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
+                                          enum_and_int_p))
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2);
+  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p);
   return val1 != 1 ? val1 : val;
 }
 
-/* Check two lists of types for compatibility,
-   returning 0 for incompatible, 1 for compatible,
-   or 2 for compatible with warning.  */
+/* Check two lists of types for compatibility, returning 0 for
+   incompatible, 1 for compatible, or 2 for compatible with
+   warning.  ENUM_AND_INT_P is as in comptypes_internal.  */
 
 static int
-type_lists_compatible_p (const_tree args1, const_tree args2)
+type_lists_compatible_p (const_tree args1, const_tree args2,
+                        bool *enum_and_int_p)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1506,7 +1616,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2)
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
-      else if (!(newval = comptypes_internal (mv1, mv2)))
+      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p)))
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
@@ -1525,7 +1635,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2)
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv2))
+                 if (comptypes_internal (mv3, mv2, enum_and_int_p))
                    break;
                }
              if (memb == 0)
@@ -1546,7 +1656,7 @@ type_lists_compatible_p (const_tree args1, const_tree args2)
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv1))
+                 if (comptypes_internal (mv3, mv1, enum_and_int_p))
                    break;
                }
              if (memb == 0)
@@ -1582,9 +1692,9 @@ c_size_in_bytes (const_tree type)
     }
 
   /* Convert in case a char is more than one unit.  */
-  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                    size_int (TYPE_PRECISION (char_type_node)
-                              / BITS_PER_UNIT));
+  return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                        size_int (TYPE_PRECISION (char_type_node)
+                                  / BITS_PER_UNIT));
 }
 \f
 /* Return either DECL or its known constant value (if it has one).  */
@@ -1613,7 +1723,7 @@ decl_constant_value (tree decl)
 
 /* Convert the array expression EXP to a pointer.  */
 static tree
-array_to_pointer_conversion (tree exp)
+array_to_pointer_conversion (location_t loc, tree exp)
 {
   tree orig_exp = exp;
   tree type = TREE_TYPE (exp);
@@ -1633,28 +1743,13 @@ array_to_pointer_conversion (tree exp)
   if (TREE_CODE (exp) == INDIRECT_REF)
     return convert (ptrtype, TREE_OPERAND (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 (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1);
+  adr = build_unary_op (loc, ADDR_EXPR, exp, 1);
   return convert (ptrtype, adr);
 }
 
 /* Convert the function expression EXP to a pointer.  */
 static tree
-function_to_pointer_conversion (tree exp)
+function_to_pointer_conversion (location_t loc, tree exp)
 {
   tree orig_exp = exp;
 
@@ -1665,15 +1760,17 @@ function_to_pointer_conversion (tree exp)
   if (TREE_NO_WARNING (orig_exp))
     TREE_NO_WARNING (exp) = 1;
 
-  return build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 0);
+  return build_unary_op (loc, ADDR_EXPR, exp, 0);
 }
 
 /* Perform the default conversion of arrays and functions to pointers.
    Return the result of converting EXP.  For any other expression, just
-   return EXP.  */
+   return EXP.
+
+   LOC is the location of the expression.  */
 
 struct c_expr
-default_function_array_conversion (struct c_expr exp)
+default_function_array_conversion (location_t loc, struct c_expr exp)
 {
   tree orig_exp = exp.value;
   tree type = TREE_TYPE (exp.value);
@@ -1708,11 +1805,11 @@ default_function_array_conversion (struct c_expr exp)
            return exp;
          }
 
-       exp.value = array_to_pointer_conversion (exp.value);
+       exp.value = array_to_pointer_conversion (loc, exp.value);
       }
       break;
     case FUNCTION_TYPE:
-      exp.value = function_to_pointer_conversion (exp.value);
+      exp.value = function_to_pointer_conversion (loc, exp.value);
       break;
     default:
       break;
@@ -1780,6 +1877,7 @@ default_conversion (tree exp)
   tree orig_exp;
   tree type = TREE_TYPE (exp);
   enum tree_code code = TREE_CODE (type);
+  tree promoted_type;
 
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
@@ -1807,6 +1905,10 @@ default_conversion (tree exp)
   if (exp == error_mark_node)
     return error_mark_node;
 
+  promoted_type = targetm.promoted_type (type);
+  if (promoted_type)
+    return convert (promoted_type, exp);
+
   if (INTEGRAL_TYPE_P (type))
     return perform_integral_promotions (exp);
 
@@ -1908,11 +2010,12 @@ lookup_field (tree decl, tree component)
   return tree_cons (NULL_TREE, field, NULL_TREE);
 }
 
-/* Make an expression to refer to the COMPONENT field of
-   structure or union value DATUM.  COMPONENT is an IDENTIFIER_NODE.  */
+/* Make an expression to refer to the COMPONENT field of structure or
+   union value DATUM.  COMPONENT is an IDENTIFIER_NODE.  LOC is the
+   location of the COMPONENT_REF.  */
 
 tree
-build_component_ref (tree datum, tree component)
+build_component_ref (location_t loc, tree datum, tree component)
 {
   tree type = TREE_TYPE (datum);
   enum tree_code code = TREE_CODE (type);
@@ -1937,7 +2040,7 @@ build_component_ref (tree datum, tree component)
 
       if (!field)
        {
-         error ("%qT has no member named %qE", type, component);
+         error_at (loc, "%qT has no member named %qE", type, component);
          return error_mark_node;
        }
 
@@ -1970,6 +2073,7 @@ build_component_ref (tree datum, tree component)
 
          ref = build3 (COMPONENT_REF, subtype, datum, subdatum,
                        NULL_TREE);
+         SET_EXPR_LOCATION (ref, loc);
          if (TREE_READONLY (subdatum)
              || (use_datum_quals && TREE_READONLY (datum)))
            TREE_READONLY (ref) = 1;
@@ -1978,7 +2082,7 @@ build_component_ref (tree datum, tree component)
            TREE_THIS_VOLATILE (ref) = 1;
 
          if (TREE_DEPRECATED (subdatum))
-           warn_deprecated_use (subdatum);
+           warn_deprecated_use (subdatum, NULL_TREE);
 
          datum = ref;
 
@@ -1989,8 +2093,9 @@ build_component_ref (tree datum, tree component)
       return ref;
     }
   else if (code != ERROR_MARK)
-    error ("request for member %qE in something not a structure or union",
-          component);
+    error_at (loc,
+             "request for member %qE in something not a structure or union",
+             component);
 
   return error_mark_node;
 }
@@ -2002,7 +2107,7 @@ build_component_ref (tree datum, tree component)
    LOC is the location to use for the generated tree.  */
 
 tree
-build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
+build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
 {
   tree pointer = default_conversion (ptr);
   tree type = TREE_TYPE (pointer);
@@ -2041,7 +2146,7 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
              error_at (loc, "dereferencing pointer to incomplete type");
              return error_mark_node;
            }
-         if (VOID_TYPE_P (t) && skip_evaluation == 0)
+         if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0)
            warning_at (loc, 0, "dereferencing %<void *%> pointer");
 
          /* We *must* set TREE_READONLY when dereferencing a pointer to const,
@@ -2060,8 +2165,26 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error_at (loc,
-             "invalid type argument of %qs (have %qT)", errorstring, type);
+    switch (errstring)
+      {
+         case RO_ARRAY_INDEXING:
+           error_at (loc,
+                     "invalid type argument of array indexing (have %qT)",
+                     type);
+           break;
+         case RO_UNARY_STAR:
+           error_at (loc,
+                     "invalid type argument of unary %<*%> (have %qT)",
+                     type);
+           break;
+         case RO_ARROW:
+           error_at (loc,
+                     "invalid type argument of %<->%> (have %qT)",
+                     type);
+           break;
+         default:
+           gcc_unreachable ();
+      }
   return error_mark_node;
 }
 
@@ -2077,7 +2200,7 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
    LOC is the location to use for the returned expression.  */
 
 tree
-build_array_ref (tree array, tree index, location_t loc)
+build_array_ref (location_t loc, tree array, tree index)
 {
   tree ret;
   bool swapped = false;
@@ -2156,10 +2279,10 @@ build_array_ref (tree array, tree index, location_t loc)
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
-           pedwarn (loc, OPT_pedantic, 
+           pedwarn (loc, OPT_pedantic,
                     "ISO C forbids subscripting %<register%> array");
          else if (!flag_isoc99 && !lvalue_p (foo))
-           pedwarn (loc, OPT_pedantic, 
+           pedwarn (loc, OPT_pedantic,
                     "ISO C90 forbids subscripting non-lvalue array");
        }
 
@@ -2196,7 +2319,7 @@ build_array_ref (tree array, tree index, location_t loc)
 
       return build_indirect_ref
        (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
-        "array indexing");
+        RO_ARRAY_INDEXING);
     }
 }
 \f
@@ -2207,7 +2330,7 @@ build_array_ref (tree array, tree index, location_t loc)
    for CONST_DECLs defined as enum constants.  If the type of the
    identifier is not available, *TYPE is set to NULL.  */
 tree
-build_external_ref (tree id, int fun, location_t loc, tree *type)
+build_external_ref (location_t loc, tree id, int fun, tree *type)
 {
   tree ref;
   tree decl = lookup_name (id);
@@ -2224,14 +2347,14 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
     }
   else if (fun)
     /* Implicit function declaration.  */
-    ref = implicitly_declare (id);
+    ref = implicitly_declare (loc, id);
   else if (decl == error_mark_node)
     /* Don't complain about something that's already been
        complained about.  */
     return error_mark_node;
   else
     {
-      undeclared_variable (id, loc);
+      undeclared_variable (loc, id);
       return error_mark_node;
     }
 
@@ -2239,10 +2362,10 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
     return error_mark_node;
 
   if (TREE_DEPRECATED (ref))
-    warn_deprecated_use (ref);
+    warn_deprecated_use (ref, NULL_TREE);
 
   /* Recursive call does not count as usage.  */
-  if (ref != current_function_decl) 
+  if (ref != current_function_decl)
     {
       TREE_USED (ref) = 1;
     }
@@ -2260,6 +2383,17 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
   if (TREE_CODE (ref) == CONST_DECL)
     {
       used_types_insert (TREE_TYPE (ref));
+
+      if (warn_cxx_compat
+         && TREE_CODE (TREE_TYPE (ref)) == ENUMERAL_TYPE
+         && C_TYPE_DEFINED_IN_STRUCT (TREE_TYPE (ref)))
+       {
+         warning_at (loc, OPT_Wc___compat,
+                     ("enum constant defined in struct or union "
+                      "is not visible in C++"));
+         inform (DECL_SOURCE_LOCATION (ref), "enum constant defined here");
+       }
+
       ref = DECL_INITIAL (ref);
       TREE_CONSTANT (ref) = 1;
     }
@@ -2284,8 +2418,8 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
           && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
           && ! TREE_PUBLIC (ref)
           && DECL_CONTEXT (ref) != current_function_decl)
-    pedwarn (loc, 0, "%qD is static but used in inline function %qD "
-            "which is not static", ref, current_function_decl);
+    record_inline_static (loc, current_function_decl, ref,
+                         csi_internal);
 
   return ref;
 }
@@ -2346,7 +2480,7 @@ pop_maybe_used (bool used)
 /* Return the result of sizeof applied to EXPR.  */
 
 struct c_expr
-c_expr_sizeof_expr (struct c_expr expr)
+c_expr_sizeof_expr (location_t loc, struct c_expr expr)
 {
   struct c_expr ret;
   if (expr.value == error_mark_node)
@@ -2361,7 +2495,7 @@ c_expr_sizeof_expr (struct c_expr expr)
       bool expr_const_operands = true;
       tree folded_expr = c_fully_fold (expr.value, require_constant_value,
                                       &expr_const_operands);
-      ret.value = c_sizeof (TREE_TYPE (folded_expr));
+      ret.value = c_sizeof (loc, TREE_TYPE (folded_expr));
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
       if (c_vla_type_p (TREE_TYPE (folded_expr)))
@@ -2370,6 +2504,7 @@ c_expr_sizeof_expr (struct c_expr expr)
          ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
                              folded_expr, ret.value);
          C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !expr_const_operands;
+         SET_EXPR_LOCATION (ret.value, loc);
        }
       pop_maybe_used (C_TYPE_VARIABLE_SIZE (TREE_TYPE (folded_expr)));
     }
@@ -2377,21 +2512,32 @@ c_expr_sizeof_expr (struct c_expr expr)
 }
 
 /* Return the result of sizeof applied to T, a structure for the type
-   name passed to sizeof (rather than the type itself).  */
+   name passed to sizeof (rather than the type itself).  LOC is the
+   location of the original expression.  */
 
 struct c_expr
-c_expr_sizeof_type (struct c_type_name *t)
+c_expr_sizeof_type (location_t loc, struct c_type_name *t)
 {
   tree type;
   struct c_expr ret;
   tree type_expr = NULL_TREE;
   bool type_expr_const = true;
   type = groktypename (t, &type_expr, &type_expr_const);
-  ret.value = c_sizeof (type);
+  ret.value = c_sizeof (loc, type);
   ret.original_code = ERROR_MARK;
   ret.original_type = NULL;
-  if (type_expr && c_vla_type_p (type))
-    {
+  if ((type_expr || TREE_CODE (ret.value) == INTEGER_CST)
+      && c_vla_type_p (type))
+    {
+      /* If the type is a [*] array, it is a VLA but is represented as
+        having a size of zero.  In such a case we must ensure that
+        the result of sizeof does not get folded to a constant by
+        c_fully_fold, because if the size is evaluated the result is
+        not constant and so constraints on zero or negative size
+        arrays must not be applied when this sizeof call is inside
+        another array declarator.  */
+      if (!type_expr)
+       type_expr = integer_zero_node;
       ret.value = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret.value),
                          type_expr, ret.value);
       C_MAYBE_CONST_EXPR_NON_CONST (ret.value) = !type_expr_const;
@@ -2402,19 +2548,43 @@ c_expr_sizeof_type (struct c_type_name *t)
 }
 
 /* Build a function call to function FUNCTION with parameters PARAMS.
+   The function call is at LOC.
    PARAMS is a list--a chain of TREE_LIST nodes--in which the
    TREE_VALUE of each node is a parameter-expression.
    FUNCTION's data type may be a function type or a pointer-to-function.  */
 
 tree
-build_function_call (tree function, tree params)
+build_function_call (location_t loc, tree function, tree params)
+{
+  VEC(tree,gc) *vec;
+  tree ret;
+
+  vec = VEC_alloc (tree, gc, list_length (params));
+  for (; params; params = TREE_CHAIN (params))
+    VEC_quick_push (tree, vec, TREE_VALUE (params));
+  ret = build_function_call_vec (loc, function, vec, NULL);
+  VEC_free (tree, gc, vec);
+  return ret;
+}
+
+/* Build a function call to function FUNCTION with parameters PARAMS.
+   ORIGTYPES, if not NULL, is a vector of types; each element is
+   either NULL or the original type of the corresponding element in
+   PARAMS.  The original type may differ from TREE_TYPE of the
+   parameter for enums.  FUNCTION's data type may be a function type
+   or pointer-to-function.  This function changes the elements of
+   PARAMS.  */
+
+tree
+build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
+                        VEC(tree,gc) *origtypes)
 {
   tree fntype, fundecl = 0;
   tree name = NULL_TREE, result;
   tree tem;
   int nargs;
   tree *argarray;
-  
+
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -2426,7 +2596,7 @@ build_function_call (tree function, tree params)
         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);
+      tem = resolve_overloaded_builtin (loc, function, params);
       if (tem)
        return tem;
 
@@ -2434,11 +2604,13 @@ build_function_call (tree function, tree params)
       fundecl = function;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
-    function = function_to_pointer_conversion (function);
+    function = function_to_pointer_conversion (loc, 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);
+  if (!VEC_empty (tree, params))
+    function = objc_rewrite_function_call (function,
+                                          VEC_index (tree, params, 0));
 
   function = c_fully_fold (function, false, NULL);
 
@@ -2450,7 +2622,7 @@ build_function_call (tree function, tree params)
   if (!(TREE_CODE (fntype) == POINTER_TYPE
        && TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE))
     {
-      error ("called object %qE is not a function", function);
+      error_at (loc, "called object %qE is not a function", function);
       return error_mark_node;
     }
 
@@ -2463,10 +2635,8 @@ build_function_call (tree function, tree params)
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  nargs = list_length (params);
-  argarray = (tree *) alloca (nargs * sizeof (tree));
-  nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype), 
-                            params, function, fundecl);
+  nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes,
+                            function, fundecl);
   if (nargs < 0)
     return error_mark_node;
 
@@ -2481,39 +2651,48 @@ build_function_call (tree function, tree params)
       && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
+      tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP],
                                       NULL_TREE);
       int i;
 
       /* This situation leads to run-time undefined behavior.  We can't,
         therefore, simply error unless we can prove that all possible
         executions of the program must execute the code.  */
-      if (warning (0, "function called through a non-compatible type"))
+      if (warning_at (loc, 0, "function called through a non-compatible type"))
        /* We can, however, treat "undefined" any way we please.
           Call abort to encourage the user to fix the program.  */
-       inform (input_location, "if this code is reached, the program will abort");
+       inform (loc, "if this code is reached, the program will abort");
       /* Before the abort, allow the function arguments to exit or
         call longjmp.  */
       for (i = 0; i < nargs; i++)
-       trap = build2 (COMPOUND_EXPR, void_type_node, argarray[i], trap);
+       trap = build2 (COMPOUND_EXPR, void_type_node,
+                      VEC_index (tree, params, i), trap);
 
       if (VOID_TYPE_P (return_type))
-       return trap;
+       {
+         if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
+           pedwarn (loc, 0,
+                    "function with qualified void return type called");
+         return trap;
+       }
       else
        {
          tree rhs;
 
          if (AGGREGATE_TYPE_P (return_type))
-           rhs = build_compound_literal (return_type,
+           rhs = build_compound_literal (loc, return_type,
                                          build_constructor (return_type, 0),
                                          false);
          else
-           rhs = fold_convert (return_type, integer_zero_node);
+           rhs = fold_convert_loc (loc, return_type, integer_zero_node);
 
-         return build2 (COMPOUND_EXPR, return_type, trap, rhs);
+         return require_complete_type (build2 (COMPOUND_EXPR, return_type,
+                                               trap, rhs));
        }
     }
 
+  argarray = VEC_address (tree, params);
+
   /* Check that arguments to builtin functions match the expectations.  */
   if (fundecl
       && DECL_BUILT_IN (fundecl)
@@ -2529,52 +2708,56 @@ build_function_call (tree function, tree params)
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
     {
       if (require_constant_value)
-       result = fold_build_call_array_initializer (TREE_TYPE (fntype),
-                                                   function, nargs, argarray);
+       result =
+         fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
+                                                function, nargs, argarray);
       else
-       result = fold_build_call_array (TREE_TYPE (fntype),
-                                       function, nargs, argarray);
+       result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
+                                           function, nargs, argarray);
       if (TREE_CODE (result) == NOP_EXPR
          && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST)
        STRIP_TYPE_NOPS (result);
     }
   else
-    result = build_call_array (TREE_TYPE (fntype),
-                              function, nargs, argarray);
+    result = build_call_array_loc (loc, TREE_TYPE (fntype),
+                                  function, nargs, argarray);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
-    return result;
+    {
+      if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
+       pedwarn (loc, 0,
+                "function with qualified void return type called");
+      return result;
+    }
   return require_complete_type (result);
 }
 \f
-/* Convert the argument expressions in the list VALUES
-   to the types in the list TYPELIST.  The resulting arguments are
-   stored in the array ARGARRAY which has size NARGS.
+/* Convert the argument expressions in the vector VALUES
+   to the types in the list TYPELIST.
 
    If TYPELIST is exhausted, or when an element has NULL as its type,
    perform the default conversions.
 
-   PARMLIST is the chain of parm decls for the function being called.
-   It may be 0, if that info is not available.
-   It is used only for generating error messages.
+   ORIGTYPES is the original types of the expressions in VALUES.  This
+   holds the type of enum values which have been converted to integral
+   types.  It may be NULL.
 
    FUNCTION is a tree for the called function.  It is used only for
    error messages, where it is formatted with %qE.
 
    This is also where warnings about wrong number of args are generated.
 
-   VALUES is a chain of TREE_LIST nodes with the elements of the list
-   in the TREE_VALUE slots of those nodes.
-
    Returns the actual number of arguments processed (which may be less
-   than NARGS in some error situations), or -1 on failure.  */
+   than the length of VALUES in some error situations), or -1 on
+   failure.  */
 
 static int
-convert_arguments (int nargs, tree *argarray,
-                  tree typelist, tree values, tree function, tree fundecl)
+convert_arguments (tree typelist, VEC(tree,gc) *values,
+                  VEC(tree,gc) *origtypes, tree function, tree fundecl)
 {
-  tree typetail, valtail;
-  int parmnum;
+  tree typetail, val;
+  unsigned int parmnum;
+  bool error_args = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
@@ -2614,20 +2797,20 @@ convert_arguments (int nargs, tree *argarray,
     }
 
   /* Scan the given expressions and types, producing individual
-     converted arguments and storing them in ARGARRAY.  */
+     converted arguments.  */
 
-  for (valtail = values, typetail = typelist, parmnum = 0;
-       valtail;
-       valtail = TREE_CHAIN (valtail), parmnum++)
+  for (typetail = typelist, parmnum = 0;
+       VEC_iterate (tree, values, parmnum, val);
+       ++parmnum)
     {
       tree type = typetail ? TREE_VALUE (typetail) : 0;
-      tree val = TREE_VALUE (valtail);
       tree valtype = TREE_TYPE (val);
       tree rname = function;
       int argnum = parmnum + 1;
       const char *invalid_func_diag;
       bool excess_precision = false;
       bool npc;
+      tree parmval;
 
       if (type == void_type_node)
        {
@@ -2663,7 +2846,6 @@ convert_arguments (int nargs, tree *argarray,
       if (type != 0)
        {
          /* Formal parm type is specified by a function prototype.  */
-         tree parmval;
 
          if (type == error_mark_node || !COMPLETE_TYPE_P (type))
            {
@@ -2672,6 +2854,8 @@ convert_arguments (int nargs, tree *argarray,
            }
          else
            {
+             tree origtype;
+
              /* Optionally warn about conversions that
                 differ from the default conversions.  */
              if (warn_traditional_conversion || warn_traditional)
@@ -2764,7 +2948,8 @@ convert_arguments (int nargs, tree *argarray,
                           and the actual arg is that enum type.  */
                        ;
                      else if (formal_prec != TYPE_PRECISION (type1))
-                       warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
+                       warning (OPT_Wtraditional_conversion,
+                                "passing argument %d of %qE "
                                 "with different width due to prototype",
                                 argnum, rname);
                      else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
@@ -2787,11 +2972,13 @@ convert_arguments (int nargs, tree *argarray,
                               && TYPE_UNSIGNED (valtype))
                        ;
                      else if (TYPE_UNSIGNED (type))
-                       warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
+                       warning (OPT_Wtraditional_conversion,
+                                "passing argument %d of %qE "
                                 "as unsigned due to prototype",
                                 argnum, rname);
                      else
-                       warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
+                       warning (OPT_Wtraditional_conversion,
+                                "passing argument %d of %qE "
                                 "as signed due to prototype", argnum, rname);
                    }
                }
@@ -2800,7 +2987,11 @@ convert_arguments (int nargs, tree *argarray,
                 sake of better warnings from convert_and_check.  */
              if (excess_precision)
                val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
-             parmval = convert_for_assignment (type, val, ic_argpass, npc,
+             origtype = (origtypes == NULL
+                         ? NULL_TREE
+                         : VEC_index (tree, origtypes, parmnum));
+             parmval = convert_for_assignment (input_location, type, val,
+                                               origtype, ic_argpass, npc,
                                                fundecl, function,
                                                parmnum + 1);
 
@@ -2809,7 +3000,6 @@ convert_arguments (int nargs, tree *argarray,
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
-         argarray[parmnum] = parmval;
        }
       else if (TREE_CODE (valtype) == REAL_TYPE
               && (TYPE_PRECISION (valtype)
@@ -2817,15 +3007,15 @@ convert_arguments (int nargs, tree *argarray,
               && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
         {
          if (type_generic)
-           argarray[parmnum] = val;
+           parmval = val;
          else
            /* Convert `float' to `double'.  */
-           argarray[parmnum] = convert (double_type_node, val);
+           parmval = convert (double_type_node, val);
        }
       else if (excess_precision && !type_generic)
        /* A "double" argument with excess precision being passed
           without a prototype or in variable arguments.  */
-       argarray[parmnum] = convert (valtype, val);
+       parmval = convert (valtype, val);
       else if ((invalid_func_diag =
                targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
        {
@@ -2834,13 +3024,17 @@ convert_arguments (int nargs, tree *argarray,
        }
       else
        /* Convert `short' and `char' to full-size `int'.  */
-       argarray[parmnum] = default_conversion (val);
+       parmval = default_conversion (val);
+
+      VEC_replace (tree, values, parmnum, parmval);
+      if (parmval == error_mark_node)
+       error_args = true;
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
     }
 
-  gcc_assert (parmnum == nargs);
+  gcc_assert (parmnum == VEC_length (tree, values));
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
@@ -2848,7 +3042,7 @@ convert_arguments (int nargs, tree *argarray,
       return -1;
     }
 
-  return parmnum;
+  return error_args ? -1 : (int) parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
@@ -2860,7 +3054,7 @@ convert_arguments (int nargs, tree *argarray,
 */
 
 struct c_expr
-parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc)
+parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
 {
   struct c_expr result;
 
@@ -2869,7 +3063,7 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc)
   result.original_type = NULL;
 
   if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
-    overflow_warning (result.value);
+    overflow_warning (loc, result.value);
 
   return result;
 }
@@ -2913,8 +3107,9 @@ parser_build_binary_op (location_t location, enum tree_code code,
   if (warn_parentheses)
     warn_about_parentheses (code, code1, arg1.value, code2, arg2.value);
 
-  if (TREE_CODE_CLASS (code1) != tcc_comparison)
-    warn_logical_operator (code, arg1.value, arg2.value);
+  if (warn_logical_op)
+    warn_logical_operator (input_location, code, TREE_TYPE (result.value),
+                          code1, arg1.value, code2, arg2.value);
 
   /* Warn about comparisons against string literals, with the exception
      of testing for equality or inequality of a string literal with NULL.  */
@@ -2922,16 +3117,18 @@ parser_build_binary_op (location_t location, enum tree_code code,
     {
       if ((code1 == STRING_CST && !integer_zerop (arg2.value))
          || (code2 == STRING_CST && !integer_zerop (arg1.value)))
-       warning (OPT_Waddress, "comparison with string literal results in unspecified behavior");
+       warning_at (location, OPT_Waddress,
+                   "comparison with string literal results in unspecified behavior");
     }
   else if (TREE_CODE_CLASS (code) == tcc_comparison
           && (code1 == STRING_CST || code2 == STRING_CST))
-    warning (OPT_Waddress, "comparison with string literal results in unspecified behavior");
+    warning_at (location, OPT_Waddress,
+               "comparison with string literal results in unspecified behavior");
 
-  if (TREE_OVERFLOW_P (result.value) 
-      && !TREE_OVERFLOW_P (arg1.value) 
+  if (TREE_OVERFLOW_P (result.value)
+      && !TREE_OVERFLOW_P (arg1.value)
       && !TREE_OVERFLOW_P (arg2.value))
-    overflow_warning (result.value);
+    overflow_warning (location, result.value);
 
   /* Warn about comparisons of different enum types.  */
   if (warn_enum_compare
@@ -2950,19 +3147,51 @@ parser_build_binary_op (location_t location, enum tree_code code,
    The resulting tree has type int.  */
 
 static tree
-pointer_diff (tree op0, tree op1)
+pointer_diff (location_t loc, tree op0, tree op1)
 {
   tree restype = ptrdiff_type_node;
+  tree result, inttype;
 
+  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
+  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
   tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
+  /* If the operands point into different address spaces, we need to
+     explicitly convert them to pointers into the common address space
+     before we can subtract the numerical address values.  */
+  if (as0 != as1)
+    {
+      addr_space_t as_common;
+      tree common_type;
+
+      /* Determine the common superset address space.  This is guaranteed
+        to exist because the caller verified that comp_target_types
+        returned non-zero.  */
+      if (!addr_space_superset (as0, as1, &as_common))
+       gcc_unreachable ();
+
+      common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+      op0 = convert (common_type, op0);
+      op1 = convert (common_type, op1);
+    }
+
+  /* Determine integer type to perform computations in.  This will usually
+     be the same as the result type (ptrdiff_t), but may need to be a wider
+     type if pointers for the address space are wider than ptrdiff_t.  */
+  if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0)))
+    inttype = lang_hooks.types.type_for_size
+               (TYPE_PRECISION (TREE_TYPE (op0)), 0);
+  else
+    inttype = restype;
+
+
   if (TREE_CODE (target_type) == VOID_TYPE)
-    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
             "pointer of type %<void *%> used in subtraction");
   if (TREE_CODE (target_type) == FUNCTION_TYPE)
-    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
             "pointer to a function used in subtraction");
 
   /* If the conversion to ptrdiff_type does anything like widening or
@@ -3014,18 +3243,22 @@ pointer_diff (tree op0, tree op1)
      Do not do default conversions on the minus operator
      in case restype is a short type.  */
 
-  op0 = build_binary_op (input_location,
-                        MINUS_EXPR, convert (restype, op0),
-                        convert (restype, op1), 0);
+  op0 = build_binary_op (loc,
+                        MINUS_EXPR, convert (inttype, op0),
+                        convert (inttype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
-    error ("arithmetic on pointer to an incomplete type");
+    error_at (loc, "arithmetic on pointer to an incomplete type");
 
   /* This generates an error if op0 is pointer to incomplete type.  */
   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));
+  result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
+                           op0, convert (inttype, op1));
+
+  /* Convert to final result type if necessary.  */
+  return convert (restype, result);
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3095,7 +3328,7 @@ build_unary_op (location_t location,
        }
       else if (!noconvert)
        arg = default_conversion (arg);
-      arg = non_lvalue (arg);
+      arg = non_lvalue_loc (location, arg);
       break;
 
     case NEGATE_EXPR:
@@ -3122,7 +3355,7 @@ build_unary_op (location_t location,
       else if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
@@ -3166,14 +3399,18 @@ build_unary_op (location_t location,
          return error_mark_node;
        }
       arg = c_objc_common_truthvalue_conversion (location, arg);
-      ret = invert_truthvalue (arg);
+      ret = invert_truthvalue_loc (location, arg);
+      /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
+      if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
+       location = EXPR_LOCATION (ret);
       goto return_build_unary_op;
 
     case REALPART_EXPR:
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1_loc (location,
+                              REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        ret = arg;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
@@ -3184,9 +3421,11 @@ build_unary_op (location_t location,
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1_loc (location,
+                              IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
-       ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg);
+       ret = omit_one_operand_loc (location, TREE_TYPE (arg),
+                               integer_zero_node, arg);
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3216,6 +3455,16 @@ build_unary_op (location_t location,
                                 : lv_decrement)))
        return error_mark_node;
 
+      if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
+       {
+         if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+           warning_at (location, OPT_Wc___compat,
+                       "increment of enumeration value is invalid in C++");
+         else
+           warning_at (location, OPT_Wc___compat,
+                       "decrement of enumeration value is invalid in C++");
+       }
+
       /* Ensure the argument is fully folded inside any SAVE_EXPR.  */
       arg = c_fully_fold (arg, false, NULL);
 
@@ -3225,7 +3474,7 @@ build_unary_op (location_t location,
        {
          tree real, imag;
 
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
@@ -3276,15 +3525,15 @@ build_unary_op (location_t location,
                     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
                           "wrong type argument to increment");
                else
-                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
                           "wrong type argument to decrement");
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = fold_convert (sizetype, inc);
+           inc = fold_convert_loc (location, sizetype, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3312,7 +3561,7 @@ build_unary_op (location_t location,
          }
 
        /* Report a read-only lvalue.  */
-       if (TREE_READONLY (arg))
+       if (TYPE_READONLY (argtype))
          {
            readonly_error (arg,
                            ((code == PREINCREMENT_EXPR
@@ -3320,6 +3569,11 @@ build_unary_op (location_t location,
                             ? lv_increment : lv_decrement));
            return error_mark_node;
          }
+       else if (TREE_READONLY (arg))
+         readonly_warning (arg,
+                           ((code == PREINCREMENT_EXPR
+                             || code == POSTINCREMENT_EXPR)
+                            ? lv_increment : lv_decrement));
 
        if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
          val = boolean_increment (code, arg);
@@ -3335,12 +3589,21 @@ build_unary_op (location_t location,
     case ADDR_EXPR:
       /* Note that this operation never does default_conversion.  */
 
+      /* The operand of unary '&' must be an lvalue (which excludes
+        expressions of type void), or, in C99, the result of a [] or
+        unary '*' operator.  */
+      if (VOID_TYPE_P (TREE_TYPE (arg))
+         && TYPE_QUALS (TREE_TYPE (arg)) == TYPE_UNQUALIFIED
+         && (TREE_CODE (arg) != INDIRECT_REF
+             || !flag_isoc99))
+       pedwarn (location, 0, "taking address of expression of type %<void%>");
+
       /* Let &* cancel out to simplify resulting code.  */
       if (TREE_CODE (arg) == INDIRECT_REF)
        {
          /* Don't let this be an lvalue.  */
          if (lvalue_p (TREE_OPERAND (arg, 0)))
-           return non_lvalue (TREE_OPERAND (arg, 0));
+           return non_lvalue_loc (location, TREE_OPERAND (arg, 0));
          ret = TREE_OPERAND (arg, 0);
          goto return_build_unary_op;
        }
@@ -3353,7 +3616,8 @@ build_unary_op (location_t location,
            return error_mark_node;
          return build_binary_op (location, PLUS_EXPR,
                                  (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
-                                  ? array_to_pointer_conversion (op0)
+                                  ? array_to_pointer_conversion (location,
+                                                                 op0)
                                   : op0),
                                  TREE_OPERAND (arg, 1), 1);
        }
@@ -3405,10 +3669,11 @@ build_unary_op (location_t location,
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
+         tree op0 = fold_convert_loc (location, sizetype,
+                                      fold_offsetof (arg, val)), op1;
 
-         op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+         op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
+         ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0);
          goto return_build_unary_op;
        }
 
@@ -3425,8 +3690,8 @@ build_unary_op (location_t location,
     argtype = TREE_TYPE (arg);
   if (TREE_CODE (arg) == INTEGER_CST)
     ret = (require_constant_value
-          ? fold_build1_initializer (code, argtype, arg)
-          : fold_build1 (code, argtype, arg));
+          ? fold_build1_initializer_loc (location, code, argtype, arg)
+          : fold_build1_loc (location, code, argtype, arg));
   else
     ret = build1 (code, argtype, arg);
  return_build_unary_op:
@@ -3446,7 +3711,7 @@ build_unary_op (location_t location,
    Lvalues can be assigned, unless their type has TYPE_READONLY.
    Lvalues can have their address taken, unless they have C_DECL_REGISTER.  */
 
-static int
+bool
 lvalue_p (const_tree ref)
 {
   const enum tree_code code = TREE_CODE (ref);
@@ -3520,6 +3785,29 @@ readonly_error (tree arg, enum lvalue_use use)
           arg);
 }
 
+/* Give a warning for storing in something that is read-only in GCC
+   terms but not const in ISO C terms.  */
+
+static void
+readonly_warning (tree arg, enum lvalue_use use)
+{
+  switch (use)
+    {
+    case lv_assign:
+      warning (0, "assignment of read-only location %qE", arg);
+      break;
+    case lv_increment:
+      warning (0, "increment of read-only location %qE", arg);
+      break;
+    case lv_decrement:
+      warning (0, "decrement of read-only location %qE", arg);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  return;
+}
+
 
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  USE says
@@ -3607,10 +3895,12 @@ c_mark_addressable (tree exp)
    IFEXP_BCP then the condition is a call to __builtin_constant_p, and
    if folded to an integer constant then the unselected half may
    contain arbitrary operations not normally permitted in constant
-   expressions.  */
+   expressions.  Set the location of the expression to LOC.  */
 
 tree
-build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
+build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
+                       tree op1, tree op1_original_type, tree op2,
+                       tree op2_original_type)
 {
   tree type1;
   tree type2;
@@ -3655,7 +3945,7 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
      In C99 they will be pointers by now.  */
   if (code1 == ARRAY_TYPE || code2 == ARRAY_TYPE)
     {
-      error ("non-lvalue array in conditional expression");
+      error_at (colon_loc, "non-lvalue array in conditional expression");
       return error_mark_node;
     }
 
@@ -3683,6 +3973,20 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
        }
     }
 
+  if (warn_cxx_compat)
+    {
+      tree t1 = op1_original_type ? op1_original_type : TREE_TYPE (orig_op1);
+      tree t2 = op2_original_type ? op2_original_type : TREE_TYPE (orig_op2);
+
+      if (TREE_CODE (t1) == ENUMERAL_TYPE
+         && TREE_CODE (t2) == ENUMERAL_TYPE
+         && TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
+       warning_at (colon_loc, OPT_Wc___compat,
+                   ("different enum types in conditional is "
+                    "invalid in C++: %qT vs %qT"),
+                   t1, t2);
+    }
+
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
@@ -3704,7 +4008,7 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
         and later code won't know it used to be different.
         Do this check on the original types, so that explicit casts
         will be considered, but default promotions won't.  */
-      if (!skip_evaluation)
+      if (c_inhibit_evaluation_warnings == 0)
        {
          int unsigned_op1 = TYPE_UNSIGNED (TREE_TYPE (orig_op1));
          int unsigned_op2 = TYPE_UNSIGNED (TREE_TYPE (orig_op2));
@@ -3731,10 +4035,19 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
                     that folding in this case even without
                     warn_sign_compare to avoid warning options
                     possibly affecting code generation.  */
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_false_node);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_false_node);
+
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_true_node);
                  op2 = c_fully_fold (op2, require_constant_value,
                                      &op2_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_true_node);
 
                  if (warn_sign_compare)
                    {
@@ -3744,20 +4057,14 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
                              && tree_expr_nonnegative_warnv_p (op2, &ovf)))
                        /* OK */;
                      else
-                       warning (OPT_Wsign_compare, "signed and unsigned type in conditional expression");
+                       warning_at (colon_loc, OPT_Wsign_compare,
+                                   ("signed and unsigned type in "
+                                    "conditional expression"));
                    }
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-                   {
-                     op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1),
-                                   NULL, op1);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const;
-                   }
+                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
                  if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST)
-                   {
-                     op2 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op2),
-                                   NULL, op2);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op2) = !op2_maybe_const;
-                   }
+                   op2 = c_wrap_maybe_const (op2, !op2_maybe_const);
                }
            }
        }
@@ -3765,22 +4072,32 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
   else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
     {
       if (code1 != VOID_TYPE || code2 != VOID_TYPE)
-       pedwarn (input_location, OPT_pedantic, 
+       pedwarn (colon_loc, OPT_pedantic,
                 "ISO C forbids conditional expr with only one void side");
       result_type = void_type_node;
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
-      if (comp_target_types (type1, type2))
+      addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+      addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2));
+      addr_space_t as_common;
+
+      if (comp_target_types (colon_loc, type1, type2))
        result_type = common_pointer_type (type1, type2);
       else if (null_pointer_constant_p (orig_op1))
-       result_type = qualify_type (type2, type1);
+       result_type = type2;
       else if (null_pointer_constant_p (orig_op2))
-       result_type = qualify_type (type1, type2);
+       result_type = type1;
+      else if (!addr_space_superset (as1, as2, &as_common))
+       {
+         error_at (colon_loc, "pointers to disjoint address spaces "
+                   "used in conditional expression");
+         return error_mark_node;
+       }
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
-           pedwarn (input_location, OPT_pedantic, 
+           pedwarn (colon_loc, OPT_pedantic,
                     "ISO C forbids conditional expr between "
                     "%<void *%> and function pointer");
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
@@ -3789,7 +4106,7 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
       else if (VOID_TYPE_P (TREE_TYPE (type2)))
        {
          if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
-           pedwarn (input_location, OPT_pedantic, 
+           pedwarn (colon_loc, OPT_pedantic,
                     "ISO C forbids conditional expr between "
                     "%<void *%> and function pointer");
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
@@ -3797,16 +4114,19 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
        }
       else
        {
+         int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+
          if (!objc_ok)
-           pedwarn (input_location, 0, 
+           pedwarn (colon_loc, 0,
                     "pointer type mismatch in conditional expression");
-         result_type = build_pointer_type (void_type_node);
+         result_type = build_pointer_type
+                         (build_qualified_type (void_type_node, qual));
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
     {
       if (!null_pointer_constant_p (orig_op2))
-       pedwarn (input_location, 0, 
+       pedwarn (colon_loc, 0,
                 "pointer/integer type mismatch in conditional expression");
       else
        {
@@ -3817,7 +4137,7 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
   else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
     {
       if (!null_pointer_constant_p (orig_op1))
-       pedwarn (input_location, 0, 
+       pedwarn (colon_loc, 0,
                 "pointer/integer type mismatch in conditional expression");
       else
        {
@@ -3832,7 +4152,7 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
        result_type = void_type_node;
       else
        {
-         error ("type mismatch in conditional expression");
+         error_at (colon_loc, "type mismatch in conditional expression");
          return error_mark_node;
        }
     }
@@ -3840,12 +4160,12 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
   /* Merge const and volatile flags of the incoming types.  */
   result_type
     = build_type_variant (result_type,
-                         TREE_READONLY (op1) || TREE_READONLY (op2),
-                         TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
+                         TYPE_READONLY (type1) || TYPE_READONLY (type2),
+                         TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
 
-  if (result_type != TREE_TYPE (op1))
+  if (result_type != type1)
     op1 = convert_and_check (result_type, op1);
-  if (result_type != TREE_TYPE (op2))
+  if (result_type != type2)
     op2 = convert_and_check (result_type, op2);
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
@@ -3871,7 +4191,7 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
                       && !TREE_OVERFLOW (orig_op2)));
     }
   if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
-    ret = fold_build3 (COND_EXPR, result_type, ifexp, op1, op2);
+    ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
   else
     {
       ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
@@ -3881,14 +4201,17 @@ build_conditional_expr (tree ifexp, bool ifexp_bcp, tree op1, tree op2)
   if (ep_result_type)
     ret = build1 (EXCESS_PRECISION_EXPR, ep_result_type, ret);
 
+  protected_set_expr_location (ret, colon_loc);
   return ret;
 }
 \f
 /* Return a compound expression that performs two expressions and
-   returns the value of the second of them.  */
+   returns the value of the second of them.
+
+   LOC is the location of the COMPOUND_EXPR.  */
 
 tree
-build_compound_expr (tree expr1, tree expr2)
+build_compound_expr (location_t loc, tree expr1, tree expr2)
 {
   bool expr1_int_operands, expr2_int_operands;
   tree eptype = NULL_TREE;
@@ -3924,8 +4247,8 @@ build_compound_expr (tree expr1, tree expr2)
                   && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
-           warning (OPT_Wunused_value, 
-                    "left-hand operand of comma expression has no effect");
+           warning_at (loc, OPT_Wunused_value,
+                       "left-hand operand of comma expression has no effect");
        }
     }
 
@@ -3934,7 +4257,7 @@ build_compound_expr (tree expr1, tree expr2)
      `foo() + bar(), baz()' the result of the `+' operator is not used,
      so we should issue a warning.  */
   else if (warn_unused_value)
-    warn_if_unused_value (expr1, input_location);
+    warn_if_unused_value (expr1, loc);
 
   if (expr2 == error_mark_node)
     return error_mark_node;
@@ -3949,13 +4272,105 @@ build_compound_expr (tree expr1, tree expr2)
   if (eptype)
     ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
 
+  protected_set_expr_location (ret, loc);
   return ret;
 }
 
-/* Build an expression representing a cast to type TYPE of expression EXPR.  */
+/* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
+   which we are casting.  OTYPE is the type of the expression being
+   cast.  Both TYPE and OTYPE are pointer types.  -Wcast-qual appeared
+   on the command line.  Named address space qualifiers are not handled
+   here, because they result in different warnings.  */
+
+static void
+handle_warn_cast_qual (tree type, tree otype)
+{
+  tree in_type = type;
+  tree in_otype = otype;
+  int added = 0;
+  int discarded = 0;
+  bool is_const;
+
+  /* Check that the qualifiers on IN_TYPE are a superset of the
+     qualifiers of IN_OTYPE.  The outermost level of POINTER_TYPE
+     nodes is uninteresting and we stop as soon as we hit a
+     non-POINTER_TYPE node on either type.  */
+  do
+    {
+      in_otype = TREE_TYPE (in_otype);
+      in_type = TREE_TYPE (in_type);
+
+      /* GNU C allows cv-qualified function types.  'const' means the
+        function is very pure, 'volatile' means it can't return.  We
+        need to warn when such qualifiers are added, not when they're
+        taken away.  */
+      if (TREE_CODE (in_otype) == FUNCTION_TYPE
+         && TREE_CODE (in_type) == FUNCTION_TYPE)
+       added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
+      else
+       discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
+    }
+  while (TREE_CODE (in_type) == POINTER_TYPE
+        && TREE_CODE (in_otype) == POINTER_TYPE);
+
+  if (added)
+    warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+
+  if (discarded)
+    /* There are qualifiers present in IN_OTYPE that are not present
+       in IN_TYPE.  */
+    warning (OPT_Wcast_qual,
+            "cast discards qualifiers from pointer target type");
+
+  if (added || discarded)
+    return;
+
+  /* A cast from **T to const **T is unsafe, because it can cause a
+     const value to be changed with no additional warning.  We only
+     issue this warning if T is the same on both sides, and we only
+     issue the warning if there are the same number of pointers on
+     both sides, as otherwise the cast is clearly unsafe anyhow.  A
+     cast is unsafe when a qualifier is added at one level and const
+     is not present at all outer levels.
+
+     To issue this warning, we check at each level whether the cast
+     adds new qualifiers not already seen.  We don't need to special
+     case function types, as they won't have the same
+     TYPE_MAIN_VARIANT.  */
+
+  if (TYPE_MAIN_VARIANT (in_type) != TYPE_MAIN_VARIANT (in_otype))
+    return;
+  if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE)
+    return;
+
+  in_type = type;
+  in_otype = otype;
+  is_const = TYPE_READONLY (TREE_TYPE (in_type));
+  do
+    {
+      in_type = TREE_TYPE (in_type);
+      in_otype = TREE_TYPE (in_otype);
+      if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
+         && !is_const)
+       {
+         warning (OPT_Wcast_qual,
+                  ("new qualifiers in middle of multi-level non-const cast "
+                   "are unsafe"));
+         break;
+       }
+      if (is_const)
+       is_const = TYPE_READONLY (in_type);
+    }
+  while (TREE_CODE (in_type) == POINTER_TYPE);
+}
+
+/* Build an expression representing a cast to type TYPE of expression EXPR.
+   LOC is the location of the cast-- typically the open paren of the cast.  */
 
 tree
-build_c_cast (tree type, tree expr)
+build_c_cast (location_t loc, tree type, tree expr)
 {
   tree value;
 
@@ -3977,13 +4392,13 @@ build_c_cast (tree type, tree expr)
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      error ("cast specifies array type");
+      error_at (loc, "cast specifies array type");
       return error_mark_node;
     }
 
   if (TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error ("cast specifies function type");
+      error_at (loc, "cast specifies function type");
       return error_mark_node;
     }
 
@@ -3998,7 +4413,7 @@ build_c_cast (tree type, tree expr)
     {
       if (TREE_CODE (type) == RECORD_TYPE
          || TREE_CODE (type) == UNION_TYPE)
-       pedwarn (input_location, OPT_pedantic, 
+       pedwarn (loc, OPT_pedantic,
                 "ISO C forbids casting nonscalar to the same type");
     }
   else if (TREE_CODE (type) == UNION_TYPE)
@@ -4014,16 +4429,19 @@ build_c_cast (tree type, tree expr)
       if (field)
        {
          tree t;
-
-         pedwarn (input_location, OPT_pedantic,
-                  "ISO C forbids casts to union type");
-         t = digest_init (type,
-                          build_constructor_single (type, field, value),
-                          false, true, 0);
+         bool maybe_const = true;
+
+         pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type");
+         t = c_fully_fold (value, false, &maybe_const);
+         t = build_constructor_single (type, field, t);
+         if (!maybe_const)
+           t = c_wrap_maybe_const (t, true);
+         t = digest_init (loc, type, t,
+                          NULL_TREE, false, true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          return t;
        }
-      error ("cast to union type from type not present in union");
+      error_at (loc, "cast to union type from type not present in union");
       return error_mark_node;
     }
   else
@@ -4031,50 +4449,48 @@ build_c_cast (tree type, tree expr)
       tree otype, ovalue;
 
       if (type == void_type_node)
-       return build1 (CONVERT_EXPR, type, value);
+       {
+         tree t = build1 (CONVERT_EXPR, type, value);
+         SET_EXPR_LOCATION (t, loc);
+         return t;
+       }
 
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
-
       if (warn_cast_qual
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
+       handle_warn_cast_qual (type, otype);
+
+      /* Warn about conversions between pointers to disjoint
+        address spaces.  */
+      if (TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && !null_pointer_constant_p (value))
        {
-         tree in_type = type;
-         tree in_otype = otype;
-         int added = 0;
-         int discarded = 0;
+         addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
+         addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (otype));
+         addr_space_t as_common;
 
-         /* Check that the qualifiers on IN_TYPE are a superset of
-            the qualifiers of IN_OTYPE.  The outermost level of
-            POINTER_TYPE nodes is uninteresting and we stop as soon
-            as we hit a non-POINTER_TYPE node on either type.  */
-         do
+         if (!addr_space_superset (as_to, as_from, &as_common))
            {
-             in_otype = TREE_TYPE (in_otype);
-             in_type = TREE_TYPE (in_type);
-
-             /* GNU C allows cv-qualified function types.  'const'
-                means the function is very pure, 'volatile' means it
-                can't return.  We need to warn when such qualifiers
-                are added, not when they're taken away.  */
-             if (TREE_CODE (in_otype) == FUNCTION_TYPE
-                 && TREE_CODE (in_type) == FUNCTION_TYPE)
-               added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
-             else
-               discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
-           }
-         while (TREE_CODE (in_type) == POINTER_TYPE
-                && TREE_CODE (in_otype) == POINTER_TYPE);
+             if (ADDR_SPACE_GENERIC_P (as_from))
+               warning_at (loc, 0, "cast to %s address space pointer "
+                           "from disjoint generic address space pointer",
+                           c_addr_space_name (as_to));
 
-         if (added)
-           warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+             else if (ADDR_SPACE_GENERIC_P (as_to))
+               warning_at (loc, 0, "cast to generic address space pointer "
+                           "from disjoint %s address space pointer",
+                           c_addr_space_name (as_from));
 
-         if (discarded)
-           /* There are qualifiers present in IN_OTYPE that are not
-              present in IN_TYPE.  */
-           warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
+             else
+               warning_at (loc, 0, "cast to %s address space pointer "
+                           "from disjoint %s address space pointer",
+                           c_addr_space_name (as_to),
+                           c_addr_space_name (as_from));
+           }
        }
 
       /* Warn about possible alignment problems.  */
@@ -4089,8 +4505,8 @@ 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 (OPT_Wcast_align,
-                "cast increases required alignment of target type");
+       warning_at (loc, OPT_Wcast_align,
+                   "cast increases required alignment of target type");
 
       if (TREE_CODE (type) == INTEGER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE
@@ -4100,21 +4516,23 @@ build_c_cast (tree type, tree expr)
          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");
+       warning_at (loc, 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 (OPT_Wbad_function_cast, "cast from function call of type %qT "
-                "to non-matching type %qT", otype, type);
+       warning_at (loc, OPT_Wbad_function_cast,
+                   "cast from function call of type %qT "
+                   "to non-matching type %qT", otype, 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 (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
-                "of different size");
+       warning_at (loc,
+                   OPT_Wint_to_pointer_cast, "cast to pointer from integer "
+                   "of different size");
 
       if (warn_strict_aliasing <= 2)
         strict_aliasing_warning (otype, type, expr);
@@ -4127,7 +4545,7 @@ build_c_cast (tree type, tree expr)
          && TREE_CODE (otype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
-       pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+       pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "conversion of function pointer to object pointer type");
 
       if (pedantic
@@ -4136,7 +4554,7 @@ build_c_cast (tree type, tree expr)
          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
          && TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
          && !null_pointer_constant_p (value))
-       pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+       pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "conversion of object pointer to function pointer type");
 
       ovalue = value;
@@ -4164,7 +4582,7 @@ build_c_cast (tree type, tree expr)
 
   /* Don't let a cast be an lvalue.  */
   if (value == expr)
-    value = non_lvalue (value);
+    value = non_lvalue_loc (loc, value);
 
   /* Don't allow the results of casting to floating-point or complex
      types be confused with actual constants, or casts involving
@@ -4180,12 +4598,16 @@ build_c_cast (tree type, tree expr)
               || TREE_CODE (expr) == COMPLEX_CST)))
       value = build1 (NOP_EXPR, type, value);
 
+  if (CAN_HAVE_LOCATION_P (value))
+    SET_EXPR_LOCATION (value, loc);
   return value;
 }
 
-/* Interpret a cast of expression EXPR to type TYPE.  */
+/* Interpret a cast of expression EXPR to type TYPE.  LOC is the
+   location of the open paren of the cast, or the position of the cast
+   expr.  */
 tree
-c_cast_expr (struct c_type_name *type_name, tree expr)
+c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
 {
   tree type;
   tree type_expr = NULL_TREE;
@@ -4200,25 +4622,41 @@ c_cast_expr (struct c_type_name *type_name, tree expr)
   type = groktypename (type_name, &type_expr, &type_expr_const);
   warn_strict_prototypes = saved_wsp;
 
-  ret = build_c_cast (type, expr);
+  ret = build_c_cast (loc, type, expr);
   if (type_expr)
     {
       ret = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (ret), type_expr, ret);
       C_MAYBE_CONST_EXPR_NON_CONST (ret) = !type_expr_const;
+      SET_EXPR_LOCATION (ret, loc);
     }
+
+  if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
+    SET_EXPR_LOCATION (ret, loc);
+
+  /* C++ does not permits types to be defined in a cast.  */
+  if (warn_cxx_compat && type_name->specs->tag_defined_p)
+    warning_at (loc, OPT_Wc___compat,
+               "defining a type in a cast is invalid in C++");
+
   return ret;
 }
 \f
 /* Build an assignment expression of lvalue LHS from value RHS.
+   If LHS_ORIGTYPE is not NULL, it is the original type of LHS, which
+   may differ from TREE_TYPE (LHS) for an enum bitfield.
    MODIFYCODE is the code for a binary operator that we use
    to combine the old value of LHS with RHS to get the new value.
    Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
+   If RHS_ORIGTYPE is not NULL_TREE, it is the original type of RHS,
+   which may differ from TREE_TYPE (RHS) for an enum value.
 
-   LOCATION is the location of the MODIFYCODE operator.  */
+   LOCATION is the location of the MODIFYCODE operator.
+   RHS_LOC is the location of the RHS.  */
 
 tree
-build_modify_expr (location_t location,
-                  tree lhs, enum tree_code modifycode, tree rhs)
+build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
+                  enum tree_code modifycode,
+                  location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
   tree newrhs;
@@ -4248,7 +4686,8 @@ build_modify_expr (location_t location,
   if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
     {
       tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs),
-                                     modifycode, rhs);
+                                     lhs_origtype, modifycode, rhs_loc, rhs,
+                                     rhs_origtype);
       if (inner == error_mark_node)
        return error_mark_node;
       result = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner),
@@ -4268,11 +4707,15 @@ build_modify_expr (location_t location,
       lhs = stabilize_reference (lhs);
       newrhs = build_binary_op (location,
                                modifycode, lhs, rhs, 1);
+
+      /* The original type of the right hand side is no longer
+        meaningful.  */
+      rhs_origtype = NULL_TREE;
     }
 
   /* Give an error for storing in something that is 'const'.  */
 
-  if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
+  if (TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
           || TREE_CODE (lhstype) == UNION_TYPE)
          && C_TYPE_FIELDS_READONLY (lhstype)))
@@ -4280,6 +4723,8 @@ build_modify_expr (location_t location,
       readonly_error (lhs, lv_assign);
       return error_mark_node;
     }
+  else if (TREE_READONLY (lhs))
+    readonly_warning (lhs, lv_assign);
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
@@ -4302,6 +4747,23 @@ build_modify_expr (location_t location,
       TREE_TYPE (lhs) = lhstype;
     }
 
+  /* Issue -Wc++-compat warnings about an assignment to an enum type
+     when LHS does not have its original type.  This happens for,
+     e.g., an enum bitfield in a struct.  */
+  if (warn_cxx_compat
+      && lhs_origtype != NULL_TREE
+      && lhs_origtype != lhstype
+      && TREE_CODE (lhs_origtype) == ENUMERAL_TYPE)
+    {
+      tree checktype = (rhs_origtype != NULL_TREE
+                       ? rhs_origtype
+                       : TREE_TYPE (rhs));
+      if (checktype != error_mark_node
+         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (lhs_origtype))
+       warning_at (location, OPT_Wc___compat,
+                   "enum conversion in assignment is invalid in C++");
+    }
+
   /* Convert new value to destination type.  Fold it first, then
      restore any excess precision information, for the sake of
      conversion warnings.  */
@@ -4310,8 +4772,8 @@ build_modify_expr (location_t location,
   newrhs = c_fully_fold (newrhs, false, NULL);
   if (rhs_semantic_type)
     newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
-  newrhs = convert_for_assignment (lhstype, newrhs, ic_assign, npc,
-                                  NULL_TREE, NULL_TREE, 0);
+  newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
+                                  ic_assign, npc, NULL_TREE, NULL_TREE, 0);
   if (TREE_CODE (newrhs) == ERROR_MARK)
     return error_mark_node;
 
@@ -4340,28 +4802,32 @@ build_modify_expr (location_t location,
   if (olhstype == TREE_TYPE (result))
     return result;
 
-  result = convert_for_assignment (olhstype, result, ic_assign, false,
-                                  NULL_TREE, NULL_TREE, 0);
+  result = convert_for_assignment (location, olhstype, result, rhs_origtype,
+                                  ic_assign, false, NULL_TREE, NULL_TREE, 0);
   protected_set_expr_location (result, location);
   return result;
 }
 \f
-/* Convert value RHS to type TYPE as preparation for an assignment
-   to an lvalue of type TYPE.  NULL_POINTER_CONSTANT says whether RHS
-   was a null pointer constant before any folding.
+/* Convert value RHS to type TYPE as preparation for an assignment to
+   an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
+   original type of RHS; this differs from TREE_TYPE (RHS) for enum
+   types.  NULL_POINTER_CONSTANT says whether RHS was a null pointer
+   constant before any folding.
    The real work of conversion is done by `convert'.
    The purpose of this function is to generate error messages
    for assignments that are not allowed in C.
    ERRTYPE says whether it is argument passing, assignment,
    initialization or return.
 
+   LOCATION is the location of the RHS.
    FUNCTION is a tree for the function being called.
    PARMNUM is the number of the argument, for printing in error messages.  */
 
 static tree
-convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
-                       bool null_pointer_constant,
-                       tree fundecl, tree function, int parmnum)
+convert_for_assignment (location_t location, tree type, tree rhs,
+                       tree origtype, enum impl_conv errtype,
+                       bool null_pointer_constant, tree fundecl,
+                       tree function, int parmnum)
 {
   enum tree_code codel = TREE_CODE (type);
   tree orig_rhs = rhs;
@@ -4392,14 +4858,14 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   /* This macro is used to emit diagnostics to ensure that all format
      strings are complete sentences, visible to gettext and checked at
      compile time.  */
-#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)               \
+#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE)                      \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
       case ic_argpass:                                                   \
         if (pedwarn (LOCATION, OPT, AR, parmnum, rname))                 \
-          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
-                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
+                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
                   "expected %qT but argument is of type %qT",            \
                   type, rhstype);                                        \
         break;                                                           \
@@ -4410,7 +4876,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
         pedwarn (LOCATION, OPT, IN);                                     \
         break;                                                           \
       case ic_return:                                                    \
-        pedwarn (LOCATION, OPT, RE);                                     \
+        pedwarn (LOCATION, OPT, RE);                                    \
         break;                                                           \
       default:                                                           \
         gcc_unreachable ();                                              \
@@ -4452,6 +4918,25 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       objc_ok = objc_compare_types (type, rhstype, parmno, rname);
     }
 
+  if (warn_cxx_compat)
+    {
+      tree checktype = origtype != NULL_TREE ? origtype : rhstype;
+      if (checktype != error_mark_node
+         && TREE_CODE (type) == ENUMERAL_TYPE
+         && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
+       {
+         WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
+                              G_("enum conversion when passing argument "
+                                 "%d of %qE is invalid in C++"),
+                              G_("enum conversion in assignment is "
+                                 "invalid in C++"),
+                              G_("enum conversion in initialization is "
+                                 "invalid in C++"),
+                              G_("enum conversion in return is "
+                                 "invalid in C++"));
+       }
+    }
+
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
     return rhs;
 
@@ -4462,7 +4947,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
         an unprototyped function, it is compile-time undefined;
         making it a constraint in that case was rejected in
         DR#252.  */
-      error ("void value not ignored as it ought to be");
+      error_at (location, "void value not ignored as it ought to be");
       return error_mark_node;
     }
   rhs = require_complete_type (rhs);
@@ -4476,12 +4961,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     {
       if (!lvalue_p (rhs))
        {
-         error ("cannot pass rvalue to reference parameter");
+         error_at (location, "cannot pass rvalue to reference parameter");
          return error_mark_node;
        }
       if (!c_mark_addressable (rhs))
        return error_mark_node;
       rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
+      SET_EXPR_LOCATION (rhs, location);
 
       /* We already know that these two types are compatible, but they
         may not be exactly identical.  In fact, `TREE_TYPE (type)' is
@@ -4489,9 +4975,13 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
         likely to be va_list, a typedef to __builtin_va_list, which
         is different enough that it will cause problems later.  */
       if (TREE_TYPE (TREE_TYPE (rhs)) != TREE_TYPE (type))
-       rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
+       {
+         rhs = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (type)), rhs);
+         SET_EXPR_LOCATION (rhs, location);
+       }
 
       rhs = build1 (NOP_EXPR, type, rhs);
+      SET_EXPR_LOCATION (rhs, location);
       return rhs;
     }
   /* Some types can interconvert without explicit casts.  */
@@ -4552,7 +5042,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))
+                 || comp_target_types (location, memb_type, rhstype))
                {
                  /* If this type won't generate any warnings, use it.  */
                  if (TYPE_QUALS (ttl) == TYPE_QUALS (ttr)
@@ -4597,8 +5087,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                     certain things, 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 (input_location, 0,
+                 if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
+                   WARN_FOR_ASSIGNMENT (location, 0,
                                         G_("passing argument %d of %qE "
                                            "makes qualified function "
                                            "pointer from unqualified"),
@@ -4611,8 +5102,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                                         G_("return makes qualified function "
                                            "pointer from unqualified"));
                }
-             else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (input_location, 0,
+             else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
+               WARN_FOR_ASSIGNMENT (location, 0,
                                     G_("passing argument %d of %qE discards "
                                        "qualifiers from pointer target type"),
                                     G_("assignment discards qualifiers "
@@ -4626,10 +5118,10 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
            }
 
          if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
-           pedwarn (input_location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ISO C prohibits argument conversion to union type");
 
-         rhs = fold_convert (TREE_TYPE (memb), rhs);
+         rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
          return build_constructor_single (type, memb, rhs);
        }
     }
@@ -4644,6 +5136,8 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       tree mvr = ttr;
       bool is_opaque_pointer;
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
+      addr_space_t asl;
+      addr_space_t asr;
 
       if (TREE_CODE (mvl) != ARRAY_TYPE)
        mvl = TYPE_MAIN_VARIANT (mvl);
@@ -4660,8 +5154,39 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
 
         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);
+       warning_at (location, OPT_Wc___compat,
+                   "request for implicit conversion "
+                   "from %qT to %qT not permitted in C++", rhstype, type);
+
+      /* See if the pointers point to incompatible address spaces.  */
+      asl = TYPE_ADDR_SPACE (ttl);
+      asr = TYPE_ADDR_SPACE (ttr);
+      if (!null_pointer_constant_p (rhs)
+         && asr != asl && !targetm.addr_space.subset_p (asr, asl))
+       {
+         switch (errtype)
+           {
+           case ic_argpass:
+             error_at (location, "passing argument %d of %qE from pointer to "
+                       "non-enclosed address space", parmnum, rname);
+             break;
+           case ic_assign:
+             error_at (location, "assignment from pointer to "
+                       "non-enclosed address space");
+             break;
+           case ic_init:
+             error_at (location, "initialization from pointer to "
+                       "non-enclosed address space");
+             break;
+           case ic_return:
+             error_at (location, "return from pointer to "
+                       "non-enclosed address space");
+             break;
+           default:
+             gcc_unreachable ();
+           }
+         return error_mark_node;
+       }
 
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
@@ -4671,25 +5196,25 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
          switch (errtype)
          {
          case ic_argpass:
-           warning (OPT_Wmissing_format_attribute,
-                    "argument %d of %qE might be "
-                    "a candidate for a format attribute",
-                    parmnum, rname);
+           warning_at (location, 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");
+           warning_at (location, 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");
+           warning_at (location, 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");
+           warning_at (location, OPT_Wmissing_format_attribute,
+                       "return type might be "
+                       "a candidate for a format attribute");
            break;
          default:
            gcc_unreachable ();
@@ -4700,7 +5225,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
         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))
+         || (target_cmp = comp_target_types (location, type, rhstype))
          || is_opaque_pointer
          || (c_common_unsigned_type (mvl)
              == c_common_unsigned_type (mvr)))
@@ -4711,7 +5236,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                  (VOID_TYPE_P (ttr)
                   && !null_pointer_constant
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (input_location, OPT_pedantic,
+           WARN_FOR_ASSIGNMENT (location, OPT_pedantic,
                                 G_("ISO C forbids passing argument %d of "
                                    "%qE between function pointer "
                                    "and %<void *%>"),
@@ -4726,13 +5251,14 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
-             if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+             if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                {
                  /* 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 (input_location, 0,
+                   WARN_FOR_ASSIGNMENT (location, 0,
                                         G_("passing argument %d of %qE discards "
                                            "qualifiers from pointer target type"),
                                         G_("assignment discards qualifiers "
@@ -4749,7 +5275,7 @@ 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 (input_location, OPT_Wpointer_sign,
+               WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
                                     G_("pointer targets in passing argument "
                                        "%d of %qE differ in signedness"),
                                     G_("pointer targets in assignment "
@@ -4766,8 +5292,9 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
                 that say the function will not do certain things,
                 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 (input_location, 0,
+             if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
+               WARN_FOR_ASSIGNMENT (location, 0,
                                     G_("passing argument %d of %qE makes "
                                        "qualified function pointer "
                                        "from unqualified"),
@@ -4782,7 +5309,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
       else
        /* Avoid warning about the volatile ObjC EH puts on decls.  */
        if (!objc_ok)
-         WARN_FOR_ASSIGNMENT (input_location, 0,
+         WARN_FOR_ASSIGNMENT (location, 0,
                               G_("passing argument %d of %qE from "
                                  "incompatible pointer type"),
                               G_("assignment from incompatible pointer type"),
@@ -4796,7 +5323,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     {
       /* ??? This should not be an error when inlining calls to
         unprototyped functions.  */
-      error ("invalid use of non-lvalue array");
+      error_at (location, "invalid use of non-lvalue array");
       return error_mark_node;
     }
   else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
@@ -4805,7 +5332,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
         or one that results from arithmetic, even including
         a cast to integer type.  */
       if (!null_pointer_constant)
-       WARN_FOR_ASSIGNMENT (input_location, 0,
+       WARN_FOR_ASSIGNMENT (location, 0,
                             G_("passing argument %d of %qE makes "
                                "pointer from integer without a cast"),
                             G_("assignment makes pointer from integer "
@@ -4819,7 +5346,7 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (input_location, 0,
+      WARN_FOR_ASSIGNMENT (location, 0,
                           G_("passing argument %d of %qE makes integer "
                              "from pointer without a cast"),
                           G_("assignment makes integer from pointer "
@@ -4843,22 +5370,24 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype,
   switch (errtype)
     {
     case ic_argpass:
-      error ("incompatible type for argument %d of %qE", parmnum, rname);
+      error_at (location, "incompatible type for argument %d of %qE", parmnum, rname);
       inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
              ? DECL_SOURCE_LOCATION (fundecl) : input_location,
              "expected %qT but argument is of type %qT", type, rhstype);
       break;
     case ic_assign:
-      error ("incompatible types when assigning to type %qT from type %qT",
-            type, rhstype);
+      error_at (location, "incompatible types when assigning to type %qT from "
+               "type %qT", type, rhstype);
       break;
     case ic_init:
-      error ("incompatible types when initializing type %qT using type %qT",
-            type, rhstype);
+      error_at (location,
+               "incompatible types when initializing type %qT using type %qT",
+               type, rhstype);
       break;
     case ic_return:
-      error ("incompatible types when returning type %qT but %qT was expected",
-            rhstype, type);
+      error_at (location,
+               "incompatible types when returning type %qT but %qT was "
+               "expected", rhstype, type);
       break;
     default:
       gcc_unreachable ();
@@ -4893,10 +5422,13 @@ valid_compound_expr_initializer (tree value, tree endtype)
 /* Perform appropriate conversions on the initial value of a variable,
    store it in the declaration DECL,
    and print any error messages that are appropriate.
-   If the init is invalid, store an ERROR_MARK.  */
+   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
+   If the init is invalid, store an ERROR_MARK.
+
+   INIT_LOC is the location of the initial value.  */
 
 void
-store_init_value (tree decl, tree init)
+store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
 {
   tree value, type;
   bool npc = false;
@@ -4911,7 +5443,8 @@ store_init_value (tree decl, tree init)
 
   if (init)
     npc = null_pointer_constant_p (init);
-  value = digest_init (type, init, npc, true, TREE_STATIC (decl));
+  value = digest_init (init_loc, type, init, origtype, npc,
+                      true, TREE_STATIC (decl));
 
   /* Store the expression if valid; else report error.  */
 
@@ -4924,7 +5457,7 @@ store_init_value (tree decl, tree init)
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
   STRIP_TYPE_NOPS (value);
-  if (TREE_STATIC (decl)) 
+  if (TREE_STATIC (decl))
     constant_expression_warning (value);
 
   /* Check if we need to set array size from compound literal size.  */
@@ -5019,7 +5552,9 @@ static void
 push_member_name (tree decl)
 {
   const char *const string
-    = DECL_NAME (decl) ? IDENTIFIER_POINTER (DECL_NAME (decl)) : "<anonymous>";
+    = (DECL_NAME (decl)
+       ? identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl)))
+       : _("<anonymous>"));
   PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
 }
 
@@ -5107,7 +5642,7 @@ pedwarn_init (location_t location, int opt, const char *msgid)
     pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
 }
 
-/* Issue a warning for a bad initializer component.  
+/* Issue a warning for a bad initializer component.
 
    OPT is the OPT_W* value corresponding to the warning option that
    controls this warning.  MSGID identifies the message.  The
@@ -5135,25 +5670,30 @@ maybe_warn_string_init (tree type, struct c_expr expr)
       && TREE_CODE (type) == ARRAY_TYPE
       && TREE_CODE (expr.value) == STRING_CST
       && expr.original_code != STRING_CST)
-    pedwarn_init (input_location, OPT_pedantic, 
+    pedwarn_init (input_location, OPT_pedantic,
                  "array initialized from parenthesized string constant");
 }
 
 /* Digest the parser output INIT as an initializer for type TYPE.
    Return a C expression of type TYPE to represent the initial value.
 
+   If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
+
    NULL_POINTER_CONSTANT is true if INIT is a null pointer constant.
 
    If INIT is a string constant, STRICT_STRING is true if it is
    unparenthesized or we should not warn here for it being parenthesized.
    For other types of INIT, STRICT_STRING is not used.
 
+   INIT_LOC is the location of the INIT.
+
    REQUIRE_CONSTANT requests an error if non-constant initializers or
    elements are seen.  */
 
 static tree
-digest_init (tree type, tree init, bool null_pointer_constant,
-            bool strict_string, int require_constant)
+digest_init (location_t init_loc, tree type, tree init, tree origtype,
+            bool null_pointer_constant, bool strict_string,
+            int require_constant)
 {
   enum tree_code code = TREE_CODE (type);
   tree inside_init = init;
@@ -5202,6 +5742,10 @@ digest_init (tree type, tree init, bool null_pointer_constant,
          expr.original_type = NULL;
          maybe_warn_string_init (type, expr);
 
+         if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+           pedwarn_init (init_loc, OPT_pedantic,
+                         "initialization of a flexible array member");
+
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
                         TYPE_MAIN_VARIANT (type)))
            return inside_init;
@@ -5233,16 +5777,26 @@ digest_init (tree type, tree init, bool null_pointer_constant,
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
              && TYPE_SIZE (type) != 0
-             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+           {
+             unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init);
+
              /* Subtract the size of a single (possibly wide) character
                 because it's ok to ignore the terminating null char
                 that is counted in the length of the constant.  */
-             && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
-                                      TREE_STRING_LENGTH (inside_init)
-                                      - (TYPE_PRECISION (typ1)
-                                         / BITS_PER_UNIT)))
-           pedwarn_init (input_location, 0, 
-                         "initializer-string for array of chars is too long");
+             if (0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+                                       (len
+                                        - (TYPE_PRECISION (typ1)
+                                           / BITS_PER_UNIT))))
+               pedwarn_init (init_loc, 0,
+                             ("initializer-string for array of chars "
+                              "is too long"));
+             else if (warn_cxx_compat
+                      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), len))
+               warning_at (init_loc, OPT_Wc___compat,
+                           ("initializer-string for array chars "
+                            "is too long for C++"));
+           }
 
          return inside_init;
        }
@@ -5312,7 +5866,8 @@ digest_init (tree type, tree init, bool null_pointer_constant,
            {
              if (TREE_CODE (inside_init) == STRING_CST
                  || TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
-               inside_init = array_to_pointer_conversion (inside_init);
+               inside_init = array_to_pointer_conversion
+                 (init_loc, inside_init);
              else
                {
                  error_init ("invalid use of non-lvalue array");
@@ -5357,7 +5912,7 @@ digest_init (tree type, tree init, bool null_pointer_constant,
          if (inside_init == error_mark_node)
            error_init ("initializer element is not constant");
          else
-           pedwarn_init (input_location, OPT_pedantic,
+           pedwarn_init (init_loc, OPT_pedantic,
                          "initializer element is not constant");
          if (flag_pedantic_errors)
            inside_init = error_mark_node;
@@ -5370,13 +5925,14 @@ digest_init (tree type, tree init, bool null_pointer_constant,
          inside_init = error_mark_node;
        }
       else if (require_constant && !maybe_const)
-       pedwarn_init (input_location, 0,
+       pedwarn_init (init_loc, 0,
                      "initializer element is not a constant expression");
 
       /* 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_pointer_constant,
+       inside_init = convert_for_assignment (init_loc, type, inside_init,
+                                             origtype,
+                                             ic_init, null_pointer_constant,
                                              NULL_TREE, NULL_TREE, 0);
       return inside_init;
     }
@@ -5390,13 +5946,13 @@ digest_init (tree type, tree init, bool null_pointer_constant,
       if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
          && (TREE_CODE (init) == STRING_CST
              || TREE_CODE (init) == COMPOUND_LITERAL_EXPR))
-       inside_init = init = array_to_pointer_conversion (init);
+       inside_init = init = array_to_pointer_conversion (init_loc, init);
       if (semantic_type)
        inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type,
                              inside_init);
       inside_init
-       = convert_for_assignment (type, inside_init, ic_init,
-                                 null_pointer_constant,
+       = convert_for_assignment (init_loc, type, inside_init, origtype,
+                                 ic_init, null_pointer_constant,
                                  NULL_TREE, NULL_TREE, 0);
 
       /* Check to see if we have already given an error message.  */
@@ -5415,7 +5971,7 @@ digest_init (tree type, tree init, bool null_pointer_constant,
          inside_init = error_mark_node;
        }
       else if (require_constant && !maybe_const)
-       pedwarn_init (input_location, 0,
+       pedwarn_init (init_loc, 0,
                      "initializer element is not a constant expression");
 
       return inside_init;
@@ -5493,6 +6049,7 @@ struct init_node
   int balance;
   tree purpose;
   tree value;
+  tree origtype;
 };
 
 /* Tree of pending elements at this constructor level.
@@ -5631,13 +6188,13 @@ start_init (tree decl, tree asmspec_tree ATTRIBUTE_UNUSED, int top_level)
               || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
               || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE
               || TREE_CODE (TREE_TYPE (decl)) == QUAL_UNION_TYPE));
-      locus = IDENTIFIER_POINTER (DECL_NAME (decl));
+      locus = identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl)));
     }
   else
     {
       require_constant_value = 0;
       require_constant_elements = 0;
-      locus = "(anonymous)";
+      locus = _("(anonymous)");
     }
 
   constructor_stack = 0;
@@ -5700,7 +6257,8 @@ really_start_incremental_init (tree type)
   if (type == 0)
     type = TREE_TYPE (constructor_decl);
 
-  if (targetm.vector_opaque_p (type))
+  if (TREE_CODE (type) == VECTOR_TYPE
+      && TYPE_VECTOR_OPAQUE (type))
     error ("opaque vector types cannot be initialized");
 
   p->type = constructor_type;
@@ -6276,6 +6834,24 @@ set_init_index (tree first, tree last)
     }
 
   if (TREE_CODE (first) != INTEGER_CST)
+    {
+      first = c_fully_fold (first, false, NULL);
+      if (TREE_CODE (first) == INTEGER_CST)
+       pedwarn_init (input_location, OPT_pedantic,
+                     "array index in initializer is not "
+                     "an integer constant expression");
+    }
+
+  if (last && TREE_CODE (last) != INTEGER_CST)
+    {
+      last = c_fully_fold (last, false, NULL);
+      if (TREE_CODE (last) == INTEGER_CST)
+       pedwarn_init (input_location, OPT_pedantic,
+                     "array index in initializer is not "
+                     "an integer constant expression");
+    }
+
+  if (TREE_CODE (first) != INTEGER_CST)
     error_init ("nonconstant array index in initializer");
   else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
     error_init ("nonconstant array index in initializer");
@@ -6361,7 +6937,8 @@ set_init_label (tree fieldname)
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
    identifies the initializer, either array index or field in a structure.
-   VALUE is the value of that index or field.
+   VALUE is the value of that index or field.  If ORIGTYPE is not
+   NULL_TREE, it is the original type of VALUE.
 
    IMPLICIT is true if value comes from pop_init_level (1),
    the new initializer has been merged with the existing one
@@ -6369,7 +6946,7 @@ set_init_label (tree fieldname)
    existing initializer.  */
 
 static void
-add_pending_init (tree purpose, tree value, bool implicit)
+add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
 {
   struct init_node *p, **q, *r;
 
@@ -6395,6 +6972,7 @@ add_pending_init (tree purpose, tree value, bool implicit)
                    warning_init (OPT_Woverride_init, "initialized field overwritten");
                }
              p->value = value;
+             p->origtype = origtype;
              return;
            }
        }
@@ -6421,6 +6999,7 @@ add_pending_init (tree purpose, tree value, bool implicit)
                    warning_init (OPT_Woverride_init, "initialized field overwritten");
                }
              p->value = value;
+             p->origtype = origtype;
              return;
            }
        }
@@ -6429,6 +7008,7 @@ add_pending_init (tree purpose, tree value, bool implicit)
   r = GGC_NEW (struct init_node);
   r->purpose = purpose;
   r->value = value;
+  r->origtype = origtype;
 
   *q = r;
   r->parent = p;
@@ -6604,7 +7184,7 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    add_pending_init (index, value, false);
+    add_pending_init (index, value, NULL_TREE, false);
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -6694,7 +7274,7 @@ set_nonincremental_init_from_string (tree str)
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, false);
+      add_pending_init (purpose, value, NULL_TREE, false);
     }
 
   constructor_incremental = 0;
@@ -6759,6 +7339,7 @@ find_init_member (tree field)
 /* "Output" the next constructor element.
    At top level, really output it to assembler code now.
    Otherwise, collect it in a list from which we will make a CONSTRUCTOR.
+   If ORIGTYPE is not NULL_TREE, it is the original type of VALUE.
    TYPE is the data type that the containing data type wants here.
    FIELD is the field (a FIELD_DECL) or the index that this element fills.
    If VALUE is a string constant, STRICT_STRING is true if it is
@@ -6775,8 +7356,8 @@ find_init_member (tree field)
    existing initializer.  */
 
 static void
-output_init_element (tree value, bool strict_string, tree type, tree field,
-                    int pending, bool implicit)
+output_init_element (tree value, tree origtype, bool strict_string, tree type,
+                    tree field, int pending, bool implicit)
 {
   tree semantic_type = NULL_TREE;
   constructor_elt *celt;
@@ -6796,7 +7377,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
           && INTEGRAL_TYPE_P (TREE_TYPE (type)))
       && !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (value)),
                     TYPE_MAIN_VARIANT (type)))
-    value = array_to_pointer_conversion (value);
+    value = array_to_pointer_conversion (input_location, value);
 
   if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR
       && require_constant_value && !flag_isoc99 && pending)
@@ -6845,6 +7426,24 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
     pedwarn_init (input_location, 0,
                  "initializer element is not a constant expression");
 
+  /* Issue -Wc++-compat warnings about initializing a bitfield with
+     enum type.  */
+  if (warn_cxx_compat
+      && field != NULL_TREE
+      && TREE_CODE (field) == FIELD_DECL
+      && DECL_BIT_FIELD_TYPE (field) != NULL_TREE
+      && (TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))
+         != TYPE_MAIN_VARIANT (type))
+      && TREE_CODE (DECL_BIT_FIELD_TYPE (field)) == ENUMERAL_TYPE)
+    {
+      tree checktype = origtype != NULL_TREE ? origtype : TREE_TYPE (value);
+      if (checktype != error_mark_node
+         && (TYPE_MAIN_VARIANT (checktype)
+             != TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))))
+       warning_init (OPT_Wc___compat,
+                     "enum conversion in initialization is invalid in C++");
+    }
+
   /* If this field is empty (and not at the end of structure),
      don't do anything other than checking the initializer.  */
   if (field
@@ -6857,8 +7456,8 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
 
   if (semantic_type)
     value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
-  value = digest_init (type, value, npc, strict_string,
-                      require_constant_value);
+  value = digest_init (input_location, type, value, origtype, npc,
+                      strict_string, require_constant_value);
   if (value == error_mark_node)
     {
       constructor_erroneous = 1;
@@ -6877,7 +7476,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
          && tree_int_cst_lt (field, constructor_unfilled_index))
        set_nonincremental_init ();
 
-      add_pending_init (field, value, implicit);
+      add_pending_init (field, value, origtype, implicit);
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -6903,7 +7502,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
            }
        }
 
-      add_pending_init (field, value, implicit);
+      add_pending_init (field, value, origtype, implicit);
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
@@ -6933,8 +7532,8 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     constructor_unfilled_index
-      = size_binop (PLUS_EXPR, constructor_unfilled_index,
-                   bitsize_one_node);
+      = size_binop_loc (input_location, PLUS_EXPR, constructor_unfilled_index,
+                       bitsize_one_node);
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
@@ -6986,7 +7585,7 @@ output_pending_init_elements (int all)
        {
          if (tree_int_cst_equal (elt->purpose,
                                  constructor_unfilled_index))
-           output_init_element (elt->value, true,
+           output_init_element (elt->value, elt->origtype, true,
                                 TREE_TYPE (constructor_type),
                                 constructor_unfilled_index, 0, false);
          else if (tree_int_cst_lt (constructor_unfilled_index,
@@ -7040,7 +7639,8 @@ output_pending_init_elements (int all)
          if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
            {
              constructor_unfilled_fields = elt->purpose;
-             output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
+             output_init_element (elt->value, elt->origtype, true,
+                                  TREE_TYPE (elt->purpose),
                                   elt->purpose, 0, false);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
@@ -7154,7 +7754,8 @@ process_init_element (struct c_expr value, bool implicit)
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
        process_init_element (pop_init_level (1), true);
-      else if (TREE_CODE (constructor_type) == ARRAY_TYPE
+      else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
+               || TREE_CODE (constructor_type) == VECTOR_TYPE)
               && (constructor_max_index == 0
                   || tree_int_cst_lt (constructor_max_index,
                                       constructor_index)))
@@ -7226,7 +7827,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
-                      || fieldcode == UNION_TYPE))
+                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
              push_init_level (1);
              continue;
@@ -7235,8 +7836,9 @@ process_init_element (struct c_expr value, bool implicit)
          if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value.value, strict_string,
-                                  fieldtype, constructor_fields, 1, implicit);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, fieldtype,
+                                  constructor_fields, 1, implicit);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7246,9 +7848,9 @@ process_init_element (struct c_expr value, bool implicit)
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
                constructor_bit_index
-                 = size_binop (PLUS_EXPR,
-                               bit_position (constructor_fields),
-                               DECL_SIZE (constructor_fields));
+                 = size_binop_loc (input_location, PLUS_EXPR,
+                                   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.  */
@@ -7316,7 +7918,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
-                      || fieldcode == UNION_TYPE))
+                      || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
              push_init_level (1);
              continue;
@@ -7325,8 +7927,9 @@ process_init_element (struct c_expr value, bool implicit)
          if (value.value)
            {
              push_member_name (constructor_fields);
-             output_init_element (value.value, strict_string,
-                                  fieldtype, constructor_fields, 1, implicit);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, fieldtype,
+                                  constructor_fields, 1, implicit);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7356,7 +7959,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && value.value != error_mark_node
                   && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
-                      || eltcode == UNION_TYPE))
+                      || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
              push_init_level (1);
              continue;
@@ -7375,13 +7978,15 @@ process_init_element (struct c_expr value, bool implicit)
          if (value.value)
            {
              push_array_bounds (tree_low_cst (constructor_index, 1));
-             output_init_element (value.value, strict_string,
-                                  elttype, constructor_index, 1, implicit);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, elttype,
+                                  constructor_index, 1, implicit);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
          constructor_index
-           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+           = size_binop_loc (input_location, PLUS_EXPR,
+                             constructor_index, bitsize_one_node);
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
@@ -7404,11 +8009,17 @@ process_init_element (struct c_expr value, bool implicit)
 
          /* Now output the actual element.  */
          if (value.value)
-           output_init_element (value.value, strict_string,
-                                elttype, constructor_index, 1, implicit);
+           {
+             if (TREE_CODE (value.value) == VECTOR_CST)
+               elttype = TYPE_MAIN_VARIANT (constructor_type);
+             output_init_element (value.value, value.original_type,
+                                  strict_string, elttype,
+                                  constructor_index, 1, implicit);
+           }
 
          constructor_index
-           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+           = size_binop_loc (input_location,
+                             PLUS_EXPR, constructor_index, bitsize_one_node);
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
@@ -7429,8 +8040,9 @@ process_init_element (struct c_expr value, bool implicit)
       else
        {
          if (value.value)
-           output_init_element (value.value, strict_string,
-                                constructor_type, NULL_TREE, 1, implicit);
+           output_init_element (value.value, value.original_type,
+                                strict_string, constructor_type,
+                                NULL_TREE, 1, implicit);
          constructor_fields = 0;
        }
 
@@ -7456,7 +8068,8 @@ process_init_element (struct c_expr value, bool implicit)
              process_init_element (pop_init_level (1), true);
            }
 
-         p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
+         p->index = size_binop_loc (input_location,
+                                    PLUS_EXPR, p->index, bitsize_one_node);
          if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
            finish = 1;
 
@@ -7506,8 +8119,8 @@ build_asm_stmt (tree cv_qualifier, tree args)
    string in the asm expression -- asm("blah") and asm("blah" : )
    are subtly different.  We use a ASM_EXPR node to represent this.  */
 tree
-build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
-               bool simple)
+build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
+               tree clobbers, tree labels, bool simple)
 {
   tree tail;
   tree args;
@@ -7521,7 +8134,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
   noutputs = list_length (outputs);
   oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
 
-  string = resolve_asm_operand_names (string, outputs, inputs);
+  string = resolve_asm_operand_names (string, outputs, inputs, labels);
 
   /* Remove output conversions that change the type but not the mode.  */
   for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
@@ -7591,7 +8204,11 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
       TREE_VALUE (tail) = input;
     }
 
-  args = build_stmt (ASM_EXPR, string, outputs, inputs, clobbers);
+  /* ASMs with labels cannot have outputs.  This should have been
+     enforced by the parser.  */
+  gcc_assert (outputs == NULL || labels == NULL);
+
+  args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
 
   /* asm statements without outputs, including simple ones, are treated
      as volatile.  */
@@ -7601,77 +8218,53 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
   return args;
 }
 \f
-/* Generate a goto statement to LABEL.  */
+/* Generate a goto statement to LABEL.  LOC is the location of the
+   GOTO.  */
 
 tree
-c_finish_goto_label (tree label)
+c_finish_goto_label (location_t loc, tree label)
 {
-  tree decl = lookup_label (label);
+  tree decl = lookup_label_for_goto (loc, label);
   if (!decl)
     return NULL_TREE;
-
-  if (C_DECL_UNJUMPABLE_STMT_EXPR (decl))
-    {
-      error ("jump into statement expression");
-      return NULL_TREE;
-    }
-
-  if (C_DECL_UNJUMPABLE_VM (decl))
-    {
-      error ("jump into scope of identifier with variably modified type");
-      return NULL_TREE;
-    }
-
-  if (!C_DECL_UNDEFINABLE_STMT_EXPR (decl))
-    {
-      /* No jump from outside this statement expression context, so
-        record that there is a jump from within this context.  */
-      struct c_label_list *nlist;
-      nlist = XOBNEW (&parser_obstack, struct c_label_list);
-      nlist->next = label_context_stack_se->labels_used;
-      nlist->label = decl;
-      label_context_stack_se->labels_used = nlist;
-    }
-
-  if (!C_DECL_UNDEFINABLE_VM (decl))
-    {
-      /* No jump from outside this context context of identifiers with
-        variably modified type, so record that there is a jump from
-        within this context.  */
-      struct c_label_list *nlist;
-      nlist = XOBNEW (&parser_obstack, struct c_label_list);
-      nlist->next = label_context_stack_vm->labels_used;
-      nlist->label = decl;
-      label_context_stack_vm->labels_used = nlist;
-    }
-
   TREE_USED (decl) = 1;
-  return add_stmt (build1 (GOTO_EXPR, void_type_node, decl));
+  {
+    tree t = build1 (GOTO_EXPR, void_type_node, decl);
+    SET_EXPR_LOCATION (t, loc);
+    return add_stmt (t);
+  }
 }
 
-/* Generate a computed goto statement to EXPR.  */
+/* Generate a computed goto statement to EXPR.  LOC is the location of
+   the GOTO.  */
 
 tree
-c_finish_goto_ptr (tree expr)
+c_finish_goto_ptr (location_t loc, tree expr)
 {
-  pedwarn (input_location, OPT_pedantic, "ISO C forbids %<goto *expr;%>");
+  tree t;
+  pedwarn (loc, OPT_pedantic, "ISO C forbids %<goto *expr;%>");
   expr = c_fully_fold (expr, false, NULL);
   expr = convert (ptr_type_node, expr);
-  return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
+  t = build1 (GOTO_EXPR, void_type_node, expr);
+  SET_EXPR_LOCATION (t, loc);
+  return add_stmt (t);
 }
 
 /* Generate a C `return' statement.  RETVAL is the expression for what
-   to return, or a null pointer for `return;' with no value.  */
+   to return, or a null pointer for `return;' with no value.  LOC is
+   the location of the return statement.  If ORIGTYPE is not NULL_TREE, it
+   is the original type of RETVAL.  */
 
 tree
-c_finish_return (tree retval)
+c_finish_return (location_t loc, tree retval, tree origtype)
 {
   tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt;
   bool no_warning = false;
   bool npc = false;
 
   if (TREE_THIS_VOLATILE (current_function_decl))
-    warning (0, "function declared %<noreturn%> has a %<return%> statement");
+    warning_at (loc, 0,
+               "function declared %<noreturn%> has a %<return%> statement");
 
   if (retval)
     {
@@ -7693,7 +8286,7 @@ c_finish_return (tree retval)
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
        {
-         pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wreturn_type, 
+         pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type,
                       "%<return%> with no value, in "
                       "function returning non-void");
          no_warning = true;
@@ -7703,16 +8296,17 @@ c_finish_return (tree retval)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn (input_location, 0, 
+       pedwarn (loc, 0,
                 "%<return%> with a value, in function returning void");
-      else 
-       pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+      else
+       pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
   else
     {
-      tree t = convert_for_assignment (valtype, retval, ic_return, npc,
-                                      NULL_TREE, NULL_TREE, 0);
+      tree t = convert_for_assignment (loc, valtype, retval, origtype,
+                                      ic_return,
+                                      npc, NULL_TREE, NULL_TREE, 0);
       tree res = DECL_RESULT (current_function_decl);
       tree inner;
 
@@ -7765,7 +8359,8 @@ c_finish_return (tree retval)
                  && !DECL_EXTERNAL (inner)
                  && !TREE_STATIC (inner)
                  && DECL_CONTEXT (inner) == current_function_decl)
-               warning (0, "function returns address of local variable");
+               warning_at (loc,
+                           0, "function returns address of local variable");
              break;
 
            default:
@@ -7776,12 +8371,13 @@ c_finish_return (tree retval)
        }
 
       retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
+      SET_EXPR_LOCATION (retval, loc);
 
       if (warn_sequence_point)
        verify_sequence_points (retval);
     }
 
-  ret_stmt = build_stmt (RETURN_EXPR, retval);
+  ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
   TREE_NO_WARNING (ret_stmt) |= no_warning;
   return add_stmt (ret_stmt);
 }
@@ -7801,15 +8397,9 @@ struct c_switch {
      of the GNU case range extension.  */
   splay_tree cases;
 
-  /* Number of nested statement expressions within this switch
-     statement; if nonzero, case and default labels may not
-     appear.  */
-  unsigned int blocked_stmt_expr;
-
-  /* Scope of outermost declarations of identifiers with variably
-     modified type within this switch statement; if nonzero, case and
-     default labels may not appear.  */
-  unsigned int blocked_vm;
+  /* The bindings at the point of the switch.  This is used for
+     warnings crossing decls when branching to a case label.  */
+  struct c_spot_bindings *bindings;
 
   /* The next node on the stack.  */
   struct c_switch *next;
@@ -7824,10 +8414,13 @@ struct c_switch {
 struct c_switch *c_switch_stack;
 
 /* Start a C switch statement, testing expression EXP.  Return the new
-   SWITCH_EXPR.  */
+   SWITCH_EXPR.  SWITCH_LOC is the location of the `switch'.
+   SWITCH_COND_LOC is the location of the switch's condition.  */
 
 tree
-c_start_case (tree exp)
+c_start_case (location_t switch_loc,
+             location_t switch_cond_loc,
+             tree exp)
 {
   tree orig_type = error_mark_node;
   struct c_switch *cs;
@@ -7840,7 +8433,7 @@ c_start_case (tree exp)
        {
          if (orig_type != error_mark_node)
            {
-             error ("switch quantity not an integer");
+             error_at (switch_cond_loc, "switch quantity not an integer");
              orig_type = error_mark_node;
            }
          exp = integer_zero_node;
@@ -7852,8 +8445,9 @@ c_start_case (tree exp)
          if (!in_system_header
              && (type == long_integer_type_node
                  || type == long_unsigned_type_node))
-           warning (OPT_Wtraditional, "%<long%> switch expression not "
-                    "converted to %<int%> in ISO C");
+           warning_at (switch_cond_loc,
+                       OPT_Wtraditional, "%<long%> switch expression not "
+                       "converted to %<int%> in ISO C");
 
          exp = c_fully_fold (exp, false, NULL);
          exp = default_conversion (exp);
@@ -7866,20 +8460,20 @@ c_start_case (tree exp)
   /* Add this new SWITCH_EXPR to the stack.  */
   cs = XNEW (struct c_switch);
   cs->switch_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE);
+  SET_EXPR_LOCATION (cs->switch_expr, switch_loc);
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
-  cs->blocked_stmt_expr = 0;
-  cs->blocked_vm = 0;
+  cs->bindings = c_get_switch_bindings ();
   cs->next = c_switch_stack;
   c_switch_stack = cs;
 
   return add_stmt (cs->switch_expr);
 }
 
-/* Process a case label.  */
+/* Process a case label at location LOC.  */
 
 tree
-do_case (tree low_value, tree high_value)
+do_case (location_t loc, tree low_value, tree high_value)
 {
   tree label = NULL_TREE;
 
@@ -7899,39 +8493,26 @@ do_case (tree low_value, tree high_value)
                 "case label is not an integer constant expression");
     }
 
-  if (c_switch_stack && !c_switch_stack->blocked_stmt_expr
-      && !c_switch_stack->blocked_vm)
-    {
-      label = c_add_case_label (c_switch_stack->cases,
-                               SWITCH_COND (c_switch_stack->switch_expr),
-                               c_switch_stack->orig_type,
-                               low_value, high_value);
-      if (label == error_mark_node)
-       label = NULL_TREE;
-    }
-  else if (c_switch_stack && c_switch_stack->blocked_stmt_expr)
-    {
-      if (low_value)
-       error ("case label in statement expression not containing "
-              "enclosing switch statement");
-      else
-       error ("%<default%> label in statement expression not containing "
-              "enclosing switch statement");
-    }
-  else if (c_switch_stack && c_switch_stack->blocked_vm)
+  if (c_switch_stack == NULL)
     {
       if (low_value)
-       error ("case label in scope of identifier with variably modified "
-              "type not containing enclosing switch statement");
+       error_at (loc, "case label not within a switch statement");
       else
-       error ("%<default%> label in scope of identifier with variably "
-              "modified type not containing enclosing switch statement");
+       error_at (loc, "%<default%> label not within a switch statement");
+      return NULL_TREE;
     }
-  else if (low_value)
-    error ("case label not within a switch statement");
-  else
-    error ("%<default%> label not within a switch statement");
 
+  if (c_check_switch_jump_warnings (c_switch_stack->bindings,
+                                   EXPR_LOCATION (c_switch_stack->switch_expr),
+                                   loc))
+    return NULL_TREE;
+
+  label = c_add_case_label (loc, c_switch_stack->cases,
+                           SWITCH_COND (c_switch_stack->switch_expr),
+                           c_switch_stack->orig_type,
+                           low_value, high_value);
+  if (label == error_mark_node)
+    label = NULL_TREE;
   return label;
 }
 
@@ -7945,16 +8526,8 @@ c_finish_case (tree body)
 
   SWITCH_BODY (cs->switch_expr) = body;
 
-  /* We must not be within a statement expression nested in the switch
-     at this point; we might, however, be within the scope of an
-     identifier with variably modified type nested in the switch.  */
-  gcc_assert (!cs->blocked_stmt_expr);
-
   /* Emit warnings as needed.  */
-  if (EXPR_HAS_LOCATION (cs->switch_expr))
-    switch_location = EXPR_LOCATION (cs->switch_expr);
-  else
-    switch_location = input_location;
+  switch_location = EXPR_LOCATION (cs->switch_expr);
   c_do_switch_warnings (cs->cases, switch_location,
                        TREE_TYPE (cs->switch_expr),
                        SWITCH_COND (cs->switch_expr));
@@ -7962,6 +8535,7 @@ c_finish_case (tree body)
   /* Pop the stack.  */
   c_switch_stack = cs->next;
   splay_tree_delete (cs->cases);
+  c_release_switch_bindings (cs->bindings);
   XDELETE (cs);
 }
 \f
@@ -8006,9 +8580,8 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
     found:
 
       if (COND_EXPR_ELSE (inner_if))
-        warning (OPT_Wparentheses,
-                 "%Hsuggest explicit braces to avoid ambiguous %<else%>",
-                 &if_locus);
+        warning_at (if_locus, OPT_Wparentheses,
+                    "suggest explicit braces to avoid ambiguous %<else%>");
     }
 
   stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
@@ -8066,11 +8639,12 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
            }
 
          t = build_and_jump (&blab);
-         exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
          if (cond_is_first)
-           SET_EXPR_LOCATION (exit, start_locus);
+           exit = fold_build3_loc (start_locus,
+                               COND_EXPR, void_type_node, cond, exit, t);
          else
-           SET_EXPR_LOCATION (exit, input_location);
+           exit = fold_build3_loc (input_location,
+                               COND_EXPR, void_type_node, cond, exit, t);
        }
 
       add_stmt (top);
@@ -8091,7 +8665,7 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
 }
 
 tree
-c_finish_bc_stmt (tree *label_p, bool is_break)
+c_finish_bc_stmt (location_t loc, tree *label_p, bool is_break)
 {
   bool skip;
   tree label = *label_p;
@@ -8108,7 +8682,7 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
   if (!label)
     {
       if (!skip)
-       *label_p = label = create_artificial_label ();
+       *label_p = label = create_artificial_label (loc);
     }
   else if (TREE_CODE (label) == LABEL_DECL)
     ;
@@ -8116,14 +8690,14 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
     {
     case 0:
       if (is_break)
-       error ("break statement not within loop or switch");
+       error_at (loc, "break statement not within loop or switch");
       else
-       error ("continue statement not within a loop");
+       error_at (loc, "continue statement not within a loop");
       return NULL_TREE;
 
     case 1:
       gcc_assert (is_break);
-      error ("break statement used with OpenMP for loop");
+      error_at (loc, "break statement used with OpenMP for loop");
       return NULL_TREE;
 
     default:
@@ -8142,25 +8716,25 @@ c_finish_bc_stmt (tree *label_p, bool is_break)
 /* A helper routine for c_process_expr_stmt and c_finish_stmt_expr.  */
 
 static void
-emit_side_effect_warnings (tree expr)
+emit_side_effect_warnings (location_t loc, tree expr)
 {
   if (expr == error_mark_node)
     ;
   else if (!TREE_SIDE_EFFECTS (expr))
     {
       if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
-       warning (OPT_Wunused_value, "%Hstatement with no effect",
-                EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
+       warning_at (loc, OPT_Wunused_value, "statement with no effect");
     }
   else
-    warn_if_unused_value (expr, input_location);
+    warn_if_unused_value (expr, loc);
 }
 
 /* Process an expression as if it were a complete statement.  Emit
-   diagnostics, but do not call ADD_STMT.  */
+   diagnostics, but do not call ADD_STMT.  LOC is the location of the
+   statement.  */
 
 tree
-c_process_expr_stmt (tree expr)
+c_process_expr_stmt (location_t loc, tree expr)
 {
   if (!expr)
     return NULL_TREE;
@@ -8173,33 +8747,34 @@ c_process_expr_stmt (tree expr)
   if (TREE_TYPE (expr) != error_mark_node
       && !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
       && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
-    error ("expression statement has incomplete type");
+    error_at (loc, "expression statement has incomplete type");
 
   /* If we're not processing a statement expression, warn about unused values.
      Warnings for statement expressions will be emitted later, once we figure
      out which is the result.  */
   if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
       && warn_unused_value)
-    emit_side_effect_warnings (expr);
+    emit_side_effect_warnings (loc, expr);
 
   /* If the expression is not of a type to which we cannot assign a line
      number, wrap the thing in a no-op NOP_EXPR.  */
   if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
-    expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
-
-  if (CAN_HAVE_LOCATION_P (expr))
-    SET_EXPR_LOCATION (expr, input_location);
+    {
+      expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
+      SET_EXPR_LOCATION (expr, loc);
+    }
 
   return expr;
 }
 
-/* Emit an expression as a statement.  */
+/* Emit an expression as a statement.  LOC is the location of the
+   expression.  */
 
 tree
-c_finish_expr_stmt (tree expr)
+c_finish_expr_stmt (location_t loc, tree expr)
 {
   if (expr)
-    return add_stmt (c_process_expr_stmt (expr));
+    return add_stmt (c_process_expr_stmt (loc, expr));
   else
     return NULL;
 }
@@ -8211,30 +8786,16 @@ tree
 c_begin_stmt_expr (void)
 {
   tree ret;
-  struct c_label_context_se *nstack;
-  struct c_label_list *glist;
 
   /* We must force a BLOCK for this level so that, if it is not expanded
      later, there is a way to turn off the entire subtree of blocks that
      are contained in it.  */
   keep_next_level ();
   ret = c_begin_compound_stmt (true);
-  if (c_switch_stack)
-    {
-      c_switch_stack->blocked_stmt_expr++;
-      gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
-    }
-  for (glist = label_context_stack_se->labels_used;
-       glist != NULL;
-       glist = glist->next)
-    {
-      C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 1;
-    }
-  nstack = XOBNEW (&parser_obstack, struct c_label_context_se);
-  nstack->labels_def = NULL;
-  nstack->labels_used = NULL;
-  nstack->next = label_context_stack_se;
-  label_context_stack_se = nstack;
+
+  c_bindings_start_stmt_expr (c_switch_stack == NULL
+                             ? NULL
+                             : c_switch_stack->bindings);
 
   /* Mark the current statement list as belonging to a statement list.  */
   STATEMENT_LIST_STMT_EXPR (ret) = 1;
@@ -8242,42 +8803,20 @@ c_begin_stmt_expr (void)
   return ret;
 }
 
+/* LOC is the location of the compound statement to which this body
+   belongs.  */
+
 tree
-c_finish_stmt_expr (tree body)
+c_finish_stmt_expr (location_t loc, tree body)
 {
   tree last, type, tmp, val;
   tree *last_p;
-  struct c_label_list *dlist, *glist, *glist_prev = NULL;
 
-  body = c_end_compound_stmt (body, true);
-  if (c_switch_stack)
-    {
-      gcc_assert (c_switch_stack->blocked_stmt_expr != 0);
-      c_switch_stack->blocked_stmt_expr--;
-    }
-  /* It is no longer possible to jump to labels defined within this
-     statement expression.  */
-  for (dlist = label_context_stack_se->labels_def;
-       dlist != NULL;
-       dlist = dlist->next)
-    {
-      C_DECL_UNJUMPABLE_STMT_EXPR (dlist->label) = 1;
-    }
-  /* It is again possible to define labels with a goto just outside
-     this statement expression.  */
-  for (glist = label_context_stack_se->next->labels_used;
-       glist != NULL;
-       glist = glist->next)
-    {
-      C_DECL_UNDEFINABLE_STMT_EXPR (glist->label) = 0;
-      glist_prev = glist;
-    }
-  if (glist_prev != NULL)
-    glist_prev->next = label_context_stack_se->labels_used;
-  else
-    label_context_stack_se->next->labels_used
-      = label_context_stack_se->labels_used;
-  label_context_stack_se = label_context_stack_se->next;
+  body = c_end_compound_stmt (loc, body, true);
+
+  c_bindings_end_stmt_expr (c_switch_stack == NULL
+                           ? NULL
+                           : c_switch_stack->bindings);
 
   /* Locate the last statement in BODY.  See c_end_compound_stmt
      about always returning a BIND_EXPR.  */
@@ -8298,7 +8837,13 @@ c_finish_stmt_expr (tree body)
       if (warn_unused_value)
        {
          for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
-           emit_side_effect_warnings (tsi_stmt (i));
+           {
+             location_t tloc;
+             tree t = tsi_stmt (i);
+
+             tloc = EXPR_HAS_LOCATION (t) ? EXPR_LOCATION (t) : loc;
+             emit_side_effect_warnings (tloc, t);
+           }
        }
       else
        i = tsi_last (last);
@@ -8316,16 +8861,17 @@ c_finish_stmt_expr (tree body)
       goto continue_searching;
     }
 
+  if (last == error_mark_node)
+    return last;
+
   /* In the case that the BIND_EXPR is not necessary, return the
      expression out from inside it.  */
-  if (last == error_mark_node
-      || (last == BIND_EXPR_BODY (body)
-         && BIND_EXPR_VARS (body) == NULL))
+  if (last == BIND_EXPR_BODY (body)
+      && BIND_EXPR_VARS (body) == NULL)
     {
       /* Even if this looks constant, do not allow it in a constant
         expression.  */
-      last = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (last), NULL_TREE, last);
-      C_MAYBE_CONST_EXPR_NON_CONST (last) = 1;
+      last = c_wrap_maybe_const (last, true);
       /* Do not warn if the return value of a statement expression is
         unused.  */
       TREE_NO_WARNING (last) = 1;
@@ -8353,83 +8899,13 @@ c_finish_stmt_expr (tree body)
     val = TREE_OPERAND (val, 0);
 
   *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
-  SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
-
-  return build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
-}
-
-/* Begin the scope of an identifier of variably modified type, scope
-   number SCOPE.  Jumping from outside this scope to inside it is not
-   permitted.  */
-
-void
-c_begin_vm_scope (unsigned int scope)
-{
-  struct c_label_context_vm *nstack;
-  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;
+  SET_EXPR_LOCATION (*last_p, EXPR_LOCATION (last));
 
-  if (c_switch_stack && !c_switch_stack->blocked_vm)
-    c_switch_stack->blocked_vm = scope;
-  for (glist = label_context_stack_vm->labels_used;
-       glist != NULL;
-       glist = glist->next)
-    {
-      C_DECL_UNDEFINABLE_VM (glist->label) = 1;
-    }
-  nstack = XOBNEW (&parser_obstack, struct c_label_context_vm);
-  nstack->labels_def = NULL;
-  nstack->labels_used = NULL;
-  nstack->scope = scope;
-  nstack->next = label_context_stack_vm;
-  label_context_stack_vm = nstack;
-}
-
-/* End a scope which may contain identifiers of variably modified
-   type, scope number SCOPE.  */
-
-void
-c_end_vm_scope (unsigned int scope)
-{
-  if (label_context_stack_vm == NULL)
-    return;
-  if (c_switch_stack && c_switch_stack->blocked_vm == scope)
-    c_switch_stack->blocked_vm = 0;
-  /* We may have a number of nested scopes of identifiers with
-     variably modified type, all at this depth.  Pop each in turn.  */
-  while (label_context_stack_vm->scope == scope)
-    {
-      struct c_label_list *dlist, *glist, *glist_prev = NULL;
-
-      /* It is no longer possible to jump to labels defined within this
-        scope.  */
-      for (dlist = label_context_stack_vm->labels_def;
-          dlist != NULL;
-          dlist = dlist->next)
-       {
-         C_DECL_UNJUMPABLE_VM (dlist->label) = 1;
-       }
-      /* It is again possible to define labels with a goto just outside
-        this scope.  */
-      for (glist = label_context_stack_vm->next->labels_used;
-          glist != NULL;
-          glist = glist->next)
-       {
-         C_DECL_UNDEFINABLE_VM (glist->label) = 0;
-         glist_prev = glist;
-       }
-      if (glist_prev != NULL)
-       glist_prev->next = label_context_stack_vm->labels_used;
-      else
-       label_context_stack_vm->next->labels_used
-         = label_context_stack_vm->labels_used;
-      label_context_stack_vm = label_context_stack_vm->next;
-    }
+  {
+    tree t = build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
+    SET_EXPR_LOCATION (t, loc);
+    return t;
+  }
 }
 \f
 /* Begin and end compound statements.  This is as simple as pushing
@@ -8444,8 +8920,12 @@ c_begin_compound_stmt (bool do_scope)
   return stmt;
 }
 
+/* End a compound statement.  STMT is the statement.  LOC is the
+   location of the compound statement-- this is usually the location
+   of the opening brace.  */
+
 tree
-c_end_compound_stmt (tree stmt, bool do_scope)
+c_end_compound_stmt (location_t loc, tree stmt, bool do_scope)
 {
   tree block = NULL;
 
@@ -8457,7 +8937,7 @@ c_end_compound_stmt (tree stmt, bool do_scope)
     }
 
   stmt = pop_stmt_list (stmt);
-  stmt = c_build_bind_expr (block, stmt);
+  stmt = c_build_bind_expr (loc, block, stmt);
 
   /* If this compound statement is nested immediately inside a statement
      expression, then force a BIND_EXPR to be created.  Otherwise we'll
@@ -8470,6 +8950,7 @@ c_end_compound_stmt (tree stmt, bool do_scope)
     {
       stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
       TREE_SIDE_EFFECTS (stmt) = 1;
+      SET_EXPR_LOCATION (stmt, loc);
     }
 
   return stmt;
@@ -8480,14 +8961,14 @@ c_end_compound_stmt (tree stmt, bool do_scope)
    meant to apply to normal control flow transfer.  */
 
 void
-push_cleanup (tree ARG_UNUSED (decl), tree cleanup, bool eh_only)
+push_cleanup (tree decl, tree cleanup, bool eh_only)
 {
   enum tree_code code;
   tree stmt, list;
   bool stmt_expr;
 
   code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
-  stmt = build_stmt (code, NULL, cleanup);
+  stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup);
   add_stmt (stmt);
   stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
   list = push_stmt_list ();
@@ -8695,9 +9176,9 @@ build_binary_op (location_t location, enum tree_code code,
       /* 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))
+         && comp_target_types (location, type0, type1))
        {
-         ret = pointer_diff (op0, op1);
+         ret = pointer_diff (location, op0, op1);
          goto return_build_binary_op;
        }
       /* Handle pointer minus int.  Just like pointer plus int.  */
@@ -8768,7 +9249,11 @@ build_binary_op (location_t location, enum tree_code code,
     case FLOOR_MOD_EXPR:
       warn_for_div_by_zero (location, op1);
 
-      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+         && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+       common = 1;
+      else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
        {
          /* Although it would be tempting to shorten always here, that loses
             on some targets, since the modulo instruction is undefined if the
@@ -8838,7 +9323,7 @@ build_binary_op (location_t location, enum tree_code code,
              if (tree_int_cst_sgn (op1) < 0)
                {
                  int_const = false;
-                 if (skip_evaluation == 0)
+                 if (c_inhibit_evaluation_warnings == 0)
                    warning (0, "right shift count is negative");
                }
              else
@@ -8849,7 +9334,7 @@ build_binary_op (location_t location, enum tree_code code,
                  if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                    {
                      int_const = false;
-                     if (skip_evaluation == 0)
+                     if (c_inhibit_evaluation_warnings == 0)
                        warning (0, "right shift count >= width of type");
                    }
                }
@@ -8875,14 +9360,14 @@ build_binary_op (location_t location, enum tree_code code,
              if (tree_int_cst_sgn (op1) < 0)
                {
                  int_const = false;
-                 if (skip_evaluation == 0)
+                 if (c_inhibit_evaluation_warnings == 0)
                    warning (0, "left shift count is negative");
                }
 
              else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
                {
                  int_const = false;
-                 if (skip_evaluation == 0)
+                 if (c_inhibit_evaluation_warnings == 0)
                    warning (0, "left shift count >= width of type");
                }
            }
@@ -8916,24 +9401,34 @@ build_binary_op (location_t location, enum tree_code code,
        {
          tree tt0 = TREE_TYPE (type0);
          tree tt1 = TREE_TYPE (type1);
+         addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
+         addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
+         addr_space_t as_common = ADDR_SPACE_GENERIC;
+
          /* 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))
+         if (comp_target_types (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
+         else if (null_pointer_constant_p (orig_op0))
+           result_type = type1;
+         else if (null_pointer_constant_p (orig_op1))
+           result_type = type0;
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
          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 && !null_pointer_constant_p (orig_op0)
-                 && TREE_CODE (tt1) == FUNCTION_TYPE)
+             if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
-             if (pedantic && !null_pointer_constant_p (orig_op1)
-                 && TREE_CODE (tt0) == FUNCTION_TYPE)
+             if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
@@ -8944,7 +9439,11 @@ build_binary_op (location_t location, enum tree_code code,
                       "comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
-           result_type = ptr_type_node;
+           {
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
+           }
        }
       else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
@@ -8988,7 +9487,11 @@ build_binary_op (location_t location, enum tree_code code,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
-         if (comp_target_types (type0, type1))
+         addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
+         addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+         addr_space_t as_common;
+
+         if (comp_target_types (location, type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
              if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
@@ -8999,9 +9502,17 @@ build_binary_op (location_t location, enum tree_code code,
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "ordered comparisons of pointers to functions");
            }
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
          else
            {
-             result_type = ptr_type_node;
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
              pedwarn (location, 0,
                       "comparison of distinct pointer types lacks a cast");
            }
@@ -9010,7 +9521,7 @@ build_binary_op (location_t location, enum tree_code code,
        {
          result_type = type0;
          if (pedantic)
-           pedwarn (location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ordered comparison of pointer with integer zero");
          else if (extra_warnings)
            warning_at (location, OPT_Wextra,
@@ -9019,7 +9530,7 @@ build_binary_op (location_t location, enum tree_code code,
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -9056,7 +9567,9 @@ build_binary_op (location_t location, enum tree_code code,
       (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
        || code1 == FIXED_POINT_TYPE || code1 == VECTOR_TYPE))
     {
-      int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+      bool first_complex = (code0 == COMPLEX_TYPE);
+      bool second_complex = (code1 == COMPLEX_TYPE);
+      int none_complex = (!first_complex && !second_complex);
 
       if (shorten || common || short_compare)
        {
@@ -9065,6 +9578,89 @@ build_binary_op (location_t location, enum tree_code code,
            return error_mark_node;
        }
 
+      if (first_complex != second_complex
+         && (code == PLUS_EXPR
+             || code == MINUS_EXPR
+             || code == MULT_EXPR
+             || (code == TRUNC_DIV_EXPR && first_complex))
+         && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE
+         && flag_signed_zeros)
+       {
+         /* An operation on mixed real/complex operands must be
+            handled specially, but the language-independent code can
+            more easily optimize the plain complex arithmetic if
+            -fno-signed-zeros.  */
+         tree real_type = TREE_TYPE (result_type);
+         tree real, imag;
+         if (type0 != orig_type0 || type1 != orig_type1)
+           {
+             gcc_assert (may_need_excess_precision && common);
+             real_result_type = c_common_type (orig_type0, orig_type1);
+           }
+         if (first_complex)
+           {
+             if (TREE_TYPE (op0) != result_type)
+               op0 = convert_and_check (result_type, op0);
+             if (TREE_TYPE (op1) != real_type)
+               op1 = convert_and_check (real_type, op1);
+           }
+         else
+           {
+             if (TREE_TYPE (op0) != real_type)
+               op0 = convert_and_check (real_type, op0);
+             if (TREE_TYPE (op1) != result_type)
+               op1 = convert_and_check (result_type, op1);
+           }
+         if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+           return error_mark_node;
+         if (first_complex)
+           {
+             op0 = c_save_expr (op0);
+             real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
+                                    op0, 1);
+             imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
+                                    op0, 1);
+             switch (code)
+               {
+               case MULT_EXPR:
+               case TRUNC_DIV_EXPR:
+                 imag = build2 (resultcode, real_type, imag, op1);
+                 /* Fall through.  */
+               case PLUS_EXPR:
+               case MINUS_EXPR:
+                 real = build2 (resultcode, real_type, real, op1);
+                 break;
+               default:
+                 gcc_unreachable();
+               }
+           }
+         else
+           {
+             op1 = c_save_expr (op1);
+             real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
+                                    op1, 1);
+             imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR,
+                                    op1, 1);
+             switch (code)
+               {
+               case MULT_EXPR:
+                 imag = build2 (resultcode, real_type, op0, imag);
+                 /* Fall through.  */
+               case PLUS_EXPR:
+                 real = build2 (resultcode, real_type, op0, real);
+                 break;
+               case MINUS_EXPR:
+                 real = build2 (resultcode, real_type, op0, real);
+                 imag = build1 (NEGATE_EXPR, real_type, imag);
+                 break;
+               default:
+                 gcc_unreachable();
+               }
+           }
+         ret = build2 (COMPLEX_EXPR, result_type, real, imag);
+         goto return_build_binary_op;
+       }
+
       /* For certain operations (which identify themselves by shorten != 0)
         if both args were extended from the same smaller type,
         do the arithmetic in that type and then extend.
@@ -9079,7 +9675,7 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten && none_complex)
        {
          final_type = result_type;
-         result_type = shorten_binary_op (result_type, op0, op1, 
+         result_type = shorten_binary_op (result_type, op0, op1,
                                           shorten == -1);
        }
 
@@ -9096,6 +9692,7 @@ build_binary_op (location_t location, enum tree_code code,
            unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
 
          if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
+             && tree_int_cst_sgn (op1) > 0
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
              && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
@@ -9137,7 +9734,7 @@ build_binary_op (location_t location, enum tree_code code,
          converted = 1;
          resultcode = xresultcode;
 
-         if (!skip_evaluation)
+         if (c_inhibit_evaluation_warnings == 0)
            {
              bool op0_maybe_const = true;
              bool op1_maybe_const = true;
@@ -9154,10 +9751,12 @@ build_binary_op (location_t location, enum tree_code code,
                     build_conditional_expr.  This requires the
                     "original" values to be folded, not just op0 and
                     op1.  */
+                 c_inhibit_evaluation_warnings++;
                  op0 = c_fully_fold (op0, require_constant_value,
                                      &op0_maybe_const);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings--;
                  orig_op0_folded = c_fully_fold (orig_op0,
                                                  require_constant_value,
                                                  NULL);
@@ -9173,17 +9772,9 @@ build_binary_op (location_t location, enum tree_code code,
              if (!in_late_binary_op)
                {
                  if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
-                   {
-                     op0 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op0),
-                                   NULL, op0);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op0) = !op0_maybe_const;
-                   }
+                   op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-                   {
-                     op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1),
-                                   NULL, op1);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const;
-                   }
+                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
                }
            }
        }
@@ -9227,8 +9818,9 @@ build_binary_op (location_t location, enum tree_code code,
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
-          ? fold_build2_initializer (resultcode, build_type, op0, op1)
-          : fold_build2 (resultcode, build_type, op0, op1));
+          ? fold_build2_initializer_loc (location, resultcode, build_type,
+                                         op0, op1)
+          : fold_build2_loc (location, resultcode, build_type, op0, op1));
   else
     ret = build2 (resultcode, build_type, op0, op1);
   if (final_type != 0)
@@ -9333,19 +9925,21 @@ c_begin_omp_parallel (void)
   return block;
 }
 
-/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound statement.  */
+/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound
+   statement.  LOC is the location of the OMP_PARALLEL.  */
 
 tree
-c_finish_omp_parallel (tree clauses, tree block)
+c_finish_omp_parallel (location_t loc, tree clauses, tree block)
 {
   tree stmt;
 
-  block = c_end_compound_stmt (block, true);
+  block = c_end_compound_stmt (loc, block, true);
 
   stmt = make_node (OMP_PARALLEL);
   TREE_TYPE (stmt) = void_type_node;
   OMP_PARALLEL_CLAUSES (stmt) = clauses;
   OMP_PARALLEL_BODY (stmt) = block;
+  SET_EXPR_LOCATION (stmt, loc);
 
   return add_stmt (stmt);
 }
@@ -9363,19 +9957,21 @@ c_begin_omp_task (void)
   return block;
 }
 
-/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound statement.  */
+/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound
+   statement.  LOC is the location of the #pragma.  */
 
 tree
-c_finish_omp_task (tree clauses, tree block)
+c_finish_omp_task (location_t loc, tree clauses, tree block)
 {
   tree stmt;
 
-  block = c_end_compound_stmt (block, true);
+  block = c_end_compound_stmt (loc, block, true);
 
   stmt = make_node (OMP_TASK);
   TREE_TYPE (stmt) = void_type_node;
   OMP_TASK_CLAUSES (stmt) = clauses;
   OMP_TASK_BODY (stmt) = block;
+  SET_EXPR_LOCATION (stmt, loc);
 
   return add_stmt (stmt);
 }
@@ -9421,7 +10017,8 @@ c_finish_omp_clauses (tree clauses)
          if (AGGREGATE_TYPE_P (TREE_TYPE (t))
              || POINTER_TYPE_P (TREE_TYPE (t)))
            {
-             error ("%qE has invalid type for %<reduction%>", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE has invalid type for %<reduction%>", t);
              remove = true;
            }
          else if (FLOAT_TYPE_P (TREE_TYPE (t)))
@@ -9455,8 +10052,9 @@ c_finish_omp_clauses (tree clauses)
                }
              if (r_name)
                {
-                 error ("%qE has invalid type for %<reduction(%s)%>",
-                        t, r_name);
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qE has invalid type for %<reduction(%s)%>",
+                           t, r_name);
                  remove = true;
                }
            }
@@ -9471,7 +10069,8 @@ c_finish_omp_clauses (tree clauses)
          t = OMP_CLAUSE_DECL (c);
          if (TREE_CODE (t) != VAR_DECL || !DECL_THREAD_LOCAL_P (t))
            {
-             error ("%qE must be %<threadprivate%> for %<copyin%>", t);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE must be %<threadprivate%> for %<copyin%>", t);
              remove = true;
            }
          goto check_dup_generic;
@@ -9480,14 +10079,16 @@ c_finish_omp_clauses (tree clauses)
          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);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%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);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE appears more than once in data clauses", t);
              remove = true;
            }
          else
@@ -9501,13 +10102,15 @@ c_finish_omp_clauses (tree clauses)
          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);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%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);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%qE appears more than once in data clauses", t);
              remove = true;
            }
          else
@@ -9521,13 +10124,15 @@ c_finish_omp_clauses (tree clauses)
          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);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                       "%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);
+             error_at (OMP_CLAUSE_LOCATION (c),
+                    "%qE appears more than once in data clauses", t);
              remove = true;
            }
          else
@@ -9581,8 +10186,9 @@ c_finish_omp_clauses (tree clauses)
                }
              if (share_name)
                {
-                 error ("%qE is predetermined %qs for %qs",
-                        t, share_name, name);
+                 error_at (OMP_CLAUSE_LOCATION (c),
+                           "%qE is predetermined %qs for %qs",
+                           t, share_name, name);
                  remove = true;
                }
            }
@@ -9636,11 +10242,11 @@ c_build_qualified_type (tree type, int type_quals)
           else if (TYPE_CANONICAL (element_type) != element_type
                    || (domain && TYPE_CANONICAL (domain) != domain))
             {
-              tree unqualified_canon 
+              tree unqualified_canon
                 = build_array_type (TYPE_CANONICAL (element_type),
-                                    domain? TYPE_CANONICAL (domain) 
+                                    domain? TYPE_CANONICAL (domain)
                                           : NULL_TREE);
-              TYPE_CANONICAL (t) 
+              TYPE_CANONICAL (t)
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
           else
@@ -9662,3 +10268,14 @@ c_build_qualified_type (tree type, int type_quals)
 
   return build_qualified_type (type, type_quals);
 }
+
+/* Build a VA_ARG_EXPR for the C parser.  */
+
+tree
+c_build_va_arg (location_t loc, tree expr, tree type)
+{
+  if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
+    warning_at (loc, OPT_Wc___compat,
+               "C++ requires promoted type, not enum type, in %<va_arg%>");
+  return build_va_arg (loc, expr, type);
+}