OSDN Git Service

* builtins.c (expand_builtin_compare_and_swap): If target is const0,
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index abd7880..4a134b0 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,
 /* 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.
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -29,22 +29,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "rtl.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
-#include "tm_p.h"
 #include "flags.h"
 #include "output.h"
 #include "flags.h"
 #include "output.h"
-#include "expr.h"
-#include "toplev.h"
 #include "intl.h"
 #include "intl.h"
-#include "ggc.h"
 #include "target.h"
 #include "tree-iterator.h"
 #include "target.h"
 #include "tree-iterator.h"
+#include "bitmap.h"
 #include "gimple.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.  */
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -55,12 +51,13 @@ enum impl_conv {
   ic_return
 };
 
   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;
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
@@ -80,10 +77,12 @@ static int require_constant_elements;
 
 static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
 
 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 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 lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
@@ -97,19 +96,19 @@ static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (int, const char *);
 static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
 static char *print_spelling (char *);
 static void warning_init (int, const char *);
 static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool);
-static void output_pending_init_elements (int);
-static int set_designator (int);
-static void push_range_stack (tree);
-static void add_pending_init (tree, tree, tree, bool);
-static void set_nonincremental_init (void);
-static void set_nonincremental_init_from_string (tree);
-static tree find_init_member (tree);
-static void readonly_error (tree, enum lvalue_use);
+static void 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 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 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.  */
 
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -284,14 +283,55 @@ c_type_promotes_to (tree type)
   return 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)
 {
 /* 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,
   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.  */
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -371,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.  */
        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);
 
        t1_complete = COMPLETE_TYPE_P (t1);
        t2_complete = COMPLETE_TYPE_P (t2);
@@ -474,9 +515,6 @@ composite_type (tree t1, tree t2)
 
        /* If both args specify argument types, we must merge the two
           lists, argument by argument.  */
 
        /* 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;
 
        len = list_length (p1);
        newargs = 0;
@@ -514,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));
                    && 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
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
@@ -524,7 +562,7 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p2));
                      {
                        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;
                      }
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -539,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));
                    && 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
                  {
                    tree mv3 = TREE_TYPE (memb);
                    if (mv3 && mv3 != error_mark_node
@@ -549,7 +587,7 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p1));
                      {
                        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;
                      }
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -559,7 +597,6 @@ composite_type (tree t1, tree t2)
          parm_done: ;
          }
 
          parm_done: ;
          }
 
-       c_override_global_bindings_to_false = false;
        t1 = build_function_type (valtype, newargs);
        t1 = qualify_type (t1, t2);
        /* ... falls through ...  */
        t1 = build_function_type (valtype, newargs);
        t1 = qualify_type (t1, t2);
        /* ... falls through ...  */
@@ -585,6 +622,8 @@ common_pointer_type (tree t1, tree t2)
   tree pointed_to_2, mv2;
   tree target;
   unsigned target_quals;
   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.  */
 
 
   /* Save time if the two types are the same.  */
 
@@ -616,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.  */
   /* 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)
   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
   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);
 }
   t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
@@ -917,7 +970,7 @@ comptypes (tree type1, tree type2)
   const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
   int val;
 
   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;
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -932,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;
 
   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;
   free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
 
   return val;
@@ -943,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;
    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 C1X 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
 
 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;
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
@@ -959,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;
 
       || 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.  */
   /* 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.  */
@@ -977,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 (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));
     }
   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)
     }
 
   if (t1 == t2)
@@ -1009,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.  */
     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.  */
      return 0;
 
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1024,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),
        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:
       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:
       break;
 
     case ARRAY_TYPE:
@@ -1042,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),
        /* 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;
 
          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;
        /* Sizes must match unless one is missing or variable.  */
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
@@ -1061,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));
 
        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)
        if (d1_variable || d2_variable)
          break;
        if (d1_zero && d2_zero)
@@ -1086,15 +1168,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
            break;
 
          if (attrval != 2)
            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),
        }
       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:
       break;
 
     default:
@@ -1103,20 +1187,28 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
   return attrval == 2 && val == 1 ? 2 : val;
 }
 
   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;
 
 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;
 
   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.  */
   /* 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)
   if (TREE_CODE (mvl) != ARRAY_TYPE)
     mvl = TYPE_MAIN_VARIANT (mvl);
   if (TREE_CODE (mvr) != ARRAY_TYPE)
@@ -1218,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
    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,
 
 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;
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1326,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;
 
        /*  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),
          {
            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;
 
            if (result != 1 && !DECL_NAME (s1))
              break;
@@ -1359,17 +1452,18 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
            return tu->val;
          }
 
            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;
 
          {
            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),
              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;
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
@@ -1405,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;
 
        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),
          {
            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)
            if (result == 0)
              break;
            if (result == 2)
@@ -1441,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.
    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,
 
 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.  */
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1466,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);
   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 (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.  */
 
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
 
@@ -1485,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),
         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;
     }
        val = 2;
       return val;
     }
@@ -1495,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),
        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.  */
        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
   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,
 
 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;
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1536,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.  */
         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)
       if (a1 == 0)
        {
          if (c_type_promotes_to (a2) != a2)
@@ -1550,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 (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
          /* 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);
              && 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);
                {
                  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)
                    break;
                }
              if (memb == 0)
@@ -1577,20 +1684,21 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
            }
          else if (TREE_CODE (a2) == UNION_TYPE
                   && (TYPE_NAME (a2) == 0
            }
          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);
                   && 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);
                {
                  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)
                    break;
                }
              if (memb == 0)
@@ -1697,6 +1805,36 @@ function_to_pointer_conversion (location_t loc, tree exp)
   return build_unary_op (loc, 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.
 /* Perform the default conversion of arrays and functions to pointers.
    Return the result of converting EXP.  For any other expression, just
    return EXP.
@@ -1752,6 +1890,12 @@ default_function_array_conversion (location_t loc, struct c_expr exp)
   return 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.  */
 
 /* EXP is an expression of integer type.  Apply the integer promotions
    to it and return the promoted value.  */
@@ -1813,6 +1957,8 @@ default_conversion (tree exp)
   enum tree_code code = TREE_CODE (type);
   tree promoted_type;
 
   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)
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
   if (code == ARRAY_TYPE)
@@ -1849,7 +1995,7 @@ default_conversion (tree exp)
   return exp;
 }
 \f
   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
 
    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 +2005,8 @@ default_conversion (tree exp)
    unions, the list steps down the chain to the component.  */
 
 static tree
    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
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1891,10 +2036,21 @@ lookup_field (tree decl, tree component)
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                    {
                  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);
 
                      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 +2077,26 @@ lookup_field (tree decl, tree component)
     }
   else
     {
     }
   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))
            {
        {
          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);
 
              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)
            }
 
          if (DECL_NAME (field) == component)
@@ -1960,6 +2126,11 @@ build_component_ref (location_t loc, tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
   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)
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
@@ -1970,7 +2141,7 @@ build_component_ref (location_t loc, tree datum, tree component)
          return error_mark_node;
        }
 
          return error_mark_node;
        }
 
-      field = lookup_field (datum, component);
+      field = lookup_field (type, component);
 
       if (!field)
        {
 
       if (!field)
        {
@@ -2041,7 +2212,7 @@ build_component_ref (location_t loc, tree datum, tree component)
    LOC is the location to use for the generated tree.  */
 
 tree
    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);
 {
   tree pointer = default_conversion (ptr);
   tree type = TREE_TYPE (pointer);
@@ -2099,8 +2270,8 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
        }
     }
   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;
 }
 
   return error_mark_node;
 }
 
@@ -2113,6 +2284,9 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
    arrays that are not lvalues (for example, members of structures returned
    by functions).
 
    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
    LOC is the location to use for the returned expression.  */
 
 tree
@@ -2125,13 +2299,17 @@ build_array_ref (location_t loc, tree array, tree index)
     return error_mark_node;
 
   if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE
     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)
        {
     {
       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;
          return error_mark_node;
        }
       temp = array;
@@ -2162,6 +2340,27 @@ build_array_ref (location_t loc, tree array, tree index)
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
 
 
   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;
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
       tree rval, type;
@@ -2195,10 +2394,10 @@ build_array_ref (location_t loc, tree array, tree index)
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
          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))
                     "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");
        }
 
                     "ISO C90 forbids subscripting non-lvalue array");
        }
 
@@ -2235,7 +2434,7 @@ build_array_ref (location_t loc, tree array, tree index)
 
       return build_indirect_ref
        (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
 
       return build_indirect_ref
        (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
-        "array indexing");
+        RO_ARRAY_INDEXING);
     }
 }
 \f
     }
 }
 \f
@@ -2281,7 +2480,7 @@ build_external_ref (location_t loc, tree id, int fun, tree *type)
     warn_deprecated_use (ref, NULL_TREE);
 
   /* Recursive call does not count as usage.  */
     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;
     }
     {
       TREE_USED (ref) = 1;
     }
@@ -2500,7 +2699,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
   tree tem;
   int nargs;
   tree *argarray;
   tree tem;
   int nargs;
   tree *argarray;
-  
+
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -2517,7 +2716,14 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
        return tem;
 
       name = DECL_NAME (function);
        return tem;
 
       name = DECL_NAME (function);
+
+      if (flag_tm)
+       tm_malloc_replacement (function);
       fundecl = 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 (loc, function);
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
     function = function_to_pointer_conversion (loc, function);
@@ -2567,7 +2773,8 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
       && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
       && !comptypes (fntype, TREE_TYPE (tem)))
     {
       tree return_type = TREE_TYPE (fntype);
-      tree trap = build_function_call (loc, built_in_decls[BUILT_IN_TRAP],
+      tree trap = build_function_call (loc,
+                                      builtin_decl_explicit (BUILT_IN_TRAP),
                                       NULL_TREE);
       int i;
 
                                       NULL_TREE);
       int i;
 
@@ -2600,7 +2807,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                                          build_constructor (return_type, 0),
                                          false);
          else
                                          build_constructor (return_type, 0),
                                          false);
          else
-           rhs = fold_convert_loc (loc, return_type, integer_zero_node);
+           rhs = build_zero_cst (return_type);
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
@@ -2617,14 +2824,13 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
     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)
 
   if (name != NULL_TREE
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
     {
       if (require_constant_value)
-       result = 
+       result =
          fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
                                                 function, nargs, argarray);
       else
          fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
                                                 function, nargs, argarray);
       else
@@ -2647,6 +2853,98 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
     }
   return require_complete_type (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.
 \f
 /* Convert the argument expressions in the vector VALUES
    to the types in the list TYPELIST.
@@ -2673,6 +2971,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 {
   tree typetail, val;
   unsigned int parmnum;
 {
   tree typetail, val;
   unsigned int parmnum;
+  bool error_args = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
@@ -2729,7 +3028,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
       if (type == void_type_node)
        {
 
       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;
        }
 
          return parmnum;
        }
 
@@ -2924,8 +3231,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
          if (type_generic)
            parmval = val;
          else
          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
        }
       else if (excess_precision && !type_generic)
        /* A "double" argument with excess precision being passed
@@ -2942,6 +3256,8 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
        parmval = default_conversion (val);
 
       VEC_replace (tree, values, parmnum, parmval);
        parmval = default_conversion (val);
 
       VEC_replace (tree, values, parmnum, parmval);
+      if (parmval == error_mark_node)
+       error_args = true;
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
@@ -2951,11 +3267,14 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
 
   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 -1;
     }
 
-  return parmnum;
+  return error_args ? -1 : (int) parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
 }
 \f
 /* This is the entry point used by the parser to build unary operators
@@ -3038,8 +3357,8 @@ parser_build_binary_op (location_t location, enum tree_code code,
     warning_at (location, 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 (location, result.value);
 
       && !TREE_OVERFLOW_P (arg2.value))
     overflow_warning (location, result.value);
 
@@ -3063,16 +3382,48 @@ static tree
 pointer_diff (location_t loc, tree op0, tree op1)
 {
   tree restype = ptrdiff_type_node;
 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;
 
   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)
   if (TREE_CODE (target_type) == VOID_TYPE)
-    pedwarn (loc, 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)
             "pointer of type %<void *%> used in subtraction");
   if (TREE_CODE (target_type) == FUNCTION_TYPE)
-    pedwarn (loc, 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
             "pointer to a function used in subtraction");
 
   /* If the conversion to ptrdiff_type does anything like widening or
@@ -3125,8 +3476,8 @@ pointer_diff (location_t loc, tree op0, tree op1)
      in case restype is a short type.  */
 
   op0 = build_binary_op (loc,
      in case restype is a short type.  */
 
   op0 = build_binary_op (loc,
-                        MINUS_EXPR, convert (restype, op0),
-                        convert (restype, op1), 0);
+                        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_at (loc, "arithmetic on pointer to an incomplete type");
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
     error_at (loc, "arithmetic on pointer to an incomplete type");
@@ -3135,8 +3486,11 @@ pointer_diff (location_t loc, tree op0, tree op1)
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-  return fold_build2_loc (loc, 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
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3233,7 +3587,7 @@ build_unary_op (location_t location,
       else if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
       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);
                   "ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
@@ -3284,26 +3638,10 @@ build_unary_op (location_t location,
       goto return_build_unary_op;
 
     case REALPART_EXPR:
       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_loc (location,
-                              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:
     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_loc (location,
-                              IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
-      else
-       ret = omit_one_operand_loc (location, 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;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3326,11 +3664,14 @@ build_unary_op (location_t location,
          goto return_build_unary_op;
        }
 
          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)
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@@ -3352,7 +3693,7 @@ build_unary_op (location_t location,
        {
          tree real, imag;
 
        {
          tree real, imag;
 
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
                   "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
@@ -3403,15 +3744,15 @@ build_unary_op (location_t location,
                     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
                     || 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
                           "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));
                           "wrong type argument to decrement");
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = fold_convert_loc (location, sizetype, inc);
+           inc = convert_to_ptrofftype_loc (location, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3438,6 +3779,13 @@ build_unary_op (location_t location,
            inc = convert (argtype, inc);
          }
 
            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))
          {
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
@@ -3492,18 +3840,12 @@ build_unary_op (location_t location,
          tree op0 = TREE_OPERAND (arg, 0);
          if (!c_mark_addressable (op0))
            return error_mark_node;
          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 (location,
-                                                                 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
        }
 
       /* 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
        return error_mark_node;
 
       /* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@@ -3524,14 +3866,22 @@ build_unary_op (location_t location,
       argtype = TREE_TYPE (arg);
 
       /* If the lvalue is const or volatile, merge that into the type
       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))
       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;
 
       if (!c_mark_addressable (arg))
        return error_mark_node;
@@ -3547,11 +3897,7 @@ build_unary_op (location_t location,
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert_loc (location, sizetype,
-                                      fold_offsetof (arg, val)), op1;
-
-         op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0);
+         ret = fold_convert_loc (location, argtype, fold_offsetof_1 (arg));
          goto return_build_unary_op;
        }
 
          goto return_build_unary_op;
        }
 
@@ -3625,44 +3971,6 @@ lvalue_p (const_tree ref)
     }
 }
 \f
     }
 }
 \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.  */
 
 /* Give a warning for storing in something that is read-only in GCC
    terms but not const in ISO C terms.  */
 
@@ -3689,15 +3997,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
 
 /* 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
 
 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)
 {
   int win = lvalue_p (ref);
 
   if (!win)
-    lvalue_error (use);
+    lvalue_error (loc, use);
 
   return win;
 }
 
   return win;
 }
@@ -3769,6 +4078,34 @@ c_mark_addressable (tree exp)
     }
 }
 \f
     }
 }
 \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
 /* 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
@@ -3785,12 +4122,11 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
   enum tree_code code1;
   enum tree_code code2;
   tree result_type = NULL;
   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;
   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)
 
   op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
   if (op1_int_operands)
@@ -3827,8 +4163,6 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       return error_mark_node;
     }
 
       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
   if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
        || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
       && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -3836,7 +4170,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
          || code2 == COMPLEX_TYPE))
     {
       && (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);
       if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
        {
          op1 = TREE_OPERAND (op1, 0);
@@ -3880,6 +4214,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
               || code2 == COMPLEX_TYPE))
     {
       result_type = c_common_type (type1, type2);
               || 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
 
       /* If -Wsign-compare, warn here if type1 and type2 have
         different signedness.  We'll promote the signed to unsigned
@@ -3940,17 +4278,9 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                                     "conditional expression"));
                    }
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
                                     "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)
                  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);
                }
            }
        }
                }
            }
        }
@@ -3964,12 +4294,22 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
     }
   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))
       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))
       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)
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
@@ -3988,12 +4328,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)));
        }
          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
        {
       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)
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
@@ -4033,13 +4378,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,
   /* 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)
     {
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
     {
@@ -4071,8 +4414,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       if (int_operands)
        ret = note_integer_operands (ret);
     }
       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;
 
   protected_set_expr_location (ret, colon_loc);
   return ret;
@@ -4120,7 +4463,7 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
                   && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
                   && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
-           warning_at (loc, OPT_Wunused_value, 
+           warning_at (loc, OPT_Wunused_value,
                        "left-hand operand of comma expression has no effect");
        }
     }
                        "left-hand operand of comma expression has no effect");
        }
     }
@@ -4151,11 +4494,13 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
 
 /* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
    which we are casting.  OTYPE is the type of the expression being
 
 /* 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
 
 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;
 {
   tree in_type = type;
   tree in_otype = otype;
@@ -4178,21 +4523,25 @@ handle_warn_cast_qual (tree type, tree otype)
         taken away.  */
       if (TREE_CODE (in_otype) == FUNCTION_TYPE
          && TREE_CODE (in_type) == FUNCTION_TYPE)
         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
       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)
     }
   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.  */
 
   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;
 
   if (added || discarded)
     return;
@@ -4225,9 +4574,10 @@ handle_warn_cast_qual (tree type, tree otype)
       if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
          && !is_const)
        {
       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)
          break;
        }
       if (is_const)
@@ -4236,7 +4586,7 @@ handle_warn_cast_qual (tree type, tree otype)
   while (TREE_CODE (in_type) == POINTER_TYPE);
 }
 
   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
    LOC is the location of the cast-- typically the open paren of the cast.  */
 
 tree
@@ -4283,14 +4633,14 @@ build_c_cast (location_t loc, tree type, tree expr)
     {
       if (TREE_CODE (type) == RECORD_TYPE
          || TREE_CODE (type) == UNION_TYPE)
     {
       if (TREE_CODE (type) == RECORD_TYPE
          || TREE_CODE (type) == UNION_TYPE)
-       pedwarn (loc, OPT_pedantic, 
+       pedwarn (loc, OPT_pedantic,
                 "ISO C forbids casting nonscalar to the same type");
     }
   else if (TREE_CODE (type) == UNION_TYPE)
     {
       tree field;
 
                 "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))))
        if (TREE_TYPE (field) != error_mark_node
            && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
                          TYPE_MAIN_VARIANT (TREE_TYPE (value))))
@@ -4299,10 +4649,14 @@ build_c_cast (location_t loc, tree type, tree expr)
       if (field)
        {
          tree t;
       if (field)
        {
          tree t;
+         bool maybe_const = true;
 
          pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type");
 
          pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type");
-         t = digest_init (loc, type,
-                          build_constructor_single (type, field, value),
+         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;
                           NULL_TREE, false, true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          return t;
@@ -4327,7 +4681,37 @@ build_c_cast (location_t loc, tree type, tree expr)
       if (warn_cast_qual
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
       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
 
       /* Warn about possible alignment problems.  */
       if (STRICT_ALIGNMENT
@@ -4469,8 +4853,9 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
   if (CAN_HAVE_LOCATION_P (ret) && !EXPR_HAS_LOCATION (ret))
     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++");
 
     warning_at (loc, OPT_Wc___compat,
                "defining a type in a cast is invalid in C++");
 
@@ -4491,7 +4876,7 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
 
 tree
 build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
 
 tree
 build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
-                  enum tree_code modifycode, 
+                  enum tree_code modifycode,
                   location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
                   location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
@@ -4508,7 +4893,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 (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)
     return error_mark_node;
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
@@ -4549,6 +4935,19 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       rhs_origtype = NULL_TREE;
     }
 
       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)
   /* Give an error for storing in something that is 'const'.  */
 
   if (TYPE_READONLY (lhstype)
@@ -4644,6 +5043,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   return result;
 }
 \f
   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
 /* 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
@@ -4709,7 +5208,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         pedwarn (LOCATION, OPT, AS);                                     \
         break;                                                           \
       case ic_init:                                                      \
         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);                                    \
         break;                                                           \
       case ic_return:                                                    \
         pedwarn (LOCATION, OPT, RE);                                    \
@@ -4719,6 +5218,36 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       }                                                                  \
   } while (0)
 
       }                                                                  \
   } while (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);
 
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
@@ -4836,10 +5365,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       tree ret;
       bool save = in_late_binary_op;
     {
       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);
        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;
     }
        in_late_binary_op = save;
       return ret;
     }
@@ -4850,14 +5379,15 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       && comptypes (type, rhstype))
     return convert_and_check (type, 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.  */
      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;
 
       && 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);
 
        {
          tree memb_type = TREE_TYPE (memb);
 
@@ -4923,36 +5453,40 @@ 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.  */
                     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 (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 "
                                         G_("passing argument %d of %qE "
-                                           "makes qualified function "
+                                           "makes %q#v qualified function "
                                            "pointer from unqualified"),
                                            "pointer from unqualified"),
-                                        G_("assignment makes qualified "
+                                        G_("assignment makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("initialization makes qualified "
+                                        G_("initialization makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
                                            "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 (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 "
                                     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"),
                                        "from pointer target type"),
-                                    G_("initialization discards qualifiers "
+                                    G_("initialization discards %qv qualifier "
                                        "from pointer target type"),
                                        "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))
 
              memb = marginal_memb;
            }
 
          if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
-           pedwarn (location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ISO C prohibits argument conversion to union type");
 
          rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
                     "ISO C prohibits argument conversion to union type");
 
          rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
@@ -4970,6 +5504,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.  */
       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);
 
       if (TREE_CODE (mvl) != ARRAY_TYPE)
        mvl = TYPE_MAIN_VARIANT (mvl);
@@ -4978,6 +5514,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);
 
       /* 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
       /* 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
@@ -4990,6 +5545,36 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                    "request for implicit conversion "
                    "from %qT to %qT not permitted in C++", rhstype, type);
 
                    "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.  */
       if (warn_missing_format_attribute
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
       if (warn_missing_format_attribute
@@ -5053,21 +5638,19 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
          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 (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.  */
                }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
@@ -5093,17 +5676,19 @@ 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.  */
                 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 (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 "
                                     G_("passing argument %d of %qE makes "
-                                       "qualified function pointer "
+                                       "%q#v qualified function pointer "
                                        "from unqualified"),
                                        "from unqualified"),
-                                    G_("assignment makes qualified function "
+                                    G_("assignment makes %q#v qualified function "
                                        "pointer from unqualified"),
                                        "pointer from unqualified"),
-                                    G_("initialization makes qualified "
+                                    G_("initialization makes %q#v qualified "
                                        "function pointer from unqualified"),
                                        "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
            }
        }
       else
@@ -5257,7 +5842,7 @@ store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
   STRIP_TYPE_NOPS (value);
 
   /* 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.  */
     constant_expression_warning (value);
 
   /* Check if we need to set array size from compound literal size.  */
@@ -5279,11 +5864,13 @@ store_init_value (location_t init_loc, 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.  */
              /* 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));
              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);
              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));
            }
        }
     }
            }
        }
     }
@@ -5412,15 +5999,16 @@ print_spelling (char *buffer)
 }
 
 /* Issue an error message for a bad initializer component.
 }
 
 /* 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
    The component name is taken from the spelling stack.  */
 
 void
-error_init (const char *msgid)
+error_init (const char *gmsgid)
 {
   char *ofwhat;
 
 {
   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);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for %qs)", ofwhat);
@@ -5428,32 +6016,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
 
 /* 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
    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;
 
 {
   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);
 }
 
   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
 
    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
    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;
 
 {
   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);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning (opt, "(near initialization for %qs)", ofwhat);
@@ -5470,7 +6060,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)
       && 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");
 }
 
                  "array initialized from parenthesized string constant");
 }
 
@@ -6105,7 +6695,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)
       /* 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;
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6120,14 +6710,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))
          /* 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 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,
 
          constructor_index
            = convert (bitsizetype,
@@ -6145,7 +6735,7 @@ really_start_incremental_init (tree type)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
     {
       /* 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;
     }
       constructor_index = bitsize_zero_node;
       constructor_unfilled_index = constructor_index;
     }
@@ -6163,7 +6753,7 @@ really_start_incremental_init (tree type)
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
    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;
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -6181,12 +6771,14 @@ push_init_level (int implicit)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
          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))
          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;
        }
          else
            break;
        }
@@ -6199,9 +6791,9 @@ push_init_level (int implicit)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields)
       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)
       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);
     }
 
   p = XNEW (struct constructor_stack);
@@ -6287,7 +6879,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))
       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)
     }
 
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
@@ -6303,7 +6895,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)
       /* 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;
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6312,8 +6904,8 @@ push_init_level (int implicit)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
     {
       /* 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)
       constructor_unfilled_index = constructor_index;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -6326,14 +6918,14 @@ push_init_level (int implicit)
          /* Detect non-empty initializations of zero-length arrays.  */
          if (constructor_max_index == NULL_TREE
              && TYPE_SIZE (constructor_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 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,
 
          constructor_index
            = convert (bitsizetype,
@@ -6348,7 +6940,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.  */
          /* 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
        }
     }
   else
@@ -6372,7 +6964,7 @@ push_init_level (int implicit)
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
    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;
 {
   struct constructor_stack *p;
   struct c_expr ret;
@@ -6385,14 +6977,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)
       /* 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;
       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;
 
 
   p = constructor_stack;
 
@@ -6420,7 +7014,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.  */
          /* 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;
        }
     }
            constructor_type = NULL_TREE;
        }
     }
@@ -6431,15 +7025,23 @@ pop_init_level (int implicit)
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
     {
       && 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))))
        /* 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,
          {
            push_member_name (constructor_unfilled_fields);
            warning_init (OPT_Wmissing_field_initializers,
@@ -6533,7 +7135,7 @@ pop_init_level (int implicit)
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
    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;
 {
   tree subtype;
   enum tree_code subcode;
@@ -6555,7 +7157,10 @@ set_designator (int array)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
       /* 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;
     }
       constructor_designated = 1;
       return 0;
     }
@@ -6588,7 +7193,7 @@ set_designator (int array)
     }
 
   constructor_designated = 1;
     }
 
   constructor_designated = 1;
-  push_init_level (2);
+  push_init_level (2, braced_init_obstack);
   return 0;
 }
 
   return 0;
 }
 
@@ -6597,11 +7202,13 @@ set_designator (int array)
    NULL_TREE if there is no range designator at this level.  */
 
 static void
    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;
 
 {
   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;
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
@@ -6619,9 +7226,10 @@ push_range_stack (tree range_end)
    of indices, running from FIRST through LAST.  */
 
 void
    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;
     return;
 
   designator_erroneous = 1;
@@ -6693,18 +7301,18 @@ set_init_index (tree first, tree last)
       designator_depth++;
       designator_erroneous = 0;
       if (constructor_range_stack || 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
     }
 }
 
 /* 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;
     return;
 
   designator_erroneous = 1;
@@ -6716,23 +7324,26 @@ set_init_label (tree fieldname)
       return;
     }
 
       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
     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
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
@@ -6746,7 +7357,8 @@ set_init_label (tree fieldname)
    existing initializer.  */
 
 static void
    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;
 
 {
   struct init_node *p, **q, *r;
 
@@ -6805,7 +7417,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;
   r->purpose = purpose;
   r->value = value;
   r->origtype = origtype;
@@ -6974,7 +7587,7 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
 /* Build AVL tree from a sorted chain.  */
 
 static void
 /* 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;
 {
   unsigned HOST_WIDE_INT ix;
   tree index, value;
@@ -6984,7 +7597,10 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
     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, false,
+                       braced_init_obstack);
+    }
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -7011,7 +7627,8 @@ set_nonincremental_init (void)
 /* Build AVL tree from a string constant.  */
 
 static 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];
 {
   tree value, purpose, type;
   HOST_WIDE_INT val[2];
@@ -7074,7 +7691,8 @@ set_nonincremental_init_from_string (tree str)
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
        }
 
       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, false,
+                        braced_init_obstack);
     }
 
   constructor_incremental = 0;
     }
 
   constructor_incremental = 0;
@@ -7084,7 +7702,7 @@ set_nonincremental_init_from_string (tree str)
    not initialized yet.  */
 
 static tree
    not initialized yet.  */
 
 static tree
-find_init_member (tree field)
+find_init_member (tree field, struct obstack * braced_init_obstack)
 {
   struct init_node *p;
 
 {
   struct init_node *p;
 
@@ -7092,7 +7710,7 @@ find_init_member (tree field)
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
     {
       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)
 
       p = constructor_pending_elts;
       while (p)
@@ -7113,7 +7731,7 @@ find_init_member (tree field)
          && (!constructor_unfilled_fields
              || tree_int_cst_lt (bitpos,
                                  bit_position (constructor_unfilled_fields))))
          && (!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)
 
       p = constructor_pending_elts;
       while (p)
@@ -7157,7 +7775,8 @@ find_init_member (tree field)
 
 static void
 output_init_element (tree value, tree origtype, bool strict_string, tree type,
 
 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;
 {
   tree semantic_type = NULL_TREE;
   constructor_elt *celt;
@@ -7251,7 +7870,7 @@ 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
          || (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)
     return;
 
   if (semantic_type)
@@ -7274,9 +7893,10 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
     {
       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
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -7289,7 +7909,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
       if (constructor_incremental)
        {
          if (!constructor_unfilled_fields)
       if (constructor_incremental)
        {
          if (!constructor_unfilled_fields)
-           set_nonincremental_init ();
+           set_nonincremental_init (braced_init_obstack);
          else
            {
              tree bitpos, unfillpos;
          else
            {
              tree bitpos, unfillpos;
@@ -7298,11 +7918,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))
              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
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
@@ -7337,21 +7958,21 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
   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 =
 
       /* 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)
     }
   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.
 }
 
 /* Output any pending elements which have become next.
@@ -7364,9 +7985,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.  */
 
    If ALL is 1, we output space as necessary so that
    we can output all the pending elements.  */
-
 static void
 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;
 {
   struct init_node *elt = constructor_pending_elts;
   tree next;
@@ -7387,7 +8007,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))
            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))
            {
          else if (tree_int_cst_lt (constructor_unfilled_index,
                                    elt->purpose))
            {
@@ -7441,7 +8062,8 @@ output_pending_init_elements (int all)
              constructor_unfilled_fields = elt->purpose;
              output_init_element (elt->value, elt->origtype, true,
                                   TREE_TYPE (elt->purpose),
              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))
            {
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
@@ -7512,7 +8134,8 @@ output_pending_init_elements (int all)
    existing initializer.  */
 
 void
    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;
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
@@ -7553,13 +8176,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)
       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)))
       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;
     }
       else
        break;
     }
@@ -7609,7 +8234,7 @@ process_init_element (struct c_expr value, bool implicit)
          if (fieldcode == ARRAY_TYPE
              && !require_constant_value
              && TYPE_SIZE (fieldtype) == NULL_TREE
          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;
            {
              error_init ("non-static initialization of a flexible array member");
              break;
@@ -7629,7 +8254,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
              continue;
            }
 
@@ -7638,7 +8263,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,
              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
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7656,22 +8282,22 @@ process_init_element (struct c_expr value, bool implicit)
                 it isn't now, so update.  */
              if (constructor_unfilled_fields == constructor_fields)
                {
                 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 =
                  /* 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)
          /* 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)
        {
        }
       else if (TREE_CODE (constructor_type) == UNION_TYPE)
        {
@@ -7720,7 +8346,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
              continue;
            }
 
@@ -7729,7 +8355,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,
              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
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7737,7 +8364,7 @@ process_init_element (struct c_expr value, bool implicit)
               directly output as a constructor.  */
            {
              constructor_bit_index = DECL_SIZE (constructor_fields);
               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;
            }
 
          constructor_fields = 0;
@@ -7761,7 +8388,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
              continue;
            }
 
@@ -7780,7 +8407,8 @@ 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,
              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);
            }
 
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
@@ -7814,7 +8442,8 @@ 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,
                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
            }
 
          constructor_index
@@ -7842,7 +8471,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,
          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;
        }
 
          constructor_fields = 0;
        }
 
@@ -7858,14 +8488,17 @@ process_init_element (struct c_expr value, bool implicit)
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->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);
            }
          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_loc (input_location,
            }
 
          p->index = size_binop_loc (input_location,
@@ -7885,7 +8518,7 @@ process_init_element (struct c_expr value, bool implicit)
              p = p->next;
              if (!p)
                break;
              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;
              p->stack = constructor_stack;
              if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
                p->index = p->range_start;
@@ -7920,7 +8553,7 @@ build_asm_stmt (tree cv_qualifier, tree args)
    are subtly different.  We use a ASM_EXPR node to represent this.  */
 tree
 build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
    are subtly different.  We use a ASM_EXPR node to represent this.  */
 tree
 build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
-               tree clobbers, bool simple)
+               tree clobbers, tree labels, bool simple)
 {
   tree tail;
   tree args;
 {
   tree tail;
   tree args;
@@ -7934,7 +8567,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
   noutputs = list_length (outputs);
   oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
 
   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))
 
   /* Remove output conversions that change the type but not the mode.  */
   for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
@@ -7949,7 +8582,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
         get an error.  Gross, but ...  */
       STRIP_NOPS (output);
 
         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
        output = error_mark_node;
 
       if (output != error_mark_node
@@ -7970,6 +8603,13 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
             mark it addressable.  */
          if (!allows_reg && !c_mark_addressable (output))
            output = error_mark_node;
             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;
        }
       else
        output = error_mark_node;
@@ -7996,7 +8636,12 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
              STRIP_NOPS (input);
              if (!c_mark_addressable (input))
                input = error_mark_node;
              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;
        }
       else
        input = error_mark_node;
@@ -8004,7 +8649,11 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
       TREE_VALUE (tail) = input;
     }
 
       TREE_VALUE (tail) = input;
     }
 
-  args = build_stmt (loc, 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.  */
 
   /* asm statements without outputs, including simple ones, are treated
      as volatile.  */
@@ -8082,7 +8731,7 @@ c_finish_return (location_t loc, tree retval, tree origtype)
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
        {
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
        {
-         pedwarn_c99 (loc, 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;
                       "%<return%> with no value, in "
                       "function returning non-void");
          no_warning = true;
@@ -8092,9 +8741,9 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn (loc, 0, 
+       pedwarn (loc, 0,
                 "%<return%> with a value, in function returning void");
                 "%<return%> with a value, in function returning void");
-      else 
+      else
        pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
        pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
@@ -8532,6 +9181,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
 tree
 c_process_expr_stmt (location_t loc, tree expr)
 {
 tree
 c_process_expr_stmt (location_t loc, tree expr)
 {
+  tree exprv;
+
   if (!expr)
     return NULL_TREE;
 
   if (!expr)
     return NULL_TREE;
 
@@ -8552,6 +9203,16 @@ c_process_expr_stmt (location_t loc, tree expr)
       && warn_unused_value)
     emit_side_effect_warnings (loc, expr);
 
       && warn_unused_value)
     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))
   /* 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))
@@ -8657,16 +9318,17 @@ c_finish_stmt_expr (location_t loc, tree body)
       goto continue_searching;
     }
 
       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.  */
   /* 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.  */
     {
       /* 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;
       /* Do not warn if the return value of a statement expression is
         unused.  */
       TREE_NO_WARNING (last) = 1;
@@ -8739,7 +9401,7 @@ c_end_compound_stmt (location_t loc, tree stmt, bool do_scope)
      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.  */
      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)
     {
       && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
       && TREE_CODE (stmt) != BIND_EXPR)
     {
@@ -8770,6 +9432,88 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
   TREE_OPERAND (stmt, 0) = list;
   STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
 }
   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.
 \f
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
@@ -8811,7 +9555,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.  */
 
   /* 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.
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
@@ -8853,6 +9597,10 @@ build_binary_op (location_t location, enum tree_code code,
      precision.  */
   bool may_need_excess_precision;
 
      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;
 
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
@@ -8877,7 +9625,10 @@ build_binary_op (location_t location, enum tree_code code,
   else
     int_const = int_const_or_overflow = false;
 
   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);
     {
       op0 = default_conversion (op0);
       op1 = default_conversion (op1);
@@ -8949,6 +9700,51 @@ build_binary_op (location_t location, enum tree_code code,
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
 
   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)
+               op0 = 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:
   switch (code)
     {
     case PLUS_EXPR:
@@ -9080,6 +9876,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;
          op0 = c_common_truthvalue_conversion (location, op0);
          op1 = c_common_truthvalue_conversion (location, op1);
          converted = 1;
+         boolean_op = true;
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
@@ -9110,7 +9907,21 @@ build_binary_op (location_t location, enum tree_code code,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
         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)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9137,9 +9948,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
 
          /* 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;
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9147,7 +9959,21 @@ build_binary_op (location_t location, enum tree_code code,
       break;
 
     case LSHIFT_EXPR:
       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)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9169,9 +9995,10 @@ build_binary_op (location_t location, enum tree_code code,
 
          /* Use the type of the value to be shifted.  */
          result_type = type0;
 
          /* 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;
            op1 = convert (integer_type_node, op1);
          /* Avoid converting op1 to result_type later.  */
          converted = 1;
@@ -9180,6 +10007,31 @@ build_binary_op (location_t location, enum tree_code code,
 
     case EQ_EXPR:
     case NE_EXPR:
 
     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,
       if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
        warning_at (location,
                    OPT_Wfloat_equal,
@@ -9192,28 +10044,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;
          && (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);
       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);
          /* 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))
            {
          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))
            {
                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");
            }
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
@@ -9224,25 +10122,11 @@ build_binary_op (location_t location, enum tree_code code,
                       "comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
                       "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)
        {
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -9260,6 +10144,31 @@ build_binary_op (location_t location, enum tree_code code,
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
     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)
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == FIXED_POINT_TYPE)
@@ -9268,6 +10177,10 @@ build_binary_op (location_t location, enum tree_code code,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
        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);
          if (comp_target_types (location, type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
@@ -9278,10 +10191,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 (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
            {
            }
          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");
            }
              pedwarn (location, 0,
                       "comparison of distinct pointer types lacks a cast");
            }
@@ -9290,17 +10216,21 @@ build_binary_op (location_t location, enum tree_code code,
        {
          result_type = type0;
          if (pedantic)
        {
          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");
          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;
        }
       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)
        {
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -9343,6 +10273,11 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten || common || short_compare)
        {
          result_type = c_common_type (type0, type1);
       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;
        }
          if (result_type == error_mark_node)
            return error_mark_node;
        }
@@ -9364,7 +10299,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);
          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)
            {
            }
          if (first_complex)
            {
@@ -9393,6 +10328,7 @@ build_binary_op (location_t location, enum tree_code code,
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = c_save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -9413,6 +10349,7 @@ build_binary_op (location_t location, enum tree_code code,
              switch (code)
                {
                case MULT_EXPR:
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = c_save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -9444,7 +10381,7 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten && none_complex)
        {
          final_type = result_type;
       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);
        }
 
                                           shorten == -1);
        }
 
@@ -9461,6 +10398,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)
            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
              /* 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
@@ -9537,20 +10475,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);
                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)
                {
                  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)
                  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);
                }
            }
        }
                }
            }
        }
@@ -9568,12 +10498,21 @@ build_binary_op (location_t location, enum tree_code code,
       return error_mark_node;
     }
 
       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 (!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.  */
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
@@ -9581,16 +10520,6 @@ build_binary_op (location_t location, enum tree_code code,
        return error_mark_node;
     }
 
        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
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
@@ -9611,8 +10540,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);
   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;
 }
   protected_set_expr_location (ret, location);
   return ret;
 }
@@ -9640,9 +10569,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;
 
       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 FUNCTION_TYPE:
       gcc_unreachable ();
 
+    case VECTOR_TYPE:
+      error_at (location, "used vector type where scalar is required");
+      return error_mark_node;
+
     default:
       break;
     }
     default:
       break;
     }
@@ -9652,8 +10589,8 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
   if (int_operands)
     expr = remove_c_maybe_const_expr (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)
   expr = c_common_truthvalue_conversion (location, expr);
 
   if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
@@ -9807,6 +10744,8 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
@@ -9923,6 +10862,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
        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;
 
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -9952,6 +10893,10 @@ c_finish_omp_clauses (tree clauses)
                case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
                  break;
                case OMP_CLAUSE_DEFAULT_SHARED:
                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:
                  share_name = "shared";
                  break;
                case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -9980,6 +10925,19 @@ c_finish_omp_clauses (tree clauses)
   return 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.  */
 
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
 
@@ -10018,11 +10976,11 @@ c_build_qualified_type (tree type, int type_quals)
           else if (TYPE_CANONICAL (element_type) != element_type
                    || (domain && TYPE_CANONICAL (domain) != domain))
             {
           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),
                 = build_array_type (TYPE_CANONICAL (element_type),
-                                    domain? TYPE_CANONICAL (domain) 
+                                    domain? TYPE_CANONICAL (domain)
                                           : NULL_TREE);
                                           : NULL_TREE);
-              TYPE_CANONICAL (t) 
+              TYPE_CANONICAL (t)
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
           else
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
           else