OSDN Git Service

PR c++/53220
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 6c86b92..d689215 100644 (file)
@@ -1,6 +1,6 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -29,21 +29,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "rtl.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
-#include "tm_p.h"
+#include "c-lang.h"
 #include "flags.h"
 #include "output.h"
-#include "expr.h"
-#include "toplev.h"
 #include "intl.h"
-#include "ggc.h"
 #include "target.h"
 #include "tree-iterator.h"
+#include "bitmap.h"
 #include "gimple.h"
-#include "tree-flow.h"
+#include "c-family/c-objc.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -54,12 +51,13 @@ enum impl_conv {
   ic_return
 };
 
-/* Whether we are building a boolean conversion inside
-   convert_for_assignment, or some other late binary operation.  If
-   build_binary_op is called (from code shared with C++) in this case,
-   then the operands have already been folded and the result will not
-   be folded again, so C_MAYBE_CONST_EXPR should not be generated.  */
-bool in_late_binary_op;
+/* Possibe cases of scalar_to_vector conversion.  */
+enum stv_conv {
+  stv_error,        /* Error occured.  */
+  stv_nothing,      /* Nothing happened.  */
+  stv_firstarg,     /* First argument must be expanded.  */
+  stv_secondarg     /* Second argument must be expanded.  */
+};
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
@@ -70,9 +68,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,14 +77,16 @@ 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, bool *);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
+                                        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 int function_types_compatible_p (const_tree, const_tree, bool *,
+                                       bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
-static tree pointer_diff (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);
@@ -98,20 +95,20 @@ 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, 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, 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 tree digest_init (location_t, tree, tree, tree, bool, bool, int);
+static void output_init_element (tree, tree, bool, tree, tree, int, bool,
+                                struct obstack *);
+static void output_pending_init_elements (int, struct obstack *);
+static int set_designator (int, struct obstack *);
+static void push_range_stack (tree, struct obstack *);
+static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void set_nonincremental_init (struct obstack *);
+static void set_nonincremental_init_from_string (tree, struct obstack *);
+static tree find_init_member (tree, struct obstack *);
 static void readonly_warning (tree, enum lvalue_use);
-static int lvalue_or_else (const_tree, enum lvalue_use);
+static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *);
+static int comptypes_internal (const_tree, const_tree, bool *, bool *);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -286,14 +283,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.  */
@@ -356,7 +394,7 @@ composite_type (tree t1, tree t2)
        tree pointed_to_1 = TREE_TYPE (t1);
        tree pointed_to_2 = TREE_TYPE (t2);
        tree target = composite_type (pointed_to_1, pointed_to_2);
-       t1 = build_pointer_type (target);
+        t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
        t1 = build_type_attribute_variant (t1, attributes);
        return qualify_type (t1, t2);
       }
@@ -373,7 +411,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);
@@ -476,9 +515,6 @@ composite_type (tree t1, tree t2)
 
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
-       /* Tell global_bindings_p to return false so that variable_size
-          doesn't die on VLAs in parameter types.  */
-       c_override_global_bindings_to_false = true;
 
        len = list_length (p1);
        newargs = 0;
@@ -516,7 +552,7 @@ composite_type (tree t1, tree t2)
                    && TREE_CODE (mv2) != ARRAY_TYPE)
                  mv2 = TYPE_MAIN_VARIANT (mv2);
                for (memb = TYPE_FIELDS (TREE_VALUE (p1));
-                    memb; memb = TREE_CHAIN (memb))
+                    memb; memb = DECL_CHAIN (memb))
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
@@ -526,7 +562,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;
                      }
@@ -541,7 +577,7 @@ composite_type (tree t1, tree t2)
                    && TREE_CODE (mv1) != ARRAY_TYPE)
                  mv1 = TYPE_MAIN_VARIANT (mv1);
                for (memb = TYPE_FIELDS (TREE_VALUE (p2));
-                    memb; memb = TREE_CHAIN (memb))
+                    memb; memb = DECL_CHAIN (memb))
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
@@ -551,7 +587,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;
                      }
@@ -561,7 +597,6 @@ composite_type (tree t1, tree t2)
          parm_done: ;
          }
 
-       c_override_global_bindings_to_false = false;
        t1 = build_function_type (valtype, newargs);
        t1 = qualify_type (t1, t2);
        /* ... falls through ...  */
@@ -587,6 +622,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.  */
 
@@ -618,10 +655,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);
 }
@@ -919,7 +970,7 @@ 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, NULL);
+  val = comptypes_internal (type1, type2, NULL, NULL);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -934,7 +985,23 @@ 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);
+  val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+
+  return val;
+}
+
+/* Like comptypes, but if it returns nonzero for different types, it
+   sets *DIFFERENT_TYPES_P to true.  */
+
+int
+comptypes_check_different_types (tree type1, tree type2,
+                                bool *different_types_p)
+{
+  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
+  int val;
+
+  val = comptypes_internal (type1, type2, NULL, different_types_p);
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -945,11 +1012,17 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
    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.  */
+   *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
+   NULL, and the types are compatible but different enough not to be
+   permitted in C11 typedef redeclarations, then this sets
+   *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
+   false, but may or may not be set if the types are incompatible.
+   This differs from comptypes, in that we don't free the seen
+   types.  */
 
 static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
+                   bool *different_types_p)
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
@@ -961,17 +1034,6 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
       || TREE_CODE (t1) == ERROR_MARK || TREE_CODE (t2) == ERROR_MARK)
     return 1;
 
-  /* If either type is the internal version of sizetype, return the
-     language version.  */
-  if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
-      && TYPE_ORIG_SIZE_TYPE (t1))
-    t1 = TYPE_ORIG_SIZE_TYPE (t1);
-
-  if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
-      && TYPE_ORIG_SIZE_TYPE (t2))
-    t2 = TYPE_ORIG_SIZE_TYPE (t2);
-
-
   /* Enumerated types are compatible with integer types, but this is
      not transitive: two enumerated types in the same translation unit
      are compatible with each other only if they are the same type.  */
@@ -979,14 +1041,24 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
   if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
     {
       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;
+      if (TREE_CODE (t2) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_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));
-      if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
-       *enum_and_int_p = true;
+      if (TREE_CODE (t1) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
     }
 
   if (t1 == t2)
@@ -1011,7 +1083,7 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
     return 1;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
-  if (!(attrval = targetm.comp_type_attributes (t1, t2)))
+  if (!(attrval = comp_type_attributes (t1, t2)))
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1026,11 +1098,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
             ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                      enum_and_int_p));
+                                      enum_and_int_p, different_types_p));
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2, enum_and_int_p);
+      val = function_types_compatible_p (t1, t2, enum_and_int_p,
+                                        different_types_p);
       break;
 
     case ARRAY_TYPE:
@@ -1044,9 +1117,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
            && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                              enum_and_int_p)))
+                                              enum_and_int_p,
+                                              different_types_p)))
          return 0;
 
+       if (different_types_p != NULL
+           && (d1 == 0) != (d2 == 0))
+         *different_types_p = true;
        /* Sizes must match unless one is missing or variable.  */
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
@@ -1063,6 +1140,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
        d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
        d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
+       if (different_types_p != NULL
+           && d1_variable != d2_variable)
+         *different_types_p = true;
        if (d1_variable || d2_variable)
          break;
        if (d1_zero && d2_zero)
@@ -1088,15 +1168,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
            break;
 
          if (attrval != 2)
-           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
-         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                                different_types_p);
+         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                             different_types_p);
        }
       break;
 
     case VECTOR_TYPE:
       val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
             && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                   enum_and_int_p));
+                                   enum_and_int_p, different_types_p));
       break;
 
     default:
@@ -1105,20 +1187,28 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
   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 (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)
@@ -1220,11 +1310,12 @@ 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.  ENUM_AND_INT_P is as in comptypes_internal.  */
+   rules.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
 
 static int
 tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
-                             bool *enum_and_int_p)
+                             bool *enum_and_int_p, bool *different_types_p)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1328,14 +1419,14 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
 
        /*  Speed up the common case where the fields are in the same order. */
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
-            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
          {
            int result;
 
            if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p);
+                                        enum_and_int_p, different_types_p);
 
            if (result != 1 && !DECL_NAME (s1))
              break;
@@ -1361,17 +1452,18 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
            return tu->val;
          }
 
-       for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
+       for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1))
          {
            bool ok = false;
 
-           for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+           for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2))
              if (DECL_NAME (s1) == DECL_NAME (s2))
                {
                  int result;
 
                  result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                              enum_and_int_p);
+                                              enum_and_int_p,
+                                              different_types_p);
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
@@ -1407,14 +1499,14 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
-            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
          {
            int result;
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p);
+                                        enum_and_int_p, different_types_p);
            if (result == 0)
              break;
            if (result == 2)
@@ -1443,11 +1535,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
    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.
-   ENUM_AND_INT_P is as in comptypes_internal.  */
+   ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal.  */
 
 static int
 function_types_compatible_p (const_tree f1, const_tree f2,
-                            bool *enum_and_int_p)
+                            bool *enum_and_int_p, bool *different_types_p)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1468,13 +1560,17 @@ 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, enum_and_int_p);
+  val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
   if (val == 0)
     return 0;
 
   args1 = TYPE_ARG_TYPES (f1);
   args2 = TYPE_ARG_TYPES (f2);
 
+  if (different_types_p != NULL
+      && (args1 == 0) != (args2 == 0))
+    *different_types_p = true;
+
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
 
@@ -1487,7 +1583,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
         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),
-                                          enum_and_int_p))
+                                          enum_and_int_p, different_types_p))
        val = 2;
       return val;
     }
@@ -1497,23 +1593,25 @@ function_types_compatible_p (const_tree f1, const_tree f2,
        return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
          && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
-                                          enum_and_int_p))
+                                          enum_and_int_p, different_types_p))
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p);
+  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
+                                 different_types_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.  ENUM_AND_INT_P is as in comptypes_internal.  */
+   warning.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
 
 static int
 type_lists_compatible_p (const_tree args1, const_tree args2,
-                        bool *enum_and_int_p)
+                        bool *enum_and_int_p, bool *different_types_p)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1538,6 +1636,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
         means there is supposed to be an argument
         but nothing is specified about what type it has.
         So match anything that self-promotes.  */
+      if (different_types_p != NULL
+         && (a1 == 0) != (a2 == 0))
+       *different_types_p = true;
       if (a1 == 0)
        {
          if (c_type_promotes_to (a2) != a2)
@@ -1552,26 +1653,30 @@ 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, enum_and_int_p)))
+      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
+                                             different_types_p)))
        {
+         if (different_types_p != NULL)
+           *different_types_p = true;
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
          if (TREE_CODE (a1) == UNION_TYPE
              && (TYPE_NAME (a1) == 0
-                 || TYPE_TRANSPARENT_UNION (a1))
+                 || TYPE_TRANSPARENT_AGGR (a1))
              && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
              && tree_int_cst_equal (TYPE_SIZE (a1),
                                     TYPE_SIZE (a2)))
            {
              tree memb;
              for (memb = TYPE_FIELDS (a1);
-                  memb; memb = TREE_CHAIN (memb))
+                  memb; memb = DECL_CHAIN (memb))
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv2, enum_and_int_p))
+                 if (comptypes_internal (mv3, mv2, enum_and_int_p,
+                                         different_types_p))
                    break;
                }
              if (memb == 0)
@@ -1579,20 +1684,21 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
            }
          else if (TREE_CODE (a2) == UNION_TYPE
                   && (TYPE_NAME (a2) == 0
-                      || TYPE_TRANSPARENT_UNION (a2))
+                      || TYPE_TRANSPARENT_AGGR (a2))
                   && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
                   && tree_int_cst_equal (TYPE_SIZE (a2),
                                          TYPE_SIZE (a1)))
            {
              tree memb;
              for (memb = TYPE_FIELDS (a2);
-                  memb; memb = TREE_CHAIN (memb))
+                  memb; memb = DECL_CHAIN (memb))
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv1, enum_and_int_p))
+                 if (comptypes_internal (mv3, mv1, enum_and_int_p,
+                                         different_types_p))
                    break;
                }
              if (memb == 0)
@@ -1628,9 +1734,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).  */
@@ -1659,7 +1765,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);
@@ -1679,13 +1785,25 @@ array_to_pointer_conversion (tree exp)
   if (TREE_CODE (exp) == INDIRECT_REF)
     return convert (ptrtype, TREE_OPERAND (exp, 0));
 
-  adr = build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1);
+  /* In C++ array compound literals are temporary objects unless they are
+     const or appear in namespace scope, so they are destroyed too soon
+     to use them for much of anything  (c++/53220).  */
+  if (warn_cxx_compat && TREE_CODE (exp) == COMPOUND_LITERAL_EXPR)
+    {
+      tree decl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+      if (!TREE_READONLY (decl) && !TREE_STATIC (decl))
+       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
+                   "converting an array compound literal to a pointer "
+                   "is ill-formed in C++");
+    }
+
+  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;
 
@@ -1696,15 +1814,47 @@ 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);
+}
+
+/* Mark EXP as read, not just set, for set but not used -Wunused
+   warning purposes.  */
+
+void
+mark_exp_read (tree exp)
+{
+  switch (TREE_CODE (exp))
+    {
+    case VAR_DECL:
+    case PARM_DECL:
+      DECL_READ_P (exp) = 1;
+      break;
+    case ARRAY_REF:
+    case COMPONENT_REF:
+    case MODIFY_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    CASE_CONVERT:
+    case ADDR_EXPR:
+      mark_exp_read (TREE_OPERAND (exp, 0));
+      break;
+    case COMPOUND_EXPR:
+    case C_MAYBE_CONST_EXPR:
+      mark_exp_read (TREE_OPERAND (exp, 1));
+      break;
+    default:
+      break;
+    }
 }
 
 /* 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);
@@ -1739,11 +1889,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;
@@ -1752,6 +1902,12 @@ default_function_array_conversion (struct c_expr exp)
   return exp;
 }
 
+struct c_expr
+default_function_array_read_conversion (location_t loc, struct c_expr exp)
+{
+  mark_exp_read (exp.value);
+  return default_function_array_conversion (loc, exp);
+}
 
 /* EXP is an expression of integer type.  Apply the integer promotions
    to it and return the promoted value.  */
@@ -1813,6 +1969,8 @@ default_conversion (tree exp)
   enum tree_code code = TREE_CODE (type);
   tree promoted_type;
 
+  mark_exp_read (exp);
+
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
   if (code == ARRAY_TYPE)
@@ -1849,7 +2007,7 @@ default_conversion (tree exp)
   return exp;
 }
 \f
-/* Look up COMPONENT in a structure or union DECL.
+/* Look up COMPONENT in a structure or union TYPE.
 
    If the component name is not found, returns NULL_TREE.  Otherwise,
    the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
@@ -1859,9 +2017,8 @@ default_conversion (tree exp)
    unions, the list steps down the chain to the component.  */
 
 static tree
-lookup_field (tree decl, tree component)
+lookup_field (tree type, tree component)
 {
-  tree type = TREE_TYPE (decl);
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1891,10 +2048,21 @@ lookup_field (tree decl, tree component)
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                    {
-                     tree anon = lookup_field (field, component);
+                     tree anon = lookup_field (TREE_TYPE (field), component);
 
                      if (anon)
                        return tree_cons (NULL_TREE, field, anon);
+
+                     /* The Plan 9 compiler permits referring
+                        directly to an anonymous struct/union field
+                        using a typedef name.  */
+                     if (flag_plan9_extensions
+                         && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                         && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+                             == TYPE_DECL)
+                         && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                             == component))
+                       break;
                    }
                }
 
@@ -1921,16 +2089,26 @@ lookup_field (tree decl, tree component)
     }
   else
     {
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        {
          if (DECL_NAME (field) == NULL_TREE
              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
            {
-             tree anon = lookup_field (field, component);
+             tree anon = lookup_field (TREE_TYPE (field), component);
 
              if (anon)
                return tree_cons (NULL_TREE, field, anon);
+
+             /* The Plan 9 compiler permits referring directly to an
+                anonymous struct/union field using a typedef
+                name.  */
+             if (flag_plan9_extensions
+                 && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                 && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
+                 && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                     == component))
+               break;
            }
 
          if (DECL_NAME (field) == component)
@@ -1944,11 +2122,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);
@@ -1959,6 +2138,11 @@ build_component_ref (tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
+  /* Detect Objective-C property syntax object.property.  */
+  if (c_dialect_objc ()
+      && (ref = objc_maybe_build_component_ref (datum, component)))
+    return ref;
+
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
@@ -1969,11 +2153,11 @@ build_component_ref (tree datum, tree component)
          return error_mark_node;
        }
 
-      field = lookup_field (datum, component);
+      field = lookup_field (type, 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;
        }
 
@@ -2006,6 +2190,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;
@@ -2025,8 +2210,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;
 }
@@ -2038,7 +2224,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);
@@ -2077,7 +2263,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,
@@ -2096,8 +2282,8 @@ 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);
+    invalid_indirection_error (loc, type, errstring);
+
   return error_mark_node;
 }
 
@@ -2110,10 +2296,13 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
    arrays that are not lvalues (for example, members of structures returned
    by functions).
 
+   For vector types, allow vector[i] but not i[vector], and create
+   *(((type*)&vectortype) + i) for the expression.
+
    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;
@@ -2122,13 +2311,17 @@ build_array_ref (tree array, tree index, location_t loc)
     return error_mark_node;
 
   if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
-      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
+      /* Allow vector[index] but not index[vector].  */
+      && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
     {
       tree temp;
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
-         error_at (loc, "subscripted value is neither array nor pointer");
+          error_at (loc,
+            "subscripted value is neither array nor pointer nor vector");
+
          return error_mark_node;
        }
       temp = array;
@@ -2159,6 +2352,27 @@ build_array_ref (tree array, tree index, location_t loc)
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
 
+  /* For vector[index], convert the vector to a
+     pointer of the underlying type.  */
+  if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE)
+    {
+      tree type = TREE_TYPE (array);
+      tree type1;
+
+      if (TREE_CODE (index) == INTEGER_CST)
+        if (!host_integerp (index, 1)
+            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
+               >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array))))
+          warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
+
+      c_common_mark_addressable_vec (array);
+      type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
+      type = build_pointer_type (type);
+      type1 = build_pointer_type (TREE_TYPE (array));
+      array = build1 (ADDR_EXPR, type1, array);
+      array = convert (type, array);
+    }
+
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
       tree rval, type;
@@ -2192,10 +2406,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");
        }
 
@@ -2232,7 +2446,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
@@ -2243,7 +2457,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);
@@ -2260,14 +2474,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;
     }
 
@@ -2278,7 +2492,7 @@ build_external_ref (tree id, int fun, location_t loc, tree *type)
     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;
     }
@@ -2393,7 +2607,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)
@@ -2408,7 +2622,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)))
@@ -2417,6 +2631,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)));
     }
@@ -2424,17 +2639,18 @@ 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 || TREE_CODE (ret.value) == INTEGER_CST)
@@ -2459,12 +2675,13 @@ 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;
@@ -2472,7 +2689,7 @@ build_function_call (tree function, tree params)
   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 (function, vec, NULL);
+  ret = build_function_call_vec (loc, function, vec, NULL);
   VEC_free (tree, gc, vec);
   return ret;
 }
@@ -2486,7 +2703,7 @@ build_function_call (tree function, tree params)
    PARAMS.  */
 
 tree
-build_function_call_vec (tree function, VEC(tree,gc) *params,
+build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                         VEC(tree,gc) *origtypes)
 {
   tree fntype, fundecl = 0;
@@ -2494,7 +2711,7 @@ build_function_call_vec (tree function, VEC(tree,gc) *params,
   tree tem;
   int nargs;
   tree *argarray;
-  
+
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -2506,15 +2723,22 @@ build_function_call_vec (tree function, VEC(tree,gc) *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;
 
       name = DECL_NAME (function);
+
+      if (flag_tm)
+       tm_malloc_replacement (function);
       fundecl = function;
+      /* Atomic functions have type checking/casting already done.  They are 
+        often rewritten and don't match the original parameter list.  */
+      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+        origtypes = NULL;
     }
   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.  */
@@ -2532,7 +2756,7 @@ build_function_call_vec (tree function, VEC(tree,gc) *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;
     }
 
@@ -2561,17 +2785,18 @@ build_function_call_vec (tree function, VEC(tree,gc) *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,
+                                      builtin_decl_explicit (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++)
@@ -2581,7 +2806,7 @@ build_function_call_vec (tree function, VEC(tree,gc) *params,
       if (VOID_TYPE_P (return_type))
        {
          if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
-           pedwarn (input_location, 0,
+           pedwarn (loc, 0,
                     "function with qualified void return type called");
          return trap;
        }
@@ -2590,11 +2815,11 @@ build_function_call_vec (tree function, VEC(tree,gc) *params,
          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 = build_zero_cst (return_type);
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
@@ -2611,35 +2836,127 @@ build_function_call_vec (tree function, VEC(tree,gc) *params,
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
-                           TYPE_ARG_TYPES (fntype));
+  check_function_arguments (fntype, nargs, argarray);
 
   if (name != NULL_TREE
       && !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)))
     {
       if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
-       pedwarn (input_location, 0,
+       pedwarn (loc, 0,
                 "function with qualified void return type called");
       return result;
     }
   return require_complete_type (result);
 }
+
+/* Build a VEC_PERM_EXPR if V0, V1 and MASK are not error_mark_nodes
+   and have vector types, V0 has the same type as V1, and the number of
+   elements of V0, V1, MASK is the same.
+
+   In case V1 is a NULL_TREE it is assumed that __builtin_shuffle was
+   called with two arguments.  In this case implementation passes the
+   first argument twice in order to share the same tree code.  This fact
+   could enable the mask-values being twice the vector length.  This is
+   an implementation accident and this semantics is not guaranteed to
+   the user.  */
+tree
+c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
+{
+  tree ret;
+  bool wrap = true;
+  bool maybe_const = false;
+  bool two_arguments = false;
+
+  if (v1 == NULL_TREE)
+    {
+      two_arguments = true;
+      v1 = v0;
+    }
+
+  if (v0 == error_mark_node || v1 == error_mark_node
+      || mask == error_mark_node)
+    return error_mark_node;
+
+  if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE
+      || TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE)
+    {
+      error_at (loc, "__builtin_shuffle last argument must "
+                    "be an integer vector");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE
+      || TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE)
+    {
+      error_at (loc, "__builtin_shuffle arguments must be vectors");
+      return error_mark_node;
+    }
+
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1)))
+    {
+      error_at (loc, "__builtin_shuffle argument vectors must be of "
+                    "the same type");
+      return error_mark_node;
+    }
+
+  if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0))
+      != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))
+      && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1))
+        != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
+    {
+      error_at (loc, "__builtin_shuffle number of elements of the "
+                    "argument vector(s) and the mask vector should "
+                    "be the same");
+      return error_mark_node;
+    }
+
+  if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
+      != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
+    {
+      error_at (loc, "__builtin_shuffle argument vector(s) inner type "
+                    "must have the same size as inner type of the mask");
+      return error_mark_node;
+    }
+
+  /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR.  */
+  v0 = c_fully_fold (v0, false, &maybe_const);
+  wrap &= maybe_const;
+
+  if (two_arguments)
+    v1 = v0 = save_expr (v0);
+  else
+    {
+      v1 = c_fully_fold (v1, false, &maybe_const);
+      wrap &= maybe_const;
+    }
+
+  mask = c_fully_fold (mask, false, &maybe_const);
+  wrap &= maybe_const;
+
+  ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask);
+
+  if (!wrap)
+    ret = c_wrap_maybe_const (ret, true);
+
+  return ret;
+}
 \f
 /* Convert the argument expressions in the vector VALUES
    to the types in the list TYPELIST.
@@ -2666,6 +2983,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 {
   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;
@@ -2722,7 +3040,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
       if (type == void_type_node)
        {
-         error ("too many arguments to function %qE", function);
+         if (selector)
+           error_at (input_location,
+                     "too many arguments to method %qE", selector);
+         else
+           error_at (input_location,
+                     "too many arguments to function %qE", function);
+
+         if (fundecl && !DECL_BUILT_IN (fundecl))
+           inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
          return parmnum;
        }
 
@@ -2856,7 +3182,8 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
                           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))
@@ -2879,11 +3206,13 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
                               && 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);
                    }
                }
@@ -2914,8 +3243,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
          if (type_generic)
            parmval = val;
          else
-           /* Convert `float' to `double'.  */
-           parmval = convert (double_type_node, val);
+           {
+             /* Convert `float' to `double'.  */
+             if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+               warning (OPT_Wdouble_promotion,
+                        "implicit conversion from %qT to %qT when passing "
+                        "argument to function",
+                        valtype, double_type_node);
+             parmval = convert (double_type_node, val);
+           }
        }
       else if (excess_precision && !type_generic)
        /* A "double" argument with excess precision being passed
@@ -2932,6 +3268,8 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
        parmval = default_conversion (val);
 
       VEC_replace (tree, values, parmnum, parmval);
+      if (parmval == error_mark_node)
+       error_args = true;
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
@@ -2941,11 +3279,14 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error ("too few arguments to function %qE", function);
+      error_at (input_location,
+               "too few arguments to function %qE", function);
+      if (fundecl && !DECL_BUILT_IN (fundecl))
+       inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
       return -1;
     }
 
-  return parmnum;
+  return error_args ? -1 : (int) parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
@@ -2957,7 +3298,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 */
 
 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;
 
@@ -2966,7 +3307,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;
 }
@@ -3020,16 +3361,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
@@ -3048,19 +3391,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
@@ -3112,18 +3487,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
@@ -3193,7 +3572,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:
@@ -3220,7 +3599,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);
@@ -3264,30 +3643,17 @@ 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);
-      else
-       ret = arg;
-      if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
-       eptype = TREE_TYPE (eptype);
-      goto return_build_unary_op;
-
     case IMAGPART_EXPR:
-      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);
-      else
-       ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg);
+      ret = build_real_imag_expr (location, code, arg);
+      if (ret == error_mark_node)
+       return error_mark_node;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3310,11 +3676,14 @@ build_unary_op (location_t location,
          goto return_build_unary_op;
        }
 
-      /* Complain about anything that is not a true lvalue.  */
-      if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
-                                 || code == POSTINCREMENT_EXPR)
-                                ? lv_increment
-                                : lv_decrement)))
+      /* Complain about anything that is not a true lvalue.  In
+        Objective-C, skip this check for property_refs.  */
+      if (!objc_is_property_ref (arg)
+         && !lvalue_or_else (location,
+                             arg, ((code == PREINCREMENT_EXPR
+                                    || code == POSTINCREMENT_EXPR)
+                                   ? lv_increment
+                                   : lv_decrement)))
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@@ -3336,7 +3705,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);
@@ -3387,15 +3756,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 = convert_to_ptrofftype_loc (location, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3422,6 +3791,13 @@ build_unary_op (location_t location,
            inc = convert (argtype, inc);
          }
 
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (location, code,
+                                                       arg, inc);
+
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
@@ -3465,7 +3841,7 @@ build_unary_op (location_t location,
        {
          /* 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;
        }
@@ -3476,17 +3852,12 @@ build_unary_op (location_t location,
          tree op0 = TREE_OPERAND (arg, 0);
          if (!c_mark_addressable (op0))
            return error_mark_node;
-         return build_binary_op (location, PLUS_EXPR,
-                                 (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
-                                  ? array_to_pointer_conversion (op0)
-                                  : op0),
-                                 TREE_OPERAND (arg, 1), 1);
        }
 
       /* Anything not already handled and not a true memory reference
         or a non-lvalue array is an error.  */
       else if (typecode != FUNCTION_TYPE && !flag
-              && !lvalue_or_else (arg, lv_addressof))
+              && !lvalue_or_else (location, arg, lv_addressof))
        return error_mark_node;
 
       /* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@@ -3507,14 +3878,22 @@ build_unary_op (location_t location,
       argtype = TREE_TYPE (arg);
 
       /* If the lvalue is const or volatile, merge that into the type
-        to which the address will point.  Note that you can't get a
-        restricted pointer by taking the address of something, so we
-        only have to deal with `const' and `volatile' here.  */
+        to which the address will point.  This is only needed
+        for function types.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
-         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
-         argtype = c_build_type_variant (argtype,
-                                         TREE_READONLY (arg),
-                                         TREE_THIS_VOLATILE (arg));
+         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
+         && TREE_CODE (argtype) == FUNCTION_TYPE)
+       {
+         int orig_quals = TYPE_QUALS (strip_array_types (argtype));
+         int quals = orig_quals;
+
+         if (TREE_READONLY (arg))
+           quals |= TYPE_QUAL_CONST;
+         if (TREE_THIS_VOLATILE (arg))
+           quals |= TYPE_QUAL_VOLATILE;
+
+         argtype = c_build_qualified_type (argtype, quals);
+       }
 
       if (!c_mark_addressable (arg))
        return error_mark_node;
@@ -3530,10 +3909,7 @@ 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;
-
-         op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+         ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
          goto return_build_unary_op;
        }
 
@@ -3550,8 +3926,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:
@@ -3607,44 +3983,6 @@ lvalue_p (const_tree ref)
     }
 }
 \f
-/* Give an error for storing in something that is 'const'.  */
-
-static void
-readonly_error (tree arg, enum lvalue_use use)
-{
-  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
-             || use == lv_asm);
-  /* Using this macro rather than (for example) arrays of messages
-     ensures that all the format strings are checked at compile
-     time.  */
-#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A)              \
-                                  : (use == lv_increment ? (I)         \
-                                  : (use == lv_decrement ? (D) : (AS))))
-  if (TREE_CODE (arg) == COMPONENT_REF)
-    {
-      if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_error (TREE_OPERAND (arg, 0), use);
-      else
-       error (READONLY_MSG (G_("assignment of read-only member %qD"),
-                            G_("increment of read-only member %qD"),
-                            G_("decrement of read-only member %qD"),
-                            G_("read-only member %qD used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
-    }
-  else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
-                        G_("increment of read-only variable %qD"),
-                        G_("decrement of read-only variable %qD"),
-                        G_("read-only variable %qD used as %<asm%> output")),
-          arg);
-  else
-    error (READONLY_MSG (G_("assignment of read-only location %qE"),
-                        G_("increment of read-only location %qE"),
-                        G_("decrement of read-only location %qE"),
-                        G_("read-only location %qE used as %<asm%> output")),
-          arg);
-}
-
 /* Give a warning for storing in something that is read-only in GCC
    terms but not const in ISO C terms.  */
 
@@ -3671,15 +4009,16 @@ readonly_warning (tree arg, enum lvalue_use use)
 
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  USE says
-   how the lvalue is being used and so selects the error message.  */
+   how the lvalue is being used and so selects the error message.
+   LOCATION is the location at which any error should be reported.  */
 
 static int
-lvalue_or_else (const_tree ref, enum lvalue_use use)
+lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
   if (!win)
-    lvalue_error (use);
+    lvalue_error (loc, use);
 
   return win;
 }
@@ -3751,27 +4090,55 @@ c_mark_addressable (tree exp)
     }
 }
 \f
+/* Convert EXPR to TYPE, warning about conversion problems with
+   constants.  SEMANTIC_TYPE is the type this conversion would use
+   without excess precision. If SEMANTIC_TYPE is NULL, this function
+   is equivalent to convert_and_check. This function is a wrapper that
+   handles conversions that may be different than
+   the usual ones because of excess precision.  */
+
+static tree
+ep_convert_and_check (tree type, tree expr, tree semantic_type)
+{
+  if (TREE_TYPE (expr) == type)
+    return expr;
+
+  if (!semantic_type)
+    return convert_and_check (type, expr);
+
+  if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      && TREE_TYPE (expr) != semantic_type)
+    {
+      /* For integers, we need to check the real conversion, not
+        the conversion to the excess precision type.  */
+      expr = convert_and_check (semantic_type, expr);
+    }
+  /* Result type is the excess precision type, which should be
+     large enough, so do not check.  */
+  return convert (type, expr);
+}
+
 /* Build and return a conditional expression IFEXP ? OP1 : OP2.  If
    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 (location_t colon_loc, tree ifexp, bool ifexp_bcp,
-                       tree op1, tree op2)
+                       tree op1, tree op1_original_type, tree op2,
+                       tree op2_original_type)
 {
   tree type1;
   tree type2;
   enum tree_code code1;
   enum tree_code code2;
   tree result_type = NULL;
-  tree ep_result_type = NULL;
+  tree semantic_result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
   bool int_const, op1_int_operands, op2_int_operands, int_operands;
   bool ifexp_int_operands;
   tree ret;
-  bool objc_ok;
 
   op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
   if (op1_int_operands)
@@ -3808,8 +4175,6 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       return error_mark_node;
     }
 
-  objc_ok = objc_compare_types (type1, type2, -3, NULL_TREE);
-
   if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
        || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
       && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -3817,7 +4182,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
          || code2 == COMPLEX_TYPE))
     {
-      ep_result_type = c_common_type (type1, type2);
+      semantic_result_type = c_common_type (type1, type2);
       if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
        {
          op1 = TREE_OPERAND (op1, 0);
@@ -3832,6 +4197,20 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
        }
     }
 
+  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))
@@ -3847,13 +4226,17 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
               || code2 == COMPLEX_TYPE))
     {
       result_type = c_common_type (type1, type2);
+      do_warn_double_promotion (result_type, type1, type2,
+                               "implicit conversion from %qT to %qT to "
+                               "match other result of conditional",
+                               colon_loc);
 
       /* If -Wsign-compare, warn here if type1 and type2 have
         different signedness.  We'll promote the signed to unsigned
         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));
@@ -3880,10 +4263,19 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                     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)
                    {
@@ -3898,17 +4290,9 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                                     "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);
                }
            }
        }
@@ -3922,12 +4306,22 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
+      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)
@@ -3946,12 +4340,17 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
          result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
                                                          TREE_TYPE (type1)));
        }
+      /* Objective-C pointer comparisons are a bit more lenient.  */
+      else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
+       result_type = objc_common_type (type1, type2);
       else
        {
-         if (!objc_ok)
-           pedwarn (colon_loc, 0,
-                    "pointer type mismatch in conditional expression");
-         result_type = build_pointer_type (void_type_node);
+         int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+
+         pedwarn (colon_loc, 0,
+                  "pointer type mismatch in conditional expression");
+         result_type = build_pointer_type
+                         (build_qualified_type (void_type_node, qual));
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
@@ -3983,7 +4382,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
        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;
        }
     }
@@ -3991,13 +4390,11 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
   /* 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))
-    op1 = convert_and_check (result_type, op1);
-  if (result_type != TREE_TYPE (op2))
-    op2 = convert_and_check (result_type, op2);
+  op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+  op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
     {
@@ -4022,24 +4419,32 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                       && !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
     {
+      if (int_operands)
+       {
+         op1 = remove_c_maybe_const_expr (op1);
+         op2 = remove_c_maybe_const_expr (op2);
+       }
       ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
       if (int_operands)
        ret = note_integer_operands (ret);
     }
-  if (ep_result_type)
-    ret = build1 (EXCESS_PRECISION_EXPR, ep_result_type, ret);
+  if (semantic_result_type)
+    ret = build1 (EXCESS_PRECISION_EXPR, semantic_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;
@@ -4075,8 +4480,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");
        }
     }
 
@@ -4085,7 +4490,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;
@@ -4100,16 +4505,19 @@ build_compound_expr (tree expr1, tree expr2)
   if (eptype)
     ret = build1 (EXCESS_PRECISION_EXPR, eptype, ret);
 
+  protected_set_expr_location (ret, loc);
   return ret;
 }
 
 /* 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.  */
+   cast.  Both TYPE and OTYPE are pointer types.  LOC is the location
+   of the cast.  -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)
+handle_warn_cast_qual (location_t loc, tree type, tree otype)
 {
   tree in_type = type;
   tree in_otype = otype;
@@ -4132,21 +4540,25 @@ handle_warn_cast_qual (tree type, tree otype)
         taken away.  */
       if (TREE_CODE (in_otype) == FUNCTION_TYPE
          && TREE_CODE (in_type) == FUNCTION_TYPE)
-       added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+       added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
       else
-       discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+       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");
+    warning_at (loc, OPT_Wcast_qual,
+               "cast adds %q#v qualifier to function type", added);
 
   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");
+    warning_at (loc, OPT_Wcast_qual,
+               "cast discards %q#v qualifier from pointer target type",
+               discarded);
 
   if (added || discarded)
     return;
@@ -4179,9 +4591,10 @@ handle_warn_cast_qual (tree type, tree 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"));
+         warning_at (loc, OPT_Wcast_qual,
+                     "to be safe all intermediate pointers in cast from "
+                      "%qT to %qT must be %<const%> qualified",
+                     otype, type);
          break;
        }
       if (is_const)
@@ -4190,10 +4603,11 @@ handle_warn_cast_qual (tree type, tree otype)
   while (TREE_CODE (in_type) == POINTER_TYPE);
 }
 
-/* Build an expression representing a cast to type TYPE of expression EXPR.  */
+/* 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;
 
@@ -4215,13 +4629,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;
     }
 
@@ -4236,14 +4650,14 @@ 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)
     {
       tree field;
 
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        if (TREE_TYPE (field) != error_mark_node
            && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
                          TYPE_MAIN_VARIANT (TREE_TYPE (value))))
@@ -4252,16 +4666,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),
+         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
@@ -4269,7 +4686,11 @@ 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);
 
@@ -4277,7 +4698,37 @@ build_c_cast (tree type, tree expr)
       if (warn_cast_qual
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
-       handle_warn_cast_qual (type, otype);
+       handle_warn_cast_qual (loc, 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))
+       {
+         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;
+
+         if (!addr_space_superset (as_to, as_from, &as_common))
+           {
+             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));
+
+             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));
+
+             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.  */
       if (STRICT_ALIGNMENT
@@ -4291,8 +4742,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
@@ -4302,21 +4753,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);
@@ -4329,7 +4782,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
@@ -4338,7 +4791,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;
@@ -4366,7 +4819,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
@@ -4382,12 +4835,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, location_t loc)
+c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
 {
   tree type;
   tree type_expr = NULL_TREE;
@@ -4402,18 +4859,20 @@ c_cast_expr (struct c_type_name *type_name, tree expr, location_t loc)
   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)
+  /* C++ does not permits types to be defined in a cast, but it
+     allows references to incomplete types.  */
+  if (warn_cxx_compat && type_name->specs->typespec_kind == ctsk_tagdef)
     warning_at (loc, OPT_Wc___compat,
                "defining a type in a cast is invalid in C++");
 
@@ -4429,11 +4888,13 @@ c_cast_expr (struct c_type_name *type_name, tree expr, location_t loc)
    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, tree lhs_origtype,
-                  enum tree_code modifycode, tree rhs, tree rhs_origtype)
+                  enum tree_code modifycode,
+                  location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
   tree newrhs;
@@ -4449,7 +4910,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
     return error_mark_node;
 
-  if (!lvalue_or_else (lhs, lv_assign))
+  /* For ObjC properties, defer this check.  */
+  if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4463,7 +4925,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
     {
       tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs),
-                                     lhs_origtype, modifycode, rhs,
+                                     lhs_origtype, modifycode, rhs_loc, rhs,
                                      rhs_origtype);
       if (inner == error_mark_node)
        return error_mark_node;
@@ -4490,6 +4952,19 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       rhs_origtype = NULL_TREE;
     }
 
+  if (c_dialect_objc ())
+    {
+      /* Check if we are modifying an Objective-C property reference;
+        if so, we need to generate setter calls.  */
+      result = objc_maybe_build_modify_expr (lhs, newrhs);
+      if (result)
+       return result;
+
+      /* Else, do the check that we postponed for Objective-C.  */
+      if (!lvalue_or_else (location, lhs, lv_assign))
+       return error_mark_node;
+    }
+
   /* Give an error for storing in something that is 'const'.  */
 
   if (TYPE_READONLY (lhstype)
@@ -4585,6 +5060,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   return result;
 }
 \f
+/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
+   This is used to implement -fplan9-extensions.  */
+
+static bool
+find_anonymous_field_with_type (tree struct_type, tree type)
+{
+  tree field;
+  bool found;
+
+  gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
+             || TREE_CODE (struct_type) == UNION_TYPE);
+  found = false;
+  for (field = TYPE_FIELDS (struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) == NULL
+         && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+      else if (DECL_NAME (field) == NULL
+              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+              && find_anonymous_field_with_type (TREE_TYPE (field), type))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+    }
+  return found;
+}
+
+/* RHS is an expression whose type is pointer to struct.  If there is
+   an anonymous field in RHS with type TYPE, then return a pointer to
+   that field in RHS.  This is used with -fplan9-extensions.  This
+   returns NULL if no conversion could be found.  */
+
+static tree
+convert_to_anonymous_field (location_t location, tree type, tree rhs)
+{
+  tree rhs_struct_type, lhs_main_type;
+  tree field, found_field;
+  bool found_sub_field;
+  tree ret;
+
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
+  rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
+  gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
+             || TREE_CODE (rhs_struct_type) == UNION_TYPE);
+
+  gcc_assert (POINTER_TYPE_P (type));
+  lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+
+  found_field = NULL_TREE;
+  found_sub_field = false;
+  for (field = TYPE_FIELDS (rhs_struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) != NULL_TREE
+         || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
+             && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
+       continue;
+      if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+       }
+      else if (find_anonymous_field_with_type (TREE_TYPE (field),
+                                              lhs_main_type))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+         found_sub_field = true;
+       }
+    }
+
+  if (found_field == NULL_TREE)
+    return NULL_TREE;
+
+  ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
+                        build_fold_indirect_ref (rhs), found_field,
+                        NULL_TREE);
+  ret = build_fold_addr_expr_loc (location, ret);
+
+  if (found_sub_field)
+    {
+      ret = convert_to_anonymous_field (location, type, ret);
+      gcc_assert (ret != NULL_TREE);
+    }
+
+  return ret;
+}
+
 /* 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
@@ -4596,6 +5171,7 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
    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.  */
 
@@ -4634,14 +5210,14 @@ convert_for_assignment (location_t location, tree type, tree rhs,
   /* 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;                                                           \
@@ -4649,18 +5225,48 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         pedwarn (LOCATION, OPT, AS);                                     \
         break;                                                           \
       case ic_init:                                                      \
-        pedwarn (LOCATION, OPT, IN);                                     \
+        pedwarn_init (LOCATION, OPT, IN);                                \
         break;                                                           \
       case ic_return:                                                    \
-        pedwarn (LOCATION, OPT, RE);                                     \
+        pedwarn (LOCATION, OPT, RE);                                    \
         break;                                                           \
       default:                                                           \
         gcc_unreachable ();                                              \
       }                                                                  \
   } while (0)
 
-  if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
-    rhs = TREE_OPERAND (rhs, 0);
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
+     extra parameter to enumerate qualifiers.  */
+
+#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS)        \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS))          \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))               \
+                 ? DECL_SOURCE_LOCATION (fundecl) : LOCATION,           \
+                  "expected %qT but argument is of type %qT",            \
+                  type, rhstype);                                        \
+        break;                                                           \
+      case ic_assign:                                                    \
+        pedwarn (LOCATION, OPT, AS, QUALS);                          \
+        break;                                                           \
+      case ic_init:                                                      \
+        pedwarn (LOCATION, OPT, IN, QUALS);                          \
+        break;                                                           \
+      case ic_return:                                                    \
+        pedwarn (LOCATION, OPT, RE, QUALS);                             \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
+  } while (0)
+
+  if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
+    rhs = TREE_OPERAND (rhs, 0);
 
   rhstype = TREE_TYPE (rhs);
   coder = TREE_CODE (rhstype);
@@ -4723,7 +5329,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         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);
@@ -4737,12 +5343,13 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       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
@@ -4750,9 +5357,13 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         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.  */
@@ -4771,10 +5382,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       tree ret;
       bool save = in_late_binary_op;
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = true;
       ret = convert_and_check (type, orig_rhs);
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = save;
       return ret;
     }
@@ -4785,14 +5396,15 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       && comptypes (type, rhstype))
     return convert_and_check (type, rhs);
 
-  /* Conversion to a transparent union from its member types.
+  /* Conversion to a transparent union or record from its member types.
      This applies only to function arguments.  */
-  if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+  if (((codel == UNION_TYPE || codel == RECORD_TYPE)
+      && TYPE_TRANSPARENT_AGGR (type))
       && errtype == ic_argpass)
     {
       tree memb, marginal_memb = NULL_TREE;
 
-      for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb))
+      for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb))
        {
          tree memb_type = TREE_TYPE (memb);
 
@@ -4858,39 +5470,43 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                     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_QUALIFIERS (location, 0,
                                         G_("passing argument %d of %qE "
-                                           "makes qualified function "
+                                           "makes %q#v qualified function "
                                            "pointer from unqualified"),
-                                        G_("assignment makes qualified "
+                                        G_("assignment makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("initialization makes qualified "
+                                        G_("initialization makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("return makes qualified function "
-                                           "pointer from unqualified"));
+                                        G_("return makes %q#v qualified function "
+                                           "pointer from unqualified"),
+                                        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
                }
-             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_QUALIFIERS (location, 0,
                                     G_("passing argument %d of %qE discards "
-                                       "qualifiers from pointer target type"),
-                                    G_("assignment discards qualifiers "
+                                       "%qv qualifier from pointer target type"),
+                                    G_("assignment discards %qv qualifier "
                                        "from pointer target type"),
-                                    G_("initialization discards qualifiers "
+                                    G_("initialization discards %qv qualifier "
                                        "from pointer target type"),
-                                    G_("return discards qualifiers from "
-                                       "pointer target type"));
+                                    G_("return discards %qv qualifier from "
+                                       "pointer target type"),
+                                    TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
 
              memb = marginal_memb;
            }
 
          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);
        }
     }
@@ -4905,6 +5521,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       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);
@@ -4913,6 +5531,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       /* Opaque pointers are treated like void pointers.  */
       is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
 
+      /* The Plan 9 compiler permits a pointer to a struct to be
+        automatically converted into a pointer to an anonymous field
+        within the struct.  */
+      if (flag_plan9_extensions
+         && (TREE_CODE (mvl) == RECORD_TYPE || TREE_CODE(mvl) == UNION_TYPE)
+         && (TREE_CODE (mvr) == RECORD_TYPE || TREE_CODE(mvr) == UNION_TYPE)
+         && mvl != mvr)
+       {
+         tree new_rhs = convert_to_anonymous_field (location, type, rhs);
+         if (new_rhs != NULL_TREE)
+           {
+             rhs = new_rhs;
+             rhstype = TREE_TYPE (rhs);
+             coder = TREE_CODE (rhstype);
+             ttr = TREE_TYPE (rhstype);
+             mvr = TYPE_MAIN_VARIANT (ttr);
+           }
+       }
+
       /* C++ does not allow the implicit conversion void* -> T*.  However,
         for the purpose of reducing the number of false positives, we
         tolerate the special case of
@@ -4921,8 +5558,39 @@ convert_for_assignment (location_t location, tree type, tree rhs,
 
         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.  */
@@ -4932,25 +5600,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          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 ();
@@ -4972,7 +5640,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                  (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 *%>"),
@@ -4987,21 +5655,19 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          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,
-                                        G_("passing argument %d of %qE discards "
-                                           "qualifiers from pointer target type"),
-                                        G_("assignment discards qualifiers "
-                                           "from pointer target type"),
-                                        G_("initialization discards qualifiers "
-                                           "from pointer target type"),
-                                        G_("return discards qualifiers from "
-                                           "pointer target type"));
+                 WARN_FOR_QUALIFIERS (location, 0,
+                                      G_("passing argument %d of %qE discards "
+                                         "%qv qualifier from pointer target type"),
+                                      G_("assignment discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("initialization discards %qv qualifier "
+                                         "from pointer target type"),
+                                      G_("return discards %qv qualifier from "
+                                         "pointer target type"),
+                                      TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
                }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
@@ -5010,7 +5676,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                ;
              /* 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 "
@@ -5027,23 +5693,25 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                 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_QUALIFIERS (location, 0,
                                     G_("passing argument %d of %qE makes "
-                                       "qualified function pointer "
+                                       "%q#v qualified function pointer "
                                        "from unqualified"),
-                                    G_("assignment makes qualified function "
+                                    G_("assignment makes %q#v qualified function "
                                        "pointer from unqualified"),
-                                    G_("initialization makes qualified "
+                                    G_("initialization makes %q#v qualified "
                                        "function pointer from unqualified"),
-                                    G_("return makes qualified function "
-                                       "pointer from unqualified"));
+                                    G_("return makes %q#v qualified function "
+                                       "pointer from unqualified"),
+                                    TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
            }
        }
       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"),
@@ -5057,7 +5725,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       /* ??? 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)
@@ -5066,7 +5734,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         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 "
@@ -5080,7 +5748,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     }
   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 "
@@ -5104,22 +5772,24 @@ convert_for_assignment (location_t location, tree type, tree rhs,
   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 ();
@@ -5155,10 +5825,12 @@ valid_compound_expr_initializer (tree value, tree endtype)
    store it in the declaration DECL,
    and print any error messages that are appropriate.
    If ORIGTYPE is not NULL_TREE, it is the original type of INIT.
-   If the init is invalid, store an ERROR_MARK.  */
+   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, tree origtype)
+store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
 {
   tree value, type;
   bool npc = false;
@@ -5173,7 +5845,8 @@ store_init_value (tree decl, tree init, tree origtype)
 
   if (init)
     npc = null_pointer_constant_p (init);
-  value = digest_init (type, init, origtype, 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.  */
 
@@ -5186,7 +5859,7 @@ store_init_value (tree decl, tree init, tree origtype)
 
   /* 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.  */
@@ -5208,11 +5881,13 @@ store_init_value (tree decl, tree init, tree origtype)
              /* For int foo[] = (int [3]){1}; we need to set array size
                 now since later on array initializer will be just the
                 brace enclosed list of the compound literal.  */
+             tree etype = strip_array_types (TREE_TYPE (decl));
              type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-             TREE_TYPE (decl) = type;
              TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
              layout_type (type);
              layout_decl (cldecl, 0);
+             TREE_TYPE (decl)
+               = c_build_qualified_type (type, TYPE_QUALS (etype));
            }
        }
     }
@@ -5341,15 +6016,16 @@ print_spelling (char *buffer)
 }
 
 /* Issue an error message for a bad initializer component.
-   MSGID identifies the message.
+   GMSGID identifies the message.
    The component name is taken from the spelling stack.  */
 
 void
-error_init (const char *msgid)
+error_init (const char *gmsgid)
 {
   char *ofwhat;
 
-  error ("%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  error (gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for %qs)", ofwhat);
@@ -5357,32 +6033,34 @@ error_init (const char *msgid)
 
 /* Issue a pedantic warning for a bad initializer component.  OPT is
    the option OPT_* (from options.h) controlling this warning or 0 if
-   it is unconditionally given.  MSGID identifies the message.  The
+   it is unconditionally given.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
 void
-pedwarn_init (location_t location, int opt, const char *msgid)
+pedwarn_init (location_t location, int opt, const char *gmsgid)
 {
   char *ofwhat;
 
-  pedwarn (location, opt, "%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  pedwarn (location, opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     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
+   controls this warning.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
 static void
-warning_init (int opt, const char *msgid)
+warning_init (int opt, const char *gmsgid)
 {
   char *ofwhat;
 
-  warning (opt, "%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  warning (opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning (opt, "(near initialization for %qs)", ofwhat);
@@ -5399,7 +6077,7 @@ 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");
 }
 
@@ -5414,12 +6092,15 @@ maybe_warn_string_init (tree type, struct c_expr expr)
    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, tree origtype, 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;
@@ -5469,7 +6150,7 @@ digest_init (tree type, tree init, tree origtype, bool null_pointer_constant,
          maybe_warn_string_init (type, expr);
 
          if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
-           pedwarn_init (input_location, OPT_pedantic,
+           pedwarn_init (init_loc, OPT_pedantic,
                          "initialization of a flexible array member");
 
          if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
@@ -5503,16 +6184,26 @@ digest_init (tree type, tree init, tree origtype, 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;
        }
@@ -5582,7 +6273,8 @@ digest_init (tree type, tree init, tree origtype, 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");
@@ -5627,7 +6319,7 @@ digest_init (tree type, tree init, tree origtype, 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;
@@ -5640,13 +6332,13 @@ digest_init (tree type, tree init, tree origtype, 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 (input_location, type,
-                                             inside_init, origtype,
+       inside_init = convert_for_assignment (init_loc, type, inside_init,
+                                             origtype,
                                              ic_init, null_pointer_constant,
                                              NULL_TREE, NULL_TREE, 0);
       return inside_init;
@@ -5661,13 +6353,13 @@ digest_init (tree type, tree init, tree origtype, 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 (input_location, type, inside_init, origtype,
-                                 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.  */
@@ -5686,7 +6378,7 @@ digest_init (tree type, tree init, tree origtype, 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;
@@ -6020,7 +6712,7 @@ really_start_incremental_init (tree type)
       /* Skip any nameless bit fields at the beginning.  */
       while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
-       constructor_fields = TREE_CHAIN (constructor_fields);
+       constructor_fields = DECL_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6035,14 +6727,14 @@ really_start_incremental_init (tree type)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          constructor_index
            = convert (bitsizetype,
@@ -6060,7 +6752,7 @@ really_start_incremental_init (tree type)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = bitsize_zero_node;
       constructor_unfilled_index = constructor_index;
     }
@@ -6078,7 +6770,7 @@ really_start_incremental_init (tree type)
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
-push_init_level (int implicit)
+push_init_level (int implicit, struct obstack * braced_init_obstack)
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -6096,12 +6788,14 @@ push_init_level (int implicit)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
-           process_init_element (pop_init_level (1), true);
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
          else if (TREE_CODE (constructor_type) == ARRAY_TYPE
                   && constructor_max_index
                   && tree_int_cst_lt (constructor_max_index,
                                       constructor_index))
-           process_init_element (pop_init_level (1), true);
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
          else
            break;
        }
@@ -6114,9 +6808,9 @@ push_init_level (int implicit)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields)
-       value = find_init_member (constructor_fields);
+       value = find_init_member (constructor_fields, braced_init_obstack);
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       value = find_init_member (constructor_index);
+       value = find_init_member (constructor_index, braced_init_obstack);
     }
 
   p = XNEW (struct constructor_stack);
@@ -6202,7 +6896,7 @@ push_init_level (int implicit)
       if (!VEC_empty (constructor_elt, constructor_elements)
          && (TREE_CODE (constructor_type) == RECORD_TYPE
              || TREE_CODE (constructor_type) == ARRAY_TYPE))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
     }
 
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
@@ -6218,7 +6912,7 @@ push_init_level (int implicit)
       /* Skip any nameless bit fields at the beginning.  */
       while (constructor_fields != 0 && DECL_C_BIT_FIELD (constructor_fields)
             && DECL_NAME (constructor_fields) == 0)
-       constructor_fields = TREE_CHAIN (constructor_fields);
+       constructor_fields = DECL_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6227,8 +6921,8 @@ push_init_level (int implicit)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
-      constructor_index = convert (bitsizetype, integer_zero_node);
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+      constructor_index = bitsize_int (0);
       constructor_unfilled_index = constructor_index;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -6241,14 +6935,14 @@ push_init_level (int implicit)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_type))
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          constructor_index
            = convert (bitsizetype,
@@ -6263,7 +6957,7 @@ push_init_level (int implicit)
          /* We need to split the char/wchar array into individual
             characters, so that we don't have to special case it
             everywhere.  */
-         set_nonincremental_init_from_string (value);
+         set_nonincremental_init_from_string (value, braced_init_obstack);
        }
     }
   else
@@ -6287,7 +6981,7 @@ push_init_level (int implicit)
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
-pop_init_level (int implicit)
+pop_init_level (int implicit, struct obstack * braced_init_obstack)
 {
   struct constructor_stack *p;
   struct c_expr ret;
@@ -6300,14 +6994,16 @@ pop_init_level (int implicit)
       /* When we come to an explicit close brace,
         pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1), true);
-
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
       gcc_assert (!constructor_range_stack);
     }
 
   /* Now output all pending elements.  */
   constructor_incremental = 1;
-  output_pending_init_elements (1);
+  output_pending_init_elements (1, braced_init_obstack);
 
   p = constructor_stack;
 
@@ -6335,7 +7031,7 @@ pop_init_level (int implicit)
          /* We have already issued an error message for the existence
             of a flexible array member not at the end of the structure.
             Discard the initializer so that we do not die later.  */
-         if (TREE_CHAIN (constructor_fields) != NULL_TREE)
+         if (DECL_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
     }
@@ -6346,15 +7042,23 @@ pop_init_level (int implicit)
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
     {
+       bool constructor_zeroinit =
+        (VEC_length (constructor_elt, constructor_elements) == 1
+         && integer_zerop
+             (VEC_index (constructor_elt, constructor_elements, 0)->value));
+
        /* Do not warn for flexible array members or zero-length arrays.  */
        while (constructor_unfilled_fields
               && (!DECL_SIZE (constructor_unfilled_fields)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
-         constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
-
-       /* Do not warn if this level of the initializer uses member
-          designators; it is likely to be deliberate.  */
-       if (constructor_unfilled_fields && !constructor_designated)
+         constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
+
+       if (constructor_unfilled_fields
+           /* Do not warn if this level of the initializer uses member
+              designators; it is likely to be deliberate.  */
+           && !constructor_designated
+           /* Do not warn about initializing with ` = {0}'.  */
+           && !constructor_zeroinit)
          {
            push_member_name (constructor_unfilled_fields);
            warning_init (OPT_Wmissing_field_initializers,
@@ -6448,7 +7152,7 @@ pop_init_level (int implicit)
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
-set_designator (int array)
+set_designator (int array, struct obstack * braced_init_obstack)
 {
   tree subtype;
   enum tree_code subcode;
@@ -6470,7 +7174,10 @@ set_designator (int array)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1), true);
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
       constructor_designated = 1;
       return 0;
     }
@@ -6503,7 +7210,7 @@ set_designator (int array)
     }
 
   constructor_designated = 1;
-  push_init_level (2);
+  push_init_level (2, braced_init_obstack);
   return 0;
 }
 
@@ -6512,11 +7219,13 @@ set_designator (int array)
    NULL_TREE if there is no range designator at this level.  */
 
 static void
-push_range_stack (tree range_end)
+push_range_stack (tree range_end, struct obstack * braced_init_obstack)
 {
   struct constructor_range_stack *p;
 
-  p = GGC_NEW (struct constructor_range_stack);
+  p = (struct constructor_range_stack *)
+    obstack_alloc (braced_init_obstack,
+                  sizeof (struct constructor_range_stack));
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
@@ -6534,9 +7243,10 @@ push_range_stack (tree range_end)
    of indices, running from FIRST through LAST.  */
 
 void
-set_init_index (tree first, tree last)
+set_init_index (tree first, tree last,
+               struct obstack * braced_init_obstack)
 {
-  if (set_designator (1))
+  if (set_designator (1, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -6608,18 +7318,18 @@ set_init_index (tree first, tree last)
       designator_depth++;
       designator_erroneous = 0;
       if (constructor_range_stack || last)
-       push_range_stack (last);
+       push_range_stack (last, braced_init_obstack);
     }
 }
 
 /* Within a struct initializer, specify the next field to be initialized.  */
 
 void
-set_init_label (tree fieldname)
+set_init_label (tree fieldname, struct obstack * braced_init_obstack)
 {
-  tree tail;
+  tree field;
 
-  if (set_designator (0))
+  if (set_designator (0, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -6631,23 +7341,26 @@ set_init_label (tree fieldname)
       return;
     }
 
-  for (tail = TYPE_FIELDS (constructor_type); tail;
-       tail = TREE_CHAIN (tail))
-    {
-      if (DECL_NAME (tail) == fieldname)
-       break;
-    }
+  field = lookup_field (constructor_type, fieldname);
 
-  if (tail == 0)
+  if (field == 0)
     error ("unknown field %qE specified in initializer", fieldname);
   else
-    {
-      constructor_fields = tail;
-      designator_depth++;
-      designator_erroneous = 0;
-      if (constructor_range_stack)
-       push_range_stack (NULL_TREE);
-    }
+    do
+      {
+       constructor_fields = TREE_VALUE (field);
+       designator_depth++;
+       designator_erroneous = 0;
+       if (constructor_range_stack)
+         push_range_stack (NULL_TREE, braced_init_obstack);
+       field = TREE_CHAIN (field);
+       if (field)
+         {
+           if (set_designator (0, braced_init_obstack))
+             return;
+         }
+      }
+    while (field != NULL_TREE);
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
@@ -6661,7 +7374,8 @@ set_init_label (tree fieldname)
    existing initializer.  */
 
 static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
+add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
+                 struct obstack * braced_init_obstack)
 {
   struct init_node *p, **q, *r;
 
@@ -6720,7 +7434,8 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
        }
     }
 
-  r = GGC_NEW (struct init_node);
+  r = (struct init_node *) obstack_alloc (braced_init_obstack,
+                                         sizeof (struct init_node));
   r->purpose = purpose;
   r->value = value;
   r->origtype = origtype;
@@ -6889,7 +7604,7 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
 /* Build AVL tree from a sorted chain.  */
 
 static void
-set_nonincremental_init (void)
+set_nonincremental_init (struct obstack * braced_init_obstack)
 {
   unsigned HOST_WIDE_INT ix;
   tree index, value;
@@ -6899,7 +7614,10 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    add_pending_init (index, value, NULL_TREE, false);
+    {
+      add_pending_init (index, value, NULL_TREE, true,
+                       braced_init_obstack);
+    }
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -6926,7 +7644,8 @@ set_nonincremental_init (void)
 /* Build AVL tree from a string constant.  */
 
 static void
-set_nonincremental_init_from_string (tree str)
+set_nonincremental_init_from_string (tree str,
+                                    struct obstack * braced_init_obstack)
 {
   tree value, purpose, type;
   HOST_WIDE_INT val[2];
@@ -6989,7 +7708,8 @@ set_nonincremental_init_from_string (tree str)
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, NULL_TREE, false);
+      add_pending_init (purpose, value, NULL_TREE, true,
+                        braced_init_obstack);
     }
 
   constructor_incremental = 0;
@@ -6999,7 +7719,7 @@ set_nonincremental_init_from_string (tree str)
    not initialized yet.  */
 
 static tree
-find_init_member (tree field)
+find_init_member (tree field, struct obstack * braced_init_obstack)
 {
   struct init_node *p;
 
@@ -7007,7 +7727,7 @@ find_init_member (tree field)
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
       p = constructor_pending_elts;
       while (p)
@@ -7028,7 +7748,7 @@ find_init_member (tree field)
          && (!constructor_unfilled_fields
              || tree_int_cst_lt (bitpos,
                                  bit_position (constructor_unfilled_fields))))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
       p = constructor_pending_elts;
       while (p)
@@ -7072,7 +7792,8 @@ find_init_member (tree field)
 
 static void
 output_init_element (tree value, tree origtype, bool strict_string, tree type,
-                    tree field, int pending, bool implicit)
+                    tree field, int pending, bool implicit,
+                    struct obstack * braced_init_obstack)
 {
   tree semantic_type = NULL_TREE;
   constructor_elt *celt;
@@ -7092,7 +7813,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
           && 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)
@@ -7166,13 +7887,13 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
          || (COMPLETE_TYPE_P (TREE_TYPE (field))
              && integer_zerop (TYPE_SIZE (TREE_TYPE (field)))
              && (TREE_CODE (constructor_type) == ARRAY_TYPE
-                 || TREE_CHAIN (field)))))
+                 || DECL_CHAIN (field)))))
     return;
 
   if (semantic_type)
     value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
-  value = digest_init (type, value, origtype, 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;
@@ -7189,9 +7910,10 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
-      add_pending_init (field, value, origtype, implicit);
+      add_pending_init (field, value, origtype, implicit,
+                       braced_init_obstack);
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -7204,7 +7926,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
       if (constructor_incremental)
        {
          if (!constructor_unfilled_fields)
-           set_nonincremental_init ();
+           set_nonincremental_init (braced_init_obstack);
          else
            {
              tree bitpos, unfillpos;
@@ -7213,11 +7935,12 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
              unfillpos = bit_position (constructor_unfilled_fields);
 
              if (tree_int_cst_lt (bitpos, unfillpos))
-               set_nonincremental_init ();
+               set_nonincremental_init (braced_init_obstack);
            }
        }
 
-      add_pending_init (field, value, origtype, implicit);
+      add_pending_init (field, value, origtype, implicit,
+                       braced_init_obstack);
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
@@ -7247,26 +7970,26 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
   /* 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
-       = TREE_CHAIN (constructor_unfilled_fields);
+       = DECL_CHAIN (constructor_unfilled_fields);
 
       /* Skip any nameless bit fields.  */
       while (constructor_unfilled_fields != 0
             && DECL_C_BIT_FIELD (constructor_unfilled_fields)
             && DECL_NAME (constructor_unfilled_fields) == 0)
        constructor_unfilled_fields =
-         TREE_CHAIN (constructor_unfilled_fields);
+         DECL_CHAIN (constructor_unfilled_fields);
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     constructor_unfilled_fields = 0;
 
   /* Now output any pending elements which have become next.  */
   if (pending)
-    output_pending_init_elements (0);
+    output_pending_init_elements (0, braced_init_obstack);
 }
 
 /* Output any pending elements which have become next.
@@ -7279,9 +8002,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
 
    If ALL is 1, we output space as necessary so that
    we can output all the pending elements.  */
-
 static void
-output_pending_init_elements (int all)
+output_pending_init_elements (int all, struct obstack * braced_init_obstack)
 {
   struct init_node *elt = constructor_pending_elts;
   tree next;
@@ -7302,7 +8024,8 @@ output_pending_init_elements (int all)
                                  constructor_unfilled_index))
            output_init_element (elt->value, elt->origtype, true,
                                 TREE_TYPE (constructor_type),
-                                constructor_unfilled_index, 0, false);
+                                constructor_unfilled_index, 0, false,
+                                braced_init_obstack);
          else if (tree_int_cst_lt (constructor_unfilled_index,
                                    elt->purpose))
            {
@@ -7356,7 +8079,8 @@ output_pending_init_elements (int all)
              constructor_unfilled_fields = elt->purpose;
              output_init_element (elt->value, elt->origtype, true,
                                   TREE_TYPE (elt->purpose),
-                                  elt->purpose, 0, false);
+                                  elt->purpose, 0, false,
+                                  braced_init_obstack);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
@@ -7427,7 +8151,8 @@ output_pending_init_elements (int all)
    existing initializer.  */
 
 void
-process_init_element (struct c_expr value, bool implicit)
+process_init_element (struct c_expr value, bool implicit,
+                     struct obstack * braced_init_obstack)
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
@@ -7468,13 +8193,15 @@ process_init_element (struct c_expr value, bool implicit)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields == 0)
-       process_init_element (pop_init_level (1), true);
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
       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)))
-       process_init_element (pop_init_level (1), true);
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
       else
        break;
     }
@@ -7524,7 +8251,7 @@ process_init_element (struct c_expr value, bool implicit)
          if (fieldcode == ARRAY_TYPE
              && !require_constant_value
              && TYPE_SIZE (fieldtype) == NULL_TREE
-             && TREE_CHAIN (constructor_fields) == NULL_TREE)
+             && DECL_CHAIN (constructor_fields) == NULL_TREE)
            {
              error_init ("non-static initialization of a flexible array member");
              break;
@@ -7544,7 +8271,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
@@ -7553,7 +8280,8 @@ process_init_element (struct c_expr value, bool implicit)
              push_member_name (constructor_fields);
              output_init_element (value.value, value.original_type,
                                   strict_string, fieldtype,
-                                  constructor_fields, 1, implicit);
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7563,30 +8291,30 @@ 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.  */
              if (constructor_unfilled_fields == constructor_fields)
                {
-                 constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+                 constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
                  /* Skip any nameless bit fields.  */
                  while (constructor_unfilled_fields != 0
                         && DECL_C_BIT_FIELD (constructor_unfilled_fields)
                         && DECL_NAME (constructor_unfilled_fields) == 0)
                    constructor_unfilled_fields =
-                     TREE_CHAIN (constructor_unfilled_fields);
+                     DECL_CHAIN (constructor_unfilled_fields);
                }
            }
 
-         constructor_fields = TREE_CHAIN (constructor_fields);
+         constructor_fields = DECL_CHAIN (constructor_fields);
          /* Skip any nameless bit fields at the beginning.  */
          while (constructor_fields != 0
                 && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
-           constructor_fields = TREE_CHAIN (constructor_fields);
+           constructor_fields = DECL_CHAIN (constructor_fields);
        }
       else if (TREE_CODE (constructor_type) == UNION_TYPE)
        {
@@ -7635,7 +8363,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
@@ -7644,7 +8372,8 @@ process_init_element (struct c_expr value, bool implicit)
              push_member_name (constructor_fields);
              output_init_element (value.value, value.original_type,
                                   strict_string, fieldtype,
-                                  constructor_fields, 1, implicit);
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7652,7 +8381,7 @@ process_init_element (struct c_expr value, bool implicit)
               directly output as a constructor.  */
            {
              constructor_bit_index = DECL_SIZE (constructor_fields);
-             constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+             constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
            }
 
          constructor_fields = 0;
@@ -7676,7 +8405,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
@@ -7695,12 +8424,14 @@ process_init_element (struct c_expr value, bool implicit)
              push_array_bounds (tree_low_cst (constructor_index, 1));
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
-                                  constructor_index, 1, implicit);
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
              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
@@ -7728,11 +8459,13 @@ process_init_element (struct c_expr value, bool implicit)
                elttype = TYPE_MAIN_VARIANT (constructor_type);
              output_init_element (value.value, value.original_type,
                                   strict_string, elttype,
-                                  constructor_index, 1, implicit);
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
            }
 
          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
@@ -7755,7 +8488,8 @@ process_init_element (struct c_expr value, bool implicit)
          if (value.value)
            output_init_element (value.value, value.original_type,
                                 strict_string, constructor_type,
-                                NULL_TREE, 1, implicit);
+                                NULL_TREE, 1, implicit,
+                                braced_init_obstack);
          constructor_fields = 0;
        }
 
@@ -7771,17 +8505,21 @@ process_init_element (struct c_expr value, bool implicit)
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1), true);
+             process_init_element (pop_init_level (1,
+                                                   braced_init_obstack),
+                                   true, braced_init_obstack);
            }
          for (p = range_stack;
               !p->range_end || tree_int_cst_equal (p->index, p->range_end);
               p = p->prev)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1), true);
+             process_init_element (pop_init_level (1, braced_init_obstack),
+                                   true, braced_init_obstack);
            }
 
-         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;
 
@@ -7797,7 +8535,7 @@ process_init_element (struct c_expr value, bool implicit)
              p = p->next;
              if (!p)
                break;
-             push_init_level (2);
+             push_init_level (2, braced_init_obstack);
              p->stack = constructor_stack;
              if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
                p->index = p->range_start;
@@ -7831,8 +8569,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;
@@ -7846,7 +8584,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))
@@ -7861,7 +8599,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
         get an error.  Gross, but ...  */
       STRIP_NOPS (output);
 
-      if (!lvalue_or_else (output, lv_asm))
+      if (!lvalue_or_else (loc, output, lv_asm))
        output = error_mark_node;
 
       if (output != error_mark_node
@@ -7882,6 +8620,13 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
             mark it addressable.  */
          if (!allows_reg && !c_mark_addressable (output))
            output = error_mark_node;
+         if (!(!allows_reg && allows_mem)
+             && output != error_mark_node
+             && VOID_TYPE_P (TREE_TYPE (output)))
+           {
+             error_at (loc, "invalid use of void expression");
+             output = error_mark_node;
+           }
        }
       else
        output = error_mark_node;
@@ -7908,7 +8653,12 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
              STRIP_NOPS (input);
              if (!c_mark_addressable (input))
                input = error_mark_node;
-         }
+           }
+         else if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
+           {
+             error_at (loc, "invalid use of void expression");
+             input = error_mark_node;
+           }
        }
       else
        input = error_mark_node;
@@ -7916,7 +8666,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.  */
@@ -7926,78 +8680,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.  If
-   ORIGTYPE is not NULL_TREE, it is the original type of RETVAL.  */
+   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, tree origtype)
+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)
     {
@@ -8019,7 +8748,7 @@ c_finish_return (tree retval, tree origtype)
       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;
@@ -8029,17 +8758,17 @@ c_finish_return (tree retval, tree origtype)
     {
       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 (input_location, valtype, retval,
-                                      origtype, 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;
 
@@ -8092,7 +8821,8 @@ c_finish_return (tree retval, tree origtype)
                  && !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:
@@ -8103,12 +8833,13 @@ c_finish_return (tree retval, tree origtype)
        }
 
       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);
 }
@@ -8128,15 +8859,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;
@@ -8151,10 +8876,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;
@@ -8167,7 +8895,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;
@@ -8179,8 +8907,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);
@@ -8193,20 +8922,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;
 
@@ -8226,39 +8955,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;
 }
 
@@ -8272,16 +8988,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));
@@ -8289,6 +8997,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
@@ -8333,9 +9042,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);
@@ -8393,11 +9101,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);
@@ -8418,7 +9127,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;
@@ -8435,7 +9144,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)
     ;
@@ -8443,14 +9152,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:
@@ -8469,26 +9178,28 @@ 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)
 {
+  tree exprv;
+
   if (!expr)
     return NULL_TREE;
 
@@ -8500,33 +9211,44 @@ 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);
+
+  exprv = expr;
+  while (TREE_CODE (exprv) == COMPOUND_EXPR)
+    exprv = TREE_OPERAND (exprv, 1);
+  while (CONVERT_EXPR_P (exprv))
+    exprv = TREE_OPERAND (exprv, 0);
+  if (DECL_P (exprv)
+      || handled_component_p (exprv)
+      || TREE_CODE (exprv) == ADDR_EXPR)
+    mark_exp_read (exprv);
 
   /* 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;
 }
@@ -8538,30 +9260,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;
@@ -8569,42 +9277,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.  */
@@ -8625,7 +9311,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);
@@ -8643,16 +9335,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;
@@ -8680,83 +9373,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));
+  SET_EXPR_LOCATION (*last_p, EXPR_LOCATION (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;
-
-  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
@@ -8771,8 +9394,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;
 
@@ -8784,19 +9411,20 @@ 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
      do the wrong thing for ({ { 1; } }) or ({ 1; { } }).  In particular,
      STATEMENT_LISTs merge, and thus we can lose track of what statement
      was really last.  */
-  if (cur_stmt_list
+  if (building_stmt_list_p ()
       && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
       && TREE_CODE (stmt) != BIND_EXPR)
     {
       stmt = build3 (BIND_EXPR, void_type_node, NULL, stmt, NULL);
       TREE_SIDE_EFFECTS (stmt) = 1;
+      SET_EXPR_LOCATION (stmt, loc);
     }
 
   return stmt;
@@ -8807,20 +9435,102 @@ 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 ();
   TREE_OPERAND (stmt, 0) = list;
   STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
 }
+
+/* Convert scalar to vector for the range of operations.  */
+static enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
+{
+  tree type0 = TREE_TYPE (op0);
+  tree type1 = TREE_TYPE (op1);
+  bool integer_only_op = false;
+  enum stv_conv ret = stv_firstarg;
+
+  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+             || TREE_CODE (type1) == VECTOR_TYPE);
+  switch (code)
+    {
+      case RSHIFT_EXPR:
+      case LSHIFT_EXPR:
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           else
+             return stv_firstarg;
+         }
+       break;
+
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+      case BIT_AND_EXPR:
+       integer_only_op = true;
+       /* ... fall through ...  */
+
+      case PLUS_EXPR:
+      case MINUS_EXPR:
+      case MULT_EXPR:
+      case TRUNC_DIV_EXPR:
+      case TRUNC_MOD_EXPR:
+      case RDIV_EXPR:
+       if (TREE_CODE (type0) == VECTOR_TYPE)
+         {
+           tree tmp;
+           ret = stv_secondarg;
+           /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
+           tmp = type0; type0 = type1; type1 = tmp;
+           tmp = op0; op0 = op1; op1 = tmp;
+         }
+
+       if (TREE_CODE (type0) == INTEGER_TYPE
+           && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           return ret;
+         }
+       else if (!integer_only_op
+                   /* Allow integer --> real conversion if safe.  */
+                && (TREE_CODE (type0) == REAL_TYPE
+                    || TREE_CODE (type0) == INTEGER_TYPE)
+                && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+         {
+           if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+             {
+               error_at (loc, "conversion of scalar to vector "
+                              "involves truncation");
+               return stv_error;
+             }
+           return ret;
+         }
+      default:
+       break;
+    }
+
+  return stv_nothing;
+}
 \f
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
@@ -8862,7 +9572,7 @@ build_binary_op (location_t location, enum tree_code code,
 
   /* When the computation is in excess precision, the type of the
      final EXCESS_PRECISION_EXPR.  */
-  tree real_result_type = NULL;
+  tree semantic_result_type = NULL;
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
@@ -8904,6 +9614,10 @@ build_binary_op (location_t location, enum tree_code code,
      precision.  */
   bool may_need_excess_precision;
 
+  /* True means this is a boolean operation that converts both its
+     operands to truth-values.  */
+  bool boolean_op = false;
+
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
@@ -8928,7 +9642,10 @@ build_binary_op (location_t location, enum tree_code code,
   else
     int_const = int_const_or_overflow = false;
 
-  if (convert_p)
+  /* Do not apply default conversion in mixed vector/scalar expression.  */
+  if (convert_p
+      && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
+          != (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE)))
     {
       op0 = default_conversion (op0);
       op1 = default_conversion (op1);
@@ -9000,18 +9717,63 @@ build_binary_op (location_t location, enum tree_code code,
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* In case when one of the operands of the binary operation is
+     a vector and another is a scalar -- convert scalar to vector.  */
+  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
+    {
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
+
+      switch (convert_flag)
+       {
+         case stv_error:
+           return error_mark_node;
+         case stv_firstarg:
+           {
+              bool maybe_const = true;
+              tree sc;
+              sc = c_fully_fold (op0, false, &maybe_const);
+              sc = save_expr (sc);
+              sc = convert (TREE_TYPE (type1), sc);
+              op0 = build_vector_from_val (type1, sc);
+              if (!maybe_const)
+                op0 = c_wrap_maybe_const (op0, true);
+              orig_type0 = type0 = TREE_TYPE (op0);
+              code0 = TREE_CODE (type0);
+              converted = 1;
+              break;
+           }
+         case stv_secondarg:
+           {
+             bool maybe_const = true;
+             tree sc;
+             sc = c_fully_fold (op1, false, &maybe_const);
+             sc = save_expr (sc);
+             sc = convert (TREE_TYPE (type0), sc);
+             op1 = build_vector_from_val (type0, sc);
+             if (!maybe_const)
+               op1 = c_wrap_maybe_const (op1, true);
+             orig_type1 = type1 = TREE_TYPE (op1);
+             code1 = TREE_CODE (type1);
+             converted = 1;
+             break;
+           }
+         default:
+           break;
+       }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
       /* Handle the pointer + int case.  */
       if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (PLUS_EXPR, op0, op1);
+         ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
          goto return_build_binary_op;
        }
       else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (PLUS_EXPR, op1, op0);
+         ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
          goto return_build_binary_op;
        }
       else
@@ -9024,13 +9786,13 @@ build_binary_op (location_t location, enum tree_code code,
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
          && 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.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (MINUS_EXPR, op0, op1);
+         ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
          goto return_build_binary_op;
        }
       else
@@ -9131,6 +9893,7 @@ build_binary_op (location_t location, enum tree_code code,
          op0 = c_common_truthvalue_conversion (location, op0);
          op1 = c_common_truthvalue_conversion (location, op1);
          converted = 1;
+         boolean_op = true;
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
@@ -9161,7 +9924,21 @@ build_binary_op (location_t location, enum tree_code code,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9169,7 +9946,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
@@ -9180,7 +9957,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");
                    }
                }
@@ -9188,9 +9965,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
-         /* Convert the shift-count to an integer, regardless of size
-            of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9198,7 +9976,21 @@ build_binary_op (location_t location, enum tree_code code,
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9206,23 +9998,24 @@ 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");
                }
            }
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
-         /* Convert the shift-count to an integer, regardless of size
-            of value being shifted.  */
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+         /* Convert the non vector shift-count to an integer, regardless
+            of size of value being shifted.  */
+         if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+             && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9231,6 +10024,31 @@ build_binary_op (location_t location, enum tree_code code,
 
     case EQ_EXPR:
     case NE_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
        warning_at (location,
                    OPT_Wfloat_equal,
@@ -9243,28 +10061,74 @@ build_binary_op (location_t location, enum tree_code code,
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+       {
+         if (TREE_CODE (op0) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+           }
+         result_type = type0;
+       }
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+       {
+         if (TREE_CODE (op1) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+           }
+         result_type = type1;
+       }
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
          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 (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
+         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");
            }
@@ -9275,25 +10139,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;
-       }
-      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
-       {
-         if (TREE_CODE (op0) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
-           warning_at (location,
-                       OPT_Waddress, "the address of %qD will never be NULL",
-                       TREE_OPERAND (op0, 0));
-         result_type = type0;
-       }
-      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
-       {
-         if (TREE_CODE (op1) == ADDR_EXPR
-             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
-           warning_at (location,
-                       OPT_Waddress, "the address of %qD will never be NULL",
-                       TREE_OPERAND (op1, 0));
-         result_type = type1;
+           {
+             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 && code1 == INTEGER_TYPE)
        {
@@ -9311,6 +10161,31 @@ build_binary_op (location_t location, enum tree_code code,
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == FIXED_POINT_TYPE)
@@ -9319,6 +10194,10 @@ build_binary_op (location_t location, enum tree_code code,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
+         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);
@@ -9329,10 +10208,23 @@ build_binary_op (location_t location, enum tree_code code,
              else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "ordered comparisons of pointers to functions");
+             else if (null_pointer_constant_p (orig_op0)
+                      || null_pointer_constant_p (orig_op1))
+               warning_at (location, OPT_Wextra,
+                           "ordered comparison of pointer with null pointer");
+
+           }
+         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");
            }
@@ -9341,17 +10233,21 @@ 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,
-                    "ordered comparison of pointer with integer zero");
+                       "ordered comparison of pointer with integer zero");
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
-         pedwarn (location, OPT_pedantic, 
-                  "ordered comparison of pointer with integer zero");
+         if (pedantic)
+           pedwarn (location, OPT_pedantic,
+                    "ordered comparison of pointer with integer zero");
+         else if (extra_warnings)
+           warning_at (location, OPT_Wextra,
+                       "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -9394,6 +10290,11 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten || common || short_compare)
        {
          result_type = c_common_type (type0, type1);
+         do_warn_double_promotion (result_type, type0, type1,
+                                   "implicit conversion from %qT to %qT "
+                                   "to match other operand of binary "
+                                   "expression",
+                                   location);
          if (result_type == error_mark_node)
            return error_mark_node;
        }
@@ -9415,7 +10316,7 @@ build_binary_op (location_t location, enum tree_code code,
          if (type0 != orig_type0 || type1 != orig_type1)
            {
              gcc_assert (may_need_excess_precision && common);
-             real_result_type = c_common_type (orig_type0, orig_type1);
+             semantic_result_type = c_common_type (orig_type0, orig_type1);
            }
          if (first_complex)
            {
@@ -9444,6 +10345,7 @@ build_binary_op (location_t location, enum tree_code code,
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = c_save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -9464,6 +10366,7 @@ build_binary_op (location_t location, enum tree_code code,
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = c_save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -9495,7 +10398,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);
        }
 
@@ -9512,6 +10415,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
@@ -9553,7 +10457,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;
@@ -9570,10 +10474,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);
@@ -9586,20 +10492,12 @@ build_binary_op (location_t location, enum tree_code code,
                warn_for_sign_compare (location, orig_op0_folded,
                                       orig_op1_folded, op0, op1,
                                       result_type, resultcode);
-             if (!in_late_binary_op)
+             if (!in_late_binary_op && !int_operands)
                {
                  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);
                }
            }
        }
@@ -9617,12 +10515,21 @@ build_binary_op (location_t location, enum tree_code code,
       return error_mark_node;
     }
 
+  if (build_type == NULL_TREE)
+    {
+      build_type = result_type;
+      if ((type0 != orig_type0 || type1 != orig_type1)
+         && !boolean_op)
+       {
+         gcc_assert (may_need_excess_precision && common);
+         semantic_result_type = c_common_type (orig_type0, orig_type1);
+       }
+    }
+
   if (!converted)
     {
-      if (TREE_TYPE (op0) != result_type)
-       op0 = convert_and_check (result_type, op0);
-      if (TREE_TYPE (op1) != result_type)
-       op1 = convert_and_check (result_type, op1);
+      op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
+      op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
@@ -9630,21 +10537,12 @@ build_binary_op (location_t location, enum tree_code code,
        return error_mark_node;
     }
 
-  if (build_type == NULL_TREE)
-    {
-      build_type = result_type;
-      if (type0 != orig_type0 || type1 != orig_type1)
-       {
-         gcc_assert (may_need_excess_precision && common);
-         real_result_type = c_common_type (orig_type0, orig_type1);
-       }
-    }
-
   /* 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)
@@ -9659,8 +10557,8 @@ build_binary_op (location_t location, enum tree_code code,
   else if (TREE_CODE (ret) != INTEGER_CST && int_operands
           && !in_late_binary_op)
     ret = note_integer_operands (ret);
-  if (real_result_type)
-    ret = build1 (EXCESS_PRECISION_EXPR, real_result_type, ret);
+  if (semantic_result_type)
+    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
   protected_set_expr_location (ret, location);
   return ret;
 }
@@ -9688,9 +10586,17 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
       error_at (location, "used union type value where scalar is required");
       return error_mark_node;
 
+    case VOID_TYPE:
+      error_at (location, "void value not ignored as it ought to be");
+      return error_mark_node;
+
     case FUNCTION_TYPE:
       gcc_unreachable ();
 
+    case VECTOR_TYPE:
+      error_at (location, "used vector type where scalar is required");
+      return error_mark_node;
+
     default:
       break;
     }
@@ -9700,8 +10606,8 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
   if (int_operands)
     expr = remove_c_maybe_const_expr (expr);
 
-  /* ??? Should we also give an error for void and vectors rather than
-     leaving those to give errors later?  */
+  /* ??? Should we also give an error for vectors rather than leaving
+     those to give errors later?  */
   expr = c_common_truthvalue_conversion (location, expr);
 
   if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
@@ -9749,19 +10655,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);
 }
@@ -9779,19 +10687,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);
 }
@@ -9837,7 +10747,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)))
@@ -9850,6 +10761,8 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
@@ -9871,8 +10784,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;
                }
            }
@@ -9887,7 +10801,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;
@@ -9896,14 +10811,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
@@ -9917,13 +10834,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
@@ -9937,13 +10856,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
@@ -9958,6 +10879,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -9987,6 +10910,10 @@ c_finish_omp_clauses (tree clauses)
                case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
                  break;
                case OMP_CLAUSE_DEFAULT_SHARED:
+                 /* const vars may be specified in firstprivate clause.  */
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                     && TREE_READONLY (t))
+                   break;
                  share_name = "shared";
                  break;
                case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -9997,8 +10924,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;
                }
            }
@@ -10014,6 +10942,19 @@ c_finish_omp_clauses (tree clauses)
   return clauses;
 }
 
+/* Create a transaction node.  */
+
+tree
+c_finish_transaction (location_t loc, tree block, int flags)
+{
+  tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
+  if (flags & TM_STMT_ATTR_OUTER)
+    TRANSACTION_EXPR_OUTER (stmt) = 1;
+  if (flags & TM_STMT_ATTR_RELAXED)
+    TRANSACTION_EXPR_RELAXED (stmt) = 1;
+  return add_stmt (stmt);
+}
+
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
 
@@ -10052,11 +10993,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
@@ -10082,10 +11023,10 @@ c_build_qualified_type (tree type, int type_quals)
 /* Build a VA_ARG_EXPR for the C parser.  */
 
 tree
-c_build_va_arg (tree expr, tree type, location_t loc)
+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 (expr, type);
+  return build_va_arg (loc, expr, type);
 }