OSDN Git Service

2012-02-01 Tristan Gingold <gingold@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index e7425a7..2de1e5c 100644 (file)
@@ -1,6 +1,6 @@
 /* Build expressions with type checking for C compiler.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -29,22 +29,18 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "rtl.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
-#include "tm_p.h"
 #include "flags.h"
 #include "output.h"
-#include "expr.h"
-#include "toplev.h"
 #include "intl.h"
-#include "ggc.h"
 #include "target.h"
 #include "tree-iterator.h"
+#include "bitmap.h"
 #include "gimple.h"
-#include "tree-flow.h"
+#include "c-family/c-objc.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -55,12 +51,13 @@ enum impl_conv {
   ic_return
 };
 
-/* Whether we are building a boolean conversion inside
-   convert_for_assignment, or some other late binary operation.  If
-   build_binary_op is called (from code shared with C++) in this case,
-   then the operands have already been folded and the result will not
-   be folded again, so C_MAYBE_CONST_EXPR should not be generated.  */
-bool in_late_binary_op;
+/* Possibe cases of scalar_to_vector conversion.  */
+enum stv_conv {
+  stv_error,        /* Error occured.  */
+  stv_nothing,      /* Nothing happened.  */
+  stv_firstarg,     /* First argument must be expanded.  */
+  stv_secondarg     /* Second argument must be expanded.  */
+};
 
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
@@ -80,10 +77,12 @@ static int require_constant_elements;
 
 static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *);
+static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
+                                        bool *);
 static int comp_target_types (location_t, tree, tree);
-static int function_types_compatible_p (const_tree, const_tree, bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *);
+static int function_types_compatible_p (const_tree, const_tree, bool *,
+                                       bool *);
+static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
@@ -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 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 int lvalue_or_else (const_tree, enum lvalue_use);
+static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *);
+static int comptypes_internal (const_tree, const_tree, bool *, bool *);
 \f
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -284,14 +283,55 @@ c_type_promotes_to (tree type)
   return type;
 }
 
+/* Return true if between two named address spaces, whether there is a superset
+   named address space that encompasses both address spaces.  If there is a
+   superset, return which address space is the superset.  */
+
+static bool
+addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
+{
+  if (as1 == as2)
+    {
+      *common = as1;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as1, as2))
+    {
+      *common = as2;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as2, as1))
+    {
+      *common = as1;
+      return true;
+    }
+  else
+    return false;
+}
+
 /* Return a variant of TYPE which has all the type qualifiers of LIKE
    as well as those of TYPE.  */
 
 static tree
 qualify_type (tree type, tree like)
 {
+  addr_space_t as_type = TYPE_ADDR_SPACE (type);
+  addr_space_t as_like = TYPE_ADDR_SPACE (like);
+  addr_space_t as_common;
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  If there isn't one, raise an error.  */
+  if (!addr_space_superset (as_type, as_like, &as_common))
+    {
+      as_common = as_type;
+      error ("%qT and %qT are in disjoint named address spaces",
+            type, like);
+    }
+
   return c_build_qualified_type (type,
-                                TYPE_QUALS (type) | TYPE_QUALS (like));
+                                TYPE_QUALS_NO_ADDR_SPACE (type)
+                                | TYPE_QUALS_NO_ADDR_SPACE (like)
+                                | ENCODE_QUAL_ADDR_SPACE (as_common));
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -354,7 +394,7 @@ composite_type (tree t1, tree t2)
        tree pointed_to_1 = TREE_TYPE (t1);
        tree pointed_to_2 = TREE_TYPE (t2);
        tree target = composite_type (pointed_to_1, pointed_to_2);
-       t1 = build_pointer_type (target);
+        t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
        t1 = build_type_attribute_variant (t1, attributes);
        return qualify_type (t1, t2);
       }
@@ -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.  */
-       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);
@@ -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.  */
-       /* 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;
@@ -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));
-                    memb; memb = TREE_CHAIN (memb))
+                    memb; memb = DECL_CHAIN (memb))
                  {
                    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));
-                       pedwarn (input_location, OPT_pedantic, 
+                       pedwarn (input_location, OPT_pedantic,
                                 "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));
-                    memb; memb = TREE_CHAIN (memb))
+                    memb; memb = DECL_CHAIN (memb))
                  {
                    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));
-                       pedwarn (input_location, OPT_pedantic, 
+                       pedwarn (input_location, OPT_pedantic,
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -559,7 +597,6 @@ composite_type (tree t1, tree t2)
          parm_done: ;
          }
 
-       c_override_global_bindings_to_false = false;
        t1 = build_function_type (valtype, newargs);
        t1 = qualify_type (t1, t2);
        /* ... falls through ...  */
@@ -585,6 +622,8 @@ common_pointer_type (tree t1, tree t2)
   tree pointed_to_2, mv2;
   tree target;
   unsigned target_quals;
+  addr_space_t as1, as2, as_common;
+  int quals1, quals2;
 
   /* Save time if the two types are the same.  */
 
@@ -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.  */
+  quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
+  quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
+
   if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
-    target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+    target_quals = (quals1 & quals2);
   else
-    target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+    target_quals = (quals1 | quals2);
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  This is guaranteed to exist due to the
+     assumption that comp_target_type returned non-zero.  */
+  as1 = TYPE_ADDR_SPACE (pointed_to_1);
+  as2 = TYPE_ADDR_SPACE (pointed_to_2);
+  if (!addr_space_superset (as1, as2, &as_common))
+    gcc_unreachable ();
+
+  target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
+
   t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
@@ -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;
 
-  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;
@@ -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;
 
-  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;
@@ -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;
-   *ENUM_AND_INT_P is never set to false.  This differs from
-   comptypes, in that we don't free the seen types.  */
+   *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
+   NULL, and the types are compatible but different enough not to be
+   permitted in C11 typedef redeclarations, then this sets
+   *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
+   false, but may or may not be set if the types are incompatible.
+   This differs from comptypes, in that we don't free the seen
+   types.  */
 
 static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
+comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
+                   bool *different_types_p)
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
@@ -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;
 
-  /* 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.  */
@@ -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 (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE)
-       *enum_and_int_p = true;
+      if (TREE_CODE (t2) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
     }
   else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
     {
       t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
-      if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
-       *enum_and_int_p = true;
+      if (TREE_CODE (t1) != VOID_TYPE)
+       {
+         if (enum_and_int_p != NULL)
+           *enum_and_int_p = true;
+         if (different_types_p != NULL)
+           *different_types_p = true;
+       }
     }
 
   if (t1 == t2)
@@ -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.  */
-  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.  */
@@ -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),
-                                      enum_and_int_p));
+                                      enum_and_int_p, different_types_p));
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2, enum_and_int_p);
+      val = function_types_compatible_p (t1, t2, enum_and_int_p,
+                                        different_types_p);
       break;
 
     case ARRAY_TYPE:
@@ -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),
-                                              enum_and_int_p)))
+                                              enum_and_int_p,
+                                              different_types_p)))
          return 0;
 
+       if (different_types_p != NULL
+           && (d1 == 0) != (d2 == 0))
+         *different_types_p = true;
        /* Sizes must match unless one is missing or variable.  */
        if (d1 == 0 || d2 == 0 || d1 == d2)
          break;
@@ -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));
 
+       if (different_types_p != NULL
+           && d1_variable != d2_variable)
+         *different_types_p = true;
        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)
-           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
-         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+           return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                                different_types_p);
+         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
+                                             different_types_p);
        }
       break;
 
     case VECTOR_TYPE:
       val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
             && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                   enum_and_int_p));
+                                   enum_and_int_p, different_types_p));
       break;
 
     default:
@@ -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 1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers.  */
+/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
+   their qualifiers, except for named address spaces.  If the pointers point to
+   different named addresses, then we must determine if one address space is a
+   subset of the other.  */
 
 static int
 comp_target_types (location_t location, tree ttl, tree ttr)
 {
   int val;
-  tree mvl, mvr;
+  tree mvl = TREE_TYPE (ttl);
+  tree mvr = TREE_TYPE (ttr);
+  addr_space_t asl = TYPE_ADDR_SPACE (mvl);
+  addr_space_t asr = TYPE_ADDR_SPACE (mvr);
+  addr_space_t as_common;
   bool enum_and_int_p;
 
+  /* Fail if pointers point to incompatible address spaces.  */
+  if (!addr_space_superset (asl, asr, &as_common))
+    return 0;
+
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  mvl = TREE_TYPE (ttl);
-  mvr = TREE_TYPE (ttr);
   if (TREE_CODE (mvl) != ARRAY_TYPE)
     mvl = TYPE_MAIN_VARIANT (mvl);
   if (TREE_CODE (mvr) != ARRAY_TYPE)
@@ -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
-   rules.  ENUM_AND_INT_P is as in comptypes_internal.  */
+   rules.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
 
 static int
 tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
-                             bool *enum_and_int_p)
+                             bool *enum_and_int_p, bool *different_types_p)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -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;
-            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
          {
            int result;
 
            if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p);
+                                        enum_and_int_p, different_types_p);
 
            if (result != 1 && !DECL_NAME (s1))
              break;
@@ -1359,17 +1452,18 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
            return tu->val;
          }
 
-       for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
+       for (s1 = TYPE_FIELDS (t1); s1; s1 = DECL_CHAIN (s1))
          {
            bool ok = false;
 
-           for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
+           for (s2 = TYPE_FIELDS (t2); s2; s2 = DECL_CHAIN (s2))
              if (DECL_NAME (s1) == DECL_NAME (s2))
                {
                  int result;
 
                  result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                              enum_and_int_p);
+                                              enum_and_int_p,
+                                              different_types_p);
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
@@ -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;
-            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+            s1 = DECL_CHAIN (s1), s2 = DECL_CHAIN (s2))
          {
            int result;
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
            result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p);
+                                        enum_and_int_p, different_types_p);
            if (result == 0)
              break;
            if (result == 2)
@@ -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.
-   ENUM_AND_INT_P is as in comptypes_internal.  */
+   ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal.  */
 
 static int
 function_types_compatible_p (const_tree f1, const_tree f2,
-                            bool *enum_and_int_p)
+                            bool *enum_and_int_p, bool *different_types_p)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -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);
-  val = comptypes_internal (ret1, ret2, enum_and_int_p);
+  val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
   if (val == 0)
     return 0;
 
   args1 = TYPE_ARG_TYPES (f1);
   args2 = TYPE_ARG_TYPES (f2);
 
+  if (different_types_p != NULL
+      && (args1 == 0) != (args2 == 0))
+    *different_types_p = true;
+
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
 
@@ -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),
-                                          enum_and_int_p))
+                                          enum_and_int_p, different_types_p))
        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),
-                                          enum_and_int_p))
+                                          enum_and_int_p, different_types_p))
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p);
+  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
+                                 different_types_p);
   return val1 != 1 ? val1 : val;
 }
 
 /* Check two lists of types for compatibility, returning 0 for
    incompatible, 1 for compatible, or 2 for compatible with
-   warning.  ENUM_AND_INT_P is as in comptypes_internal.  */
+   warning.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
+   comptypes_internal.  */
 
 static int
 type_lists_compatible_p (const_tree args1, const_tree args2,
-                        bool *enum_and_int_p)
+                        bool *enum_and_int_p, bool *different_types_p)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -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.  */
+      if (different_types_p != NULL
+         && (a1 == 0) != (a2 == 0))
+       *different_types_p = true;
       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 (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p)))
+      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
+                                             different_types_p)))
        {
+         if (different_types_p != NULL)
+           *different_types_p = true;
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
          if (TREE_CODE (a1) == UNION_TYPE
              && (TYPE_NAME (a1) == 0
-                 || TYPE_TRANSPARENT_UNION (a1))
+                 || TYPE_TRANSPARENT_AGGR (a1))
              && TREE_CODE (TYPE_SIZE (a1)) == INTEGER_CST
              && tree_int_cst_equal (TYPE_SIZE (a1),
                                     TYPE_SIZE (a2)))
            {
              tree memb;
              for (memb = TYPE_FIELDS (a1);
-                  memb; memb = TREE_CHAIN (memb))
+                  memb; memb = DECL_CHAIN (memb))
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv2, enum_and_int_p))
+                 if (comptypes_internal (mv3, mv2, enum_and_int_p,
+                                         different_types_p))
                    break;
                }
              if (memb == 0)
@@ -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
-                      || TYPE_TRANSPARENT_UNION (a2))
+                      || TYPE_TRANSPARENT_AGGR (a2))
                   && TREE_CODE (TYPE_SIZE (a2)) == INTEGER_CST
                   && tree_int_cst_equal (TYPE_SIZE (a2),
                                          TYPE_SIZE (a1)))
            {
              tree memb;
              for (memb = TYPE_FIELDS (a2);
-                  memb; memb = TREE_CHAIN (memb))
+                  memb; memb = DECL_CHAIN (memb))
                {
                  tree mv3 = TREE_TYPE (memb);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes_internal (mv3, mv1, enum_and_int_p))
+                 if (comptypes_internal (mv3, mv1, enum_and_int_p,
+                                         different_types_p))
                    break;
                }
              if (memb == 0)
@@ -1697,6 +1805,36 @@ function_to_pointer_conversion (location_t loc, tree exp)
   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.
@@ -1752,6 +1890,12 @@ default_function_array_conversion (location_t loc, struct c_expr exp)
   return exp;
 }
 
+struct c_expr
+default_function_array_read_conversion (location_t loc, struct c_expr exp)
+{
+  mark_exp_read (exp.value);
+  return default_function_array_conversion (loc, exp);
+}
 
 /* EXP is an expression of integer type.  Apply the integer promotions
    to it and return the promoted value.  */
@@ -1813,6 +1957,8 @@ default_conversion (tree exp)
   enum tree_code code = TREE_CODE (type);
   tree promoted_type;
 
+  mark_exp_read (exp);
+
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
   if (code == ARRAY_TYPE)
@@ -1849,7 +1995,7 @@ default_conversion (tree exp)
   return exp;
 }
 \f
-/* Look up COMPONENT in a structure or union DECL.
+/* Look up COMPONENT in a structure or union TYPE.
 
    If the component name is not found, returns NULL_TREE.  Otherwise,
    the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
@@ -1859,9 +2005,8 @@ default_conversion (tree exp)
    unions, the list steps down the chain to the component.  */
 
 static tree
-lookup_field (tree decl, tree component)
+lookup_field (tree type, tree component)
 {
-  tree type = TREE_TYPE (decl);
   tree field;
 
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@@ -1891,10 +2036,21 @@ lookup_field (tree decl, tree component)
                  if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                      || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
                    {
-                     tree anon = lookup_field (field, component);
+                     tree anon = lookup_field (TREE_TYPE (field), component);
 
                      if (anon)
                        return tree_cons (NULL_TREE, field, anon);
+
+                     /* The Plan 9 compiler permits referring
+                        directly to an anonymous struct/union field
+                        using a typedef name.  */
+                     if (flag_plan9_extensions
+                         && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                         && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+                             == TYPE_DECL)
+                         && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                             == component))
+                       break;
                    }
                }
 
@@ -1921,16 +2077,26 @@ lookup_field (tree decl, tree component)
     }
   else
     {
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        {
          if (DECL_NAME (field) == NULL_TREE
              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
            {
-             tree anon = lookup_field (field, component);
+             tree anon = lookup_field (TREE_TYPE (field), component);
 
              if (anon)
                return tree_cons (NULL_TREE, field, anon);
+
+             /* The Plan 9 compiler permits referring directly to an
+                anonymous struct/union field using a typedef
+                name.  */
+             if (flag_plan9_extensions
+                 && TYPE_NAME (TREE_TYPE (field)) != NULL_TREE
+                 && TREE_CODE (TYPE_NAME (TREE_TYPE (field))) == TYPE_DECL
+                 && (DECL_NAME (TYPE_NAME (TREE_TYPE (field)))
+                     == component))
+               break;
            }
 
          if (DECL_NAME (field) == component)
@@ -1960,6 +2126,11 @@ build_component_ref (location_t loc, tree datum, tree component)
   if (!objc_is_public (datum, component))
     return error_mark_node;
 
+  /* Detect Objective-C property syntax object.property.  */
+  if (c_dialect_objc ()
+      && (ref = objc_maybe_build_component_ref (datum, component)))
+    return ref;
+
   /* See if there is a field or component with name COMPONENT.  */
 
   if (code == RECORD_TYPE || code == UNION_TYPE)
@@ -1970,7 +2141,7 @@ build_component_ref (location_t loc, tree datum, tree component)
          return error_mark_node;
        }
 
-      field = lookup_field (datum, component);
+      field = lookup_field (type, component);
 
       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
-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);
@@ -2099,8 +2270,8 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error_at (loc,
-             "invalid type argument of %qs (have %qT)", errorstring, type);
+    invalid_indirection_error (loc, type, errstring);
+
   return error_mark_node;
 }
 
@@ -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).
 
+   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
@@ -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
-      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE)
+      && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE
+      /* Allow vector[index] but not index[vector].  */
+      && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE)
     {
       tree temp;
       if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
          && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
        {
-         error_at (loc, "subscripted value is neither array nor pointer");
+          error_at (loc,
+            "subscripted value is neither array nor pointer nor vector");
+
          return error_mark_node;
        }
       temp = array;
@@ -2162,6 +2340,27 @@ build_array_ref (location_t loc, tree array, tree index)
 
   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;
@@ -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))
-           pedwarn (loc, OPT_pedantic, 
+           pedwarn (loc, OPT_pedantic,
                     "ISO C forbids subscripting %<register%> array");
          else if (!flag_isoc99 && !lvalue_p (foo))
-           pedwarn (loc, OPT_pedantic, 
+           pedwarn (loc, OPT_pedantic,
                     "ISO C90 forbids subscripting non-lvalue array");
        }
 
@@ -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),
-        "array indexing");
+        RO_ARRAY_INDEXING);
     }
 }
 \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.  */
-  if (ref != current_function_decl) 
+  if (ref != current_function_decl)
     {
       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;
-  
+
 
   /* 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);
+
+      if (flag_tm)
+       tm_malloc_replacement (function);
       fundecl = function;
+      /* Atomic functions have type checking/casting already done.  They are 
+        often rewritten and don't match the original parameter list.  */
+      if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
+        origtypes = NULL;
     }
   if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
     function = function_to_pointer_conversion (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);
-      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;
 
@@ -2600,7 +2807,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                                          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));
@@ -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.  */
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
-                           TYPE_ARG_TYPES (fntype));
+  check_function_arguments (fntype, nargs, argarray);
 
   if (name != NULL_TREE
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
     {
       if (require_constant_value)
-       result = 
+       result =
          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);
 }
+
+/* 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.
@@ -2673,6 +2971,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 {
   tree typetail, val;
   unsigned int parmnum;
+  bool error_args = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
@@ -2729,7 +3028,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
       if (type == void_type_node)
        {
-         error ("too many arguments to function %qE", function);
+         if (selector)
+           error_at (input_location,
+                     "too many arguments to method %qE", selector);
+         else
+           error_at (input_location,
+                     "too many arguments to function %qE", function);
+
+         if (fundecl && !DECL_BUILT_IN (fundecl))
+           inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
          return parmnum;
        }
 
@@ -2924,8 +3231,15 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
          if (type_generic)
            parmval = val;
          else
-           /* Convert `float' to `double'.  */
-           parmval = convert (double_type_node, val);
+           {
+             /* Convert `float' to `double'.  */
+             if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+               warning (OPT_Wdouble_promotion,
+                        "implicit conversion from %qT to %qT when passing "
+                        "argument to function",
+                        valtype, double_type_node);
+             parmval = convert (double_type_node, val);
+           }
        }
       else if (excess_precision && !type_generic)
        /* A "double" argument with excess precision being passed
@@ -2942,6 +3256,8 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
        parmval = default_conversion (val);
 
       VEC_replace (tree, values, parmnum, parmval);
+      if (parmval == error_mark_node)
+       error_args = true;
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
@@ -2951,11 +3267,14 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
-      error ("too few arguments to function %qE", function);
+      error_at (input_location,
+               "too few arguments to function %qE", function);
+      if (fundecl && !DECL_BUILT_IN (fundecl))
+       inform (DECL_SOURCE_LOCATION (fundecl), "declared here");
       return -1;
     }
 
-  return parmnum;
+  return error_args ? -1 : (int) parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
@@ -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");
 
-  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);
 
@@ -3063,16 +3382,48 @@ static tree
 pointer_diff (location_t loc, tree op0, tree op1)
 {
   tree restype = ptrdiff_type_node;
+  tree result, inttype;
 
+  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
+  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
   tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
+  /* If the operands point into different address spaces, we need to
+     explicitly convert them to pointers into the common address space
+     before we can subtract the numerical address values.  */
+  if (as0 != as1)
+    {
+      addr_space_t as_common;
+      tree common_type;
+
+      /* Determine the common superset address space.  This is guaranteed
+        to exist because the caller verified that comp_target_types
+        returned non-zero.  */
+      if (!addr_space_superset (as0, as1, &as_common))
+       gcc_unreachable ();
+
+      common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+      op0 = convert (common_type, op0);
+      op1 = convert (common_type, op1);
+    }
+
+  /* Determine integer type to perform computations in.  This will usually
+     be the same as the result type (ptrdiff_t), but may need to be a wider
+     type if pointers for the address space are wider than ptrdiff_t.  */
+  if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0)))
+    inttype = lang_hooks.types.type_for_size
+               (TYPE_PRECISION (TREE_TYPE (op0)), 0);
+  else
+    inttype = restype;
+
+
   if (TREE_CODE (target_type) == VOID_TYPE)
-    pedwarn (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)
-    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
@@ -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,
-                        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");
@@ -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.  */
-  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
@@ -3233,7 +3587,7 @@ build_unary_op (location_t location,
       else if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
@@ -3284,26 +3638,10 @@ build_unary_op (location_t location,
       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:
-      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;
@@ -3326,11 +3664,14 @@ build_unary_op (location_t location,
          goto return_build_unary_op;
        }
 
-      /* Complain about anything that is not a true lvalue.  */
-      if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
-                                 || code == POSTINCREMENT_EXPR)
-                                ? lv_increment
-                                : lv_decrement)))
+      /* Complain about anything that is not a true lvalue.  In
+        Objective-C, skip this check for property_refs.  */
+      if (!objc_is_property_ref (arg)
+         && !lvalue_or_else (location,
+                             arg, ((code == PREINCREMENT_EXPR
+                                    || code == POSTINCREMENT_EXPR)
+                                   ? lv_increment
+                                   : lv_decrement)))
        return error_mark_node;
 
       if (warn_cxx_compat && TREE_CODE (TREE_TYPE (arg)) == ENUMERAL_TYPE)
@@ -3352,7 +3693,7 @@ build_unary_op (location_t location,
        {
          tree real, imag;
 
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
@@ -3403,15 +3744,15 @@ build_unary_op (location_t location,
                     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
                           "wrong type argument to increment");
                else
-                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
                           "wrong type argument to decrement");
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = fold_convert_loc (location, sizetype, inc);
+           inc = convert_to_ptrofftype_loc (location, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3438,6 +3779,13 @@ build_unary_op (location_t location,
            inc = convert (argtype, inc);
          }
 
+       /* If 'arg' is an Objective-C PROPERTY_REF expression, then we
+          need to ask Objective-C to build the increment or decrement
+          expression for it.  */
+       if (objc_is_property_ref (arg))
+         return objc_build_incr_expr_for_property_ref (location, code,
+                                                       arg, inc);
+
        /* Report a read-only lvalue.  */
        if (TYPE_READONLY (argtype))
          {
@@ -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;
-         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
-              && !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
@@ -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
-        to which the address will point.  Note that you can't get a
-        restricted pointer by taking the address of something, so we
-        only have to deal with `const' and `volatile' here.  */
+        to which the address will point.  This is only needed
+        for function types.  */
       if ((DECL_P (arg) || REFERENCE_CLASS_P (arg))
-         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg)))
-         argtype = c_build_type_variant (argtype,
-                                         TREE_READONLY (arg),
-                                         TREE_THIS_VOLATILE (arg));
+         && (TREE_READONLY (arg) || TREE_THIS_VOLATILE (arg))
+         && TREE_CODE (argtype) == FUNCTION_TYPE)
+       {
+         int orig_quals = TYPE_QUALS (strip_array_types (argtype));
+         int quals = orig_quals;
+
+         if (TREE_READONLY (arg))
+           quals |= TYPE_QUAL_CONST;
+         if (TREE_THIS_VOLATILE (arg))
+           quals |= TYPE_QUAL_VOLATILE;
+
+         argtype = c_build_qualified_type (argtype, quals);
+       }
 
       if (!c_mark_addressable (arg))
        return error_mark_node;
@@ -3547,11 +3897,7 @@ build_unary_op (location_t location,
       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;
        }
 
@@ -3625,44 +3971,6 @@ lvalue_p (const_tree ref)
     }
 }
 \f
-/* Give an error for storing in something that is 'const'.  */
-
-static void
-readonly_error (tree arg, enum lvalue_use use)
-{
-  gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
-             || use == lv_asm);
-  /* Using this macro rather than (for example) arrays of messages
-     ensures that all the format strings are checked at compile
-     time.  */
-#define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A)              \
-                                  : (use == lv_increment ? (I)         \
-                                  : (use == lv_decrement ? (D) : (AS))))
-  if (TREE_CODE (arg) == COMPONENT_REF)
-    {
-      if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       readonly_error (TREE_OPERAND (arg, 0), use);
-      else
-       error (READONLY_MSG (G_("assignment of read-only member %qD"),
-                            G_("increment of read-only member %qD"),
-                            G_("decrement of read-only member %qD"),
-                            G_("read-only member %qD used as %<asm%> output")),
-              TREE_OPERAND (arg, 1));
-    }
-  else if (TREE_CODE (arg) == VAR_DECL)
-    error (READONLY_MSG (G_("assignment of read-only variable %qD"),
-                        G_("increment of read-only variable %qD"),
-                        G_("decrement of read-only variable %qD"),
-                        G_("read-only variable %qD used as %<asm%> output")),
-          arg);
-  else
-    error (READONLY_MSG (G_("assignment of read-only location %qE"),
-                        G_("increment of read-only location %qE"),
-                        G_("decrement of read-only location %qE"),
-                        G_("read-only location %qE used as %<asm%> output")),
-          arg);
-}
-
 /* Give a warning for storing in something that is read-only in GCC
    terms but not const in ISO C terms.  */
 
@@ -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
-   how the lvalue is being used and so selects the error message.  */
+   how the lvalue is being used and so selects the error message.
+   LOCATION is the location at which any error should be reported.  */
 
 static int
-lvalue_or_else (const_tree ref, enum lvalue_use use)
+lvalue_or_else (location_t loc, const_tree ref, enum lvalue_use use)
 {
   int win = lvalue_p (ref);
 
   if (!win)
-    lvalue_error (use);
+    lvalue_error (loc, use);
 
   return win;
 }
@@ -3769,6 +4078,34 @@ c_mark_addressable (tree exp)
     }
 }
 \f
+/* Convert EXPR to TYPE, warning about conversion problems with
+   constants.  SEMANTIC_TYPE is the type this conversion would use
+   without excess precision. If SEMANTIC_TYPE is NULL, this function
+   is equivalent to convert_and_check. This function is a wrapper that
+   handles conversions that may be different than
+   the usual ones because of excess precision.  */
+
+static tree
+ep_convert_and_check (tree type, tree expr, tree semantic_type)
+{
+  if (TREE_TYPE (expr) == type)
+    return expr;
+
+  if (!semantic_type)
+    return convert_and_check (type, expr);
+
+  if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      && TREE_TYPE (expr) != semantic_type)
+    {
+      /* For integers, we need to check the real conversion, not
+        the conversion to the excess precision type.  */
+      expr = convert_and_check (semantic_type, expr);
+    }
+  /* Result type is the excess precision type, which should be
+     large enough, so do not check.  */
+  return convert (type, expr);
+}
+
 /* Build and return a conditional expression IFEXP ? OP1 : OP2.  If
    IFEXP_BCP then the condition is a call to __builtin_constant_p, and
    if folded to an integer constant then the unselected half may
@@ -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;
-  tree ep_result_type = NULL;
+  tree semantic_result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
   bool int_const, op1_int_operands, op2_int_operands, int_operands;
   bool ifexp_int_operands;
   tree ret;
-  bool objc_ok;
 
   op1_int_operands = EXPR_INT_CONST_OPERANDS (orig_op1);
   if (op1_int_operands)
@@ -3827,8 +4163,6 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       return error_mark_node;
     }
 
-  objc_ok = objc_compare_types (type1, type2, -3, NULL_TREE);
-
   if ((TREE_CODE (op1) == EXCESS_PRECISION_EXPR
        || TREE_CODE (op2) == EXCESS_PRECISION_EXPR)
       && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
@@ -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))
     {
-      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);
@@ -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);
+      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
@@ -3956,12 +4294,22 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
+      addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+      addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2));
+      addr_space_t as_common;
+
       if (comp_target_types (colon_loc, type1, type2))
        result_type = common_pointer_type (type1, type2);
       else if (null_pointer_constant_p (orig_op1))
-       result_type = qualify_type (type2, type1);
+       result_type = type2;
       else if (null_pointer_constant_p (orig_op2))
-       result_type = qualify_type (type1, type2);
+       result_type = type1;
+      else if (!addr_space_superset (as1, as2, &as_common))
+       {
+         error_at (colon_loc, "pointers to disjoint address spaces "
+                   "used in conditional expression");
+         return error_mark_node;
+       }
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
@@ -3980,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)));
        }
+      /* Objective-C pointer comparisons are a bit more lenient.  */
+      else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
+       result_type = objc_common_type (type1, type2);
       else
        {
-         if (!objc_ok)
-           pedwarn (colon_loc, 0,
-                    "pointer type mismatch in conditional expression");
-         result_type = build_pointer_type (void_type_node);
+         int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+
+         pedwarn (colon_loc, 0,
+                  "pointer type mismatch in conditional expression");
+         result_type = build_pointer_type
+                         (build_qualified_type (void_type_node, qual));
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
@@ -4028,10 +4381,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                          TYPE_READONLY (type1) || TYPE_READONLY (type2),
                          TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
 
-  if (result_type != type1)
-    op1 = convert_and_check (result_type, op1);
-  if (result_type != type2)
-    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)
     {
@@ -4063,8 +4414,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       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;
@@ -4112,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
-           warning_at (loc, OPT_Wunused_value, 
+           warning_at (loc, OPT_Wunused_value,
                        "left-hand operand of comma expression has no effect");
        }
     }
@@ -4143,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
-   cast.  Both TYPE and OTYPE are pointer types.  -Wcast-qual appeared
-   on the command line.  */
+   cast.  Both TYPE and OTYPE are pointer types.  LOC is the location
+   of the cast.  -Wcast-qual appeared on the command line.  Named
+   address space qualifiers are not handled here, because they result
+   in different warnings.  */
 
 static void
-handle_warn_cast_qual (tree type, tree otype)
+handle_warn_cast_qual (location_t loc, tree type, tree otype)
 {
   tree in_type = type;
   tree in_otype = otype;
@@ -4170,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)
-       added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+       added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
       else
-       discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+       discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
     }
   while (TREE_CODE (in_type) == POINTER_TYPE
         && TREE_CODE (in_otype) == POINTER_TYPE);
 
   if (added)
-    warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+    warning_at (loc, OPT_Wcast_qual,
+               "cast adds %q#v qualifier to function type", added);
 
   if (discarded)
     /* There are qualifiers present in IN_OTYPE that are not present
        in IN_TYPE.  */
-    warning (OPT_Wcast_qual,
-            "cast discards qualifiers from pointer target type");
+    warning_at (loc, OPT_Wcast_qual,
+               "cast discards %q#v qualifier from pointer target type",
+               discarded);
 
   if (added || discarded)
     return;
@@ -4217,9 +4574,10 @@ handle_warn_cast_qual (tree type, tree otype)
       if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
          && !is_const)
        {
-         warning (OPT_Wcast_qual,
-                  ("new qualifiers in middle of multi-level non-const cast "
-                   "are unsafe"));
+         warning_at (loc, OPT_Wcast_qual,
+                     "to be safe all intermediate pointers in cast from "
+                      "%qT to %qT must be %<const%> qualified",
+                     otype, type);
          break;
        }
       if (is_const)
@@ -4228,7 +4586,7 @@ handle_warn_cast_qual (tree type, tree otype)
   while (TREE_CODE (in_type) == POINTER_TYPE);
 }
 
-/* Build an expression representing a cast to type TYPE of expression EXPR.  
+/* Build an expression representing a cast to type TYPE of expression EXPR.
    LOC is the location of the cast-- typically the open paren of the cast.  */
 
 tree
@@ -4275,14 +4633,14 @@ build_c_cast (location_t loc, tree type, tree expr)
     {
       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;
 
-      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))))
@@ -4291,10 +4649,14 @@ build_c_cast (location_t loc, tree type, tree expr)
       if (field)
        {
          tree t;
+         bool maybe_const = true;
 
          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;
@@ -4319,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)
-       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
@@ -4461,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);
 
-  /* 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++");
 
@@ -4483,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,
-                  enum tree_code modifycode, 
+                  enum tree_code modifycode,
                   location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
@@ -4500,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 (!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)
@@ -4541,6 +4935,19 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
       rhs_origtype = NULL_TREE;
     }
 
+  if (c_dialect_objc ())
+    {
+      /* Check if we are modifying an Objective-C property reference;
+        if so, we need to generate setter calls.  */
+      result = objc_maybe_build_modify_expr (lhs, newrhs);
+      if (result)
+       return result;
+
+      /* Else, do the check that we postponed for Objective-C.  */
+      if (!lvalue_or_else (location, lhs, lv_assign))
+       return error_mark_node;
+    }
+
   /* Give an error for storing in something that is 'const'.  */
 
   if (TYPE_READONLY (lhstype)
@@ -4636,6 +5043,106 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
   return result;
 }
 \f
+/* Return whether STRUCT_TYPE has an anonymous field with type TYPE.
+   This is used to implement -fplan9-extensions.  */
+
+static bool
+find_anonymous_field_with_type (tree struct_type, tree type)
+{
+  tree field;
+  bool found;
+
+  gcc_assert (TREE_CODE (struct_type) == RECORD_TYPE
+             || TREE_CODE (struct_type) == UNION_TYPE);
+  found = false;
+  for (field = TYPE_FIELDS (struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) == NULL
+         && comptypes (type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+      else if (DECL_NAME (field) == NULL
+              && (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
+                  || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+              && find_anonymous_field_with_type (TREE_TYPE (field), type))
+       {
+         if (found)
+           return false;
+         found = true;
+       }
+    }
+  return found;
+}
+
+/* RHS is an expression whose type is pointer to struct.  If there is
+   an anonymous field in RHS with type TYPE, then return a pointer to
+   that field in RHS.  This is used with -fplan9-extensions.  This
+   returns NULL if no conversion could be found.  */
+
+static tree
+convert_to_anonymous_field (location_t location, tree type, tree rhs)
+{
+  tree rhs_struct_type, lhs_main_type;
+  tree field, found_field;
+  bool found_sub_field;
+  tree ret;
+
+  gcc_assert (POINTER_TYPE_P (TREE_TYPE (rhs)));
+  rhs_struct_type = TREE_TYPE (TREE_TYPE (rhs));
+  gcc_assert (TREE_CODE (rhs_struct_type) == RECORD_TYPE
+             || TREE_CODE (rhs_struct_type) == UNION_TYPE);
+
+  gcc_assert (POINTER_TYPE_P (type));
+  lhs_main_type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
+
+  found_field = NULL_TREE;
+  found_sub_field = false;
+  for (field = TYPE_FIELDS (rhs_struct_type);
+       field != NULL_TREE;
+       field = TREE_CHAIN (field))
+    {
+      if (DECL_NAME (field) != NULL_TREE
+         || (TREE_CODE (TREE_TYPE (field)) != RECORD_TYPE
+             && TREE_CODE (TREE_TYPE (field)) != UNION_TYPE))
+       continue;
+      if (comptypes (lhs_main_type, TYPE_MAIN_VARIANT (TREE_TYPE (field))))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+       }
+      else if (find_anonymous_field_with_type (TREE_TYPE (field),
+                                              lhs_main_type))
+       {
+         if (found_field != NULL_TREE)
+           return NULL_TREE;
+         found_field = field;
+         found_sub_field = true;
+       }
+    }
+
+  if (found_field == NULL_TREE)
+    return NULL_TREE;
+
+  ret = fold_build3_loc (location, COMPONENT_REF, TREE_TYPE (found_field),
+                        build_fold_indirect_ref (rhs), found_field,
+                        NULL_TREE);
+  ret = build_fold_addr_expr_loc (location, ret);
+
+  if (found_sub_field)
+    {
+      ret = convert_to_anonymous_field (location, type, ret);
+      gcc_assert (ret != NULL_TREE);
+    }
+
+  return ret;
+}
+
 /* Convert value RHS to type TYPE as preparation for an assignment to
    an lvalue of type TYPE.  If ORIGTYPE is not NULL_TREE, it is the
    original type of RHS; this differs from TREE_TYPE (RHS) for enum
@@ -4701,7 +5208,7 @@ convert_for_assignment (location_t location, tree type, tree rhs,
         pedwarn (LOCATION, OPT, AS);                                     \
         break;                                                           \
       case ic_init:                                                      \
-        pedwarn (LOCATION, OPT, IN);                                     \
+        pedwarn_init (LOCATION, OPT, IN);                                \
         break;                                                           \
       case ic_return:                                                    \
         pedwarn (LOCATION, OPT, RE);                                    \
@@ -4711,6 +5218,36 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       }                                                                  \
   } 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);
 
@@ -4828,10 +5365,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
     {
       tree ret;
       bool save = in_late_binary_op;
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = true;
       ret = convert_and_check (type, orig_rhs);
-      if (codel == BOOLEAN_TYPE)
+      if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
        in_late_binary_op = save;
       return ret;
     }
@@ -4842,14 +5379,15 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       && comptypes (type, rhstype))
     return convert_and_check (type, rhs);
 
-  /* Conversion to a transparent union from its member types.
+  /* Conversion to a transparent union or record from its member types.
      This applies only to function arguments.  */
-  if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+  if (((codel == UNION_TYPE || codel == RECORD_TYPE)
+      && TYPE_TRANSPARENT_AGGR (type))
       && errtype == ic_argpass)
     {
       tree memb, marginal_memb = NULL_TREE;
 
-      for (memb = TYPE_FIELDS (type); memb ; memb = TREE_CHAIN (memb))
+      for (memb = TYPE_FIELDS (type); memb ; memb = DECL_CHAIN (memb))
        {
          tree memb_type = TREE_TYPE (memb);
 
@@ -4915,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.  */
-                 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 qualified function "
+                                           "makes %q#v qualified function "
                                            "pointer from unqualified"),
-                                        G_("assignment makes qualified "
+                                        G_("assignment makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("initialization makes qualified "
+                                        G_("initialization makes %q#v qualified "
                                            "function pointer from "
                                            "unqualified"),
-                                        G_("return makes qualified function "
-                                           "pointer from unqualified"));
+                                        G_("return makes %q#v qualified function "
+                                           "pointer from unqualified"),
+                                        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
                }
-             else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
-               WARN_FOR_ASSIGNMENT (location, 0,
+             else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
+               WARN_FOR_QUALIFIERS (location, 0,
                                     G_("passing argument %d of %qE discards "
-                                       "qualifiers from pointer target type"),
-                                    G_("assignment discards qualifiers "
+                                       "%qv qualifier from pointer target type"),
+                                    G_("assignment discards %qv qualifier "
                                        "from pointer target type"),
-                                    G_("initialization discards qualifiers "
+                                    G_("initialization discards %qv qualifier "
                                        "from pointer target type"),
-                                    G_("return discards qualifiers from "
-                                       "pointer target type"));
+                                    G_("return discards %qv qualifier from "
+                                       "pointer target type"),
+                                    TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
 
              memb = marginal_memb;
            }
 
          if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
-           pedwarn (location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ISO C prohibits argument conversion to union type");
 
          rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
@@ -4962,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.  */
+      addr_space_t asl;
+      addr_space_t asr;
 
       if (TREE_CODE (mvl) != ARRAY_TYPE)
        mvl = TYPE_MAIN_VARIANT (mvl);
@@ -4970,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);
 
+      /* 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
@@ -4982,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);
 
+      /* 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
@@ -5045,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)
            {
-             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.  */
@@ -5085,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.  */
-             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 "
-                                       "qualified function pointer "
+                                       "%q#v qualified function pointer "
                                        "from unqualified"),
-                                    G_("assignment makes qualified function "
+                                    G_("assignment makes %q#v qualified function "
                                        "pointer from unqualified"),
-                                    G_("initialization makes qualified "
+                                    G_("initialization makes %q#v qualified "
                                        "function pointer from unqualified"),
-                                    G_("return makes qualified function "
-                                       "pointer from unqualified"));
+                                    G_("return makes %q#v qualified function "
+                                       "pointer from unqualified"),
+                                    TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
            }
        }
       else
@@ -5249,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);
-  if (TREE_STATIC (decl)) 
+  if (TREE_STATIC (decl))
     constant_expression_warning (value);
 
   /* Check if we need to set array size from compound literal size.  */
@@ -5271,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.  */
+             tree etype = strip_array_types (TREE_TYPE (decl));
              type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
-             TREE_TYPE (decl) = type;
              TYPE_DOMAIN (type) = TYPE_DOMAIN (TREE_TYPE (cldecl));
              layout_type (type);
              layout_decl (cldecl, 0);
+             TREE_TYPE (decl)
+               = c_build_qualified_type (type, TYPE_QUALS (etype));
            }
        }
     }
@@ -5404,15 +5999,16 @@ print_spelling (char *buffer)
 }
 
 /* Issue an error message for a bad initializer component.
-   MSGID identifies the message.
+   GMSGID identifies the message.
    The component name is taken from the spelling stack.  */
 
 void
-error_init (const char *msgid)
+error_init (const char *gmsgid)
 {
   char *ofwhat;
 
-  error ("%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  error (gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     error ("(near initialization for %qs)", ofwhat);
@@ -5420,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
-   it is unconditionally given.  MSGID identifies the message.  The
+   it is unconditionally given.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
 void
-pedwarn_init (location_t location, int opt, const char *msgid)
+pedwarn_init (location_t location, int opt, const char *gmsgid)
 {
   char *ofwhat;
 
-  pedwarn (location, opt, "%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  pedwarn (location, opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
 }
 
-/* Issue a warning for a bad initializer component.  
+/* Issue a warning for a bad initializer component.
 
    OPT is the OPT_W* value corresponding to the warning option that
-   controls this warning.  MSGID identifies the message.  The
+   controls this warning.  GMSGID identifies the message.  The
    component name is taken from the spelling stack.  */
 
 static void
-warning_init (int opt, const char *msgid)
+warning_init (int opt, const char *gmsgid)
 {
   char *ofwhat;
 
-  warning (opt, "%s", _(msgid));
+  /* The gmsgid may be a format string with %< and %>. */
+  warning (opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat)
     warning (opt, "(near initialization for %qs)", ofwhat);
@@ -5462,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)
-    pedwarn_init (input_location, OPT_pedantic, 
+    pedwarn_init (input_location, OPT_pedantic,
                  "array initialized from parenthesized string constant");
 }
 
@@ -6097,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)
-       constructor_fields = TREE_CHAIN (constructor_fields);
+       constructor_fields = DECL_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6112,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))
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          constructor_index
            = convert (bitsizetype,
@@ -6137,7 +6735,7 @@ really_start_incremental_init (tree type)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
       constructor_index = bitsize_zero_node;
       constructor_unfilled_index = constructor_index;
     }
@@ -6155,7 +6753,7 @@ really_start_incremental_init (tree type)
    IMPLICIT is 1 (or 2 if the push is because of designator list).  */
 
 void
-push_init_level (int implicit)
+push_init_level (int implicit, struct obstack * braced_init_obstack)
 {
   struct constructor_stack *p;
   tree value = NULL_TREE;
@@ -6173,12 +6771,14 @@ push_init_level (int implicit)
          if ((TREE_CODE (constructor_type) == RECORD_TYPE
               || TREE_CODE (constructor_type) == UNION_TYPE)
              && constructor_fields == 0)
-           process_init_element (pop_init_level (1), true);
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
          else if (TREE_CODE (constructor_type) == ARRAY_TYPE
                   && constructor_max_index
                   && tree_int_cst_lt (constructor_max_index,
                                       constructor_index))
-           process_init_element (pop_init_level (1), true);
+           process_init_element (pop_init_level (1, braced_init_obstack),
+                                 true, braced_init_obstack);
          else
            break;
        }
@@ -6191,9 +6791,9 @@ push_init_level (int implicit)
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
           || TREE_CODE (constructor_type) == UNION_TYPE)
          && constructor_fields)
-       value = find_init_member (constructor_fields);
+       value = find_init_member (constructor_fields, braced_init_obstack);
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
-       value = find_init_member (constructor_index);
+       value = find_init_member (constructor_index, braced_init_obstack);
     }
 
   p = XNEW (struct constructor_stack);
@@ -6279,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))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
     }
 
   if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
@@ -6295,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)
-       constructor_fields = TREE_CHAIN (constructor_fields);
+       constructor_fields = DECL_CHAIN (constructor_fields);
 
       constructor_unfilled_fields = constructor_fields;
       constructor_bit_index = bitsize_zero_node;
@@ -6304,8 +6904,8 @@ push_init_level (int implicit)
     {
       /* Vectors are like simple fixed-size arrays.  */
       constructor_max_index =
-       build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
-      constructor_index = convert (bitsizetype, integer_zero_node);
+       bitsize_int (TYPE_VECTOR_SUBPARTS (constructor_type) - 1);
+      constructor_index = bitsize_int (0);
       constructor_unfilled_index = constructor_index;
     }
   else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
@@ -6318,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))
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          /* constructor_max_index needs to be an INTEGER_CST.  Attempts
             to initialize VLAs will cause a proper error; avoid tree
             checking errors as well by setting a safe value.  */
          if (constructor_max_index
              && TREE_CODE (constructor_max_index) != INTEGER_CST)
-           constructor_max_index = build_int_cst (NULL_TREE, -1);
+           constructor_max_index = integer_minus_one_node;
 
          constructor_index
            = convert (bitsizetype,
@@ -6340,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.  */
-         set_nonincremental_init_from_string (value);
+         set_nonincremental_init_from_string (value, braced_init_obstack);
        }
     }
   else
@@ -6364,7 +6964,7 @@ push_init_level (int implicit)
    Otherwise, return a CONSTRUCTOR expression as the value.  */
 
 struct c_expr
-pop_init_level (int implicit)
+pop_init_level (int implicit, struct obstack * braced_init_obstack)
 {
   struct constructor_stack *p;
   struct c_expr ret;
@@ -6377,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)
-       process_init_element (pop_init_level (1), true);
-
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
       gcc_assert (!constructor_range_stack);
     }
 
   /* Now output all pending elements.  */
   constructor_incremental = 1;
-  output_pending_init_elements (1);
+  output_pending_init_elements (1, braced_init_obstack);
 
   p = constructor_stack;
 
@@ -6412,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.  */
-         if (TREE_CHAIN (constructor_fields) != NULL_TREE)
+         if (DECL_CHAIN (constructor_fields) != NULL_TREE)
            constructor_type = NULL_TREE;
        }
     }
@@ -6423,15 +7025,23 @@ pop_init_level (int implicit)
       && TREE_CODE (constructor_type) == RECORD_TYPE
       && constructor_unfilled_fields)
     {
+       bool constructor_zeroinit =
+        (VEC_length (constructor_elt, constructor_elements) == 1
+         && integer_zerop
+             (VEC_index (constructor_elt, constructor_elements, 0)->value));
+
        /* Do not warn for flexible array members or zero-length arrays.  */
        while (constructor_unfilled_fields
               && (!DECL_SIZE (constructor_unfilled_fields)
                   || integer_zerop (DECL_SIZE (constructor_unfilled_fields))))
-         constructor_unfilled_fields = TREE_CHAIN (constructor_unfilled_fields);
-
-       /* Do not warn if this level of the initializer uses member
-          designators; it is likely to be deliberate.  */
-       if (constructor_unfilled_fields && !constructor_designated)
+         constructor_unfilled_fields = DECL_CHAIN (constructor_unfilled_fields);
+
+       if (constructor_unfilled_fields
+           /* Do not warn if this level of the initializer uses member
+              designators; it is likely to be deliberate.  */
+           && !constructor_designated
+           /* Do not warn about initializing with ` = {0}'.  */
+           && !constructor_zeroinit)
          {
            push_member_name (constructor_unfilled_fields);
            warning_init (OPT_Wmissing_field_initializers,
@@ -6525,7 +7135,7 @@ pop_init_level (int implicit)
    ARRAY argument is nonzero for array ranges.  Returns zero for success.  */
 
 static int
-set_designator (int array)
+set_designator (int array, struct obstack * braced_init_obstack)
 {
   tree subtype;
   enum tree_code subcode;
@@ -6547,7 +7157,10 @@ set_designator (int array)
       /* Designator list starts at the level of closest explicit
         braces.  */
       while (constructor_stack->implicit)
-       process_init_element (pop_init_level (1), true);
+       {
+         process_init_element (pop_init_level (1, braced_init_obstack),
+                               true, braced_init_obstack);
+       }
       constructor_designated = 1;
       return 0;
     }
@@ -6580,7 +7193,7 @@ set_designator (int array)
     }
 
   constructor_designated = 1;
-  push_init_level (2);
+  push_init_level (2, braced_init_obstack);
   return 0;
 }
 
@@ -6589,11 +7202,13 @@ set_designator (int array)
    NULL_TREE if there is no range designator at this level.  */
 
 static void
-push_range_stack (tree range_end)
+push_range_stack (tree range_end, struct obstack * braced_init_obstack)
 {
   struct constructor_range_stack *p;
 
-  p = GGC_NEW (struct constructor_range_stack);
+  p = (struct constructor_range_stack *)
+    obstack_alloc (braced_init_obstack,
+                  sizeof (struct constructor_range_stack));
   p->prev = constructor_range_stack;
   p->next = 0;
   p->fields = constructor_fields;
@@ -6611,9 +7226,10 @@ push_range_stack (tree range_end)
    of indices, running from FIRST through LAST.  */
 
 void
-set_init_index (tree first, tree last)
+set_init_index (tree first, tree last,
+               struct obstack * braced_init_obstack)
 {
-  if (set_designator (1))
+  if (set_designator (1, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -6685,18 +7301,18 @@ set_init_index (tree first, tree last)
       designator_depth++;
       designator_erroneous = 0;
       if (constructor_range_stack || last)
-       push_range_stack (last);
+       push_range_stack (last, braced_init_obstack);
     }
 }
 
 /* Within a struct initializer, specify the next field to be initialized.  */
 
 void
-set_init_label (tree fieldname)
+set_init_label (tree fieldname, struct obstack * braced_init_obstack)
 {
-  tree tail;
+  tree field;
 
-  if (set_designator (0))
+  if (set_designator (0, braced_init_obstack))
     return;
 
   designator_erroneous = 1;
@@ -6708,23 +7324,26 @@ set_init_label (tree fieldname)
       return;
     }
 
-  for (tail = TYPE_FIELDS (constructor_type); tail;
-       tail = TREE_CHAIN (tail))
-    {
-      if (DECL_NAME (tail) == fieldname)
-       break;
-    }
+  field = lookup_field (constructor_type, fieldname);
 
-  if (tail == 0)
+  if (field == 0)
     error ("unknown field %qE specified in initializer", fieldname);
   else
-    {
-      constructor_fields = tail;
-      designator_depth++;
-      designator_erroneous = 0;
-      if (constructor_range_stack)
-       push_range_stack (NULL_TREE);
-    }
+    do
+      {
+       constructor_fields = TREE_VALUE (field);
+       designator_depth++;
+       designator_erroneous = 0;
+       if (constructor_range_stack)
+         push_range_stack (NULL_TREE, braced_init_obstack);
+       field = TREE_CHAIN (field);
+       if (field)
+         {
+           if (set_designator (0, braced_init_obstack))
+             return;
+         }
+      }
+    while (field != NULL_TREE);
 }
 \f
 /* Add a new initializer to the tree of pending initializers.  PURPOSE
@@ -6738,7 +7357,8 @@ set_init_label (tree fieldname)
    existing initializer.  */
 
 static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
+add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
+                 struct obstack * braced_init_obstack)
 {
   struct init_node *p, **q, *r;
 
@@ -6797,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;
@@ -6966,7 +7587,7 @@ add_pending_init (tree purpose, tree value, tree origtype, bool implicit)
 /* Build AVL tree from a sorted chain.  */
 
 static void
-set_nonincremental_init (void)
+set_nonincremental_init (struct obstack * braced_init_obstack)
 {
   unsigned HOST_WIDE_INT ix;
   tree index, value;
@@ -6976,7 +7597,10 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    add_pending_init (index, value, NULL_TREE, false);
+    {
+      add_pending_init (index, value, NULL_TREE, false,
+                       braced_init_obstack);
+    }
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -7003,7 +7627,8 @@ set_nonincremental_init (void)
 /* Build AVL tree from a string constant.  */
 
 static void
-set_nonincremental_init_from_string (tree str)
+set_nonincremental_init_from_string (tree str,
+                                    struct obstack * braced_init_obstack)
 {
   tree value, purpose, type;
   HOST_WIDE_INT val[2];
@@ -7066,7 +7691,8 @@ set_nonincremental_init_from_string (tree str)
        }
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value, NULL_TREE, false);
+      add_pending_init (purpose, value, NULL_TREE, false,
+                        braced_init_obstack);
     }
 
   constructor_incremental = 0;
@@ -7076,7 +7702,7 @@ set_nonincremental_init_from_string (tree str)
    not initialized yet.  */
 
 static tree
-find_init_member (tree field)
+find_init_member (tree field, struct obstack * braced_init_obstack)
 {
   struct init_node *p;
 
@@ -7084,7 +7710,7 @@ find_init_member (tree field)
     {
       if (constructor_incremental
          && tree_int_cst_lt (field, constructor_unfilled_index))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
       p = constructor_pending_elts;
       while (p)
@@ -7105,7 +7731,7 @@ find_init_member (tree field)
          && (!constructor_unfilled_fields
              || tree_int_cst_lt (bitpos,
                                  bit_position (constructor_unfilled_fields))))
-       set_nonincremental_init ();
+       set_nonincremental_init (braced_init_obstack);
 
       p = constructor_pending_elts;
       while (p)
@@ -7149,7 +7775,8 @@ find_init_member (tree field)
 
 static void
 output_init_element (tree value, tree origtype, bool strict_string, tree type,
-                    tree field, int pending, bool implicit)
+                    tree field, int pending, bool implicit,
+                    struct obstack * braced_init_obstack)
 {
   tree semantic_type = NULL_TREE;
   constructor_elt *celt;
@@ -7243,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
-                 || TREE_CHAIN (field)))))
+                 || DECL_CHAIN (field)))))
     return;
 
   if (semantic_type)
@@ -7266,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))
-       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
@@ -7281,7 +7909,7 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
       if (constructor_incremental)
        {
          if (!constructor_unfilled_fields)
-           set_nonincremental_init ();
+           set_nonincremental_init (braced_init_obstack);
          else
            {
              tree bitpos, unfillpos;
@@ -7290,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))
-               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
@@ -7329,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
-       = TREE_CHAIN (constructor_unfilled_fields);
+       = DECL_CHAIN (constructor_unfilled_fields);
 
       /* Skip any nameless bit fields.  */
       while (constructor_unfilled_fields != 0
             && DECL_C_BIT_FIELD (constructor_unfilled_fields)
             && DECL_NAME (constructor_unfilled_fields) == 0)
        constructor_unfilled_fields =
-         TREE_CHAIN (constructor_unfilled_fields);
+         DECL_CHAIN (constructor_unfilled_fields);
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE)
     constructor_unfilled_fields = 0;
 
   /* Now output any pending elements which have become next.  */
   if (pending)
-    output_pending_init_elements (0);
+    output_pending_init_elements (0, braced_init_obstack);
 }
 
 /* Output any pending elements which have become next.
@@ -7356,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.  */
-
 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;
@@ -7379,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, 0, false);
+                                constructor_unfilled_index, 0, false,
+                                braced_init_obstack);
          else if (tree_int_cst_lt (constructor_unfilled_index,
                                    elt->purpose))
            {
@@ -7433,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),
-                                  elt->purpose, 0, false);
+                                  elt->purpose, 0, false,
+                                  braced_init_obstack);
            }
          else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
            {
@@ -7504,7 +8134,8 @@ output_pending_init_elements (int all)
    existing initializer.  */
 
 void
-process_init_element (struct c_expr value, bool implicit)
+process_init_element (struct c_expr value, bool implicit,
+                     struct obstack * braced_init_obstack)
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
@@ -7545,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)
-       process_init_element (pop_init_level (1), true);
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
       else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
                || TREE_CODE (constructor_type) == VECTOR_TYPE)
               && (constructor_max_index == 0
                   || tree_int_cst_lt (constructor_max_index,
                                       constructor_index)))
-       process_init_element (pop_init_level (1), true);
+       process_init_element (pop_init_level (1, braced_init_obstack),
+                             true, braced_init_obstack);
       else
        break;
     }
@@ -7601,7 +8234,7 @@ process_init_element (struct c_expr value, bool implicit)
          if (fieldcode == ARRAY_TYPE
              && !require_constant_value
              && TYPE_SIZE (fieldtype) == NULL_TREE
-             && TREE_CHAIN (constructor_fields) == NULL_TREE)
+             && DECL_CHAIN (constructor_fields) == NULL_TREE)
            {
              error_init ("non-static initialization of a flexible array member");
              break;
@@ -7621,7 +8254,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
@@ -7630,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,
-                                  constructor_fields, 1, implicit);
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7648,22 +8282,22 @@ process_init_element (struct c_expr value, bool implicit)
                 it isn't now, so update.  */
              if (constructor_unfilled_fields == constructor_fields)
                {
-                 constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+                 constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
                  /* Skip any nameless bit fields.  */
                  while (constructor_unfilled_fields != 0
                         && DECL_C_BIT_FIELD (constructor_unfilled_fields)
                         && DECL_NAME (constructor_unfilled_fields) == 0)
                    constructor_unfilled_fields =
-                     TREE_CHAIN (constructor_unfilled_fields);
+                     DECL_CHAIN (constructor_unfilled_fields);
                }
            }
 
-         constructor_fields = TREE_CHAIN (constructor_fields);
+         constructor_fields = DECL_CHAIN (constructor_fields);
          /* Skip any nameless bit fields at the beginning.  */
          while (constructor_fields != 0
                 && DECL_C_BIT_FIELD (constructor_fields)
                 && DECL_NAME (constructor_fields) == 0)
-           constructor_fields = TREE_CHAIN (constructor_fields);
+           constructor_fields = DECL_CHAIN (constructor_fields);
        }
       else if (TREE_CODE (constructor_type) == UNION_TYPE)
        {
@@ -7712,7 +8346,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
                       || fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
@@ -7721,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,
-                                  constructor_fields, 1, implicit);
+                                  constructor_fields, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
          else
@@ -7729,7 +8364,7 @@ process_init_element (struct c_expr value, bool implicit)
               directly output as a constructor.  */
            {
              constructor_bit_index = DECL_SIZE (constructor_fields);
-             constructor_unfilled_fields = TREE_CHAIN (constructor_fields);
+             constructor_unfilled_fields = DECL_CHAIN (constructor_fields);
            }
 
          constructor_fields = 0;
@@ -7753,7 +8388,7 @@ process_init_element (struct c_expr value, bool implicit)
                   && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
                       || eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
            {
-             push_init_level (1);
+             push_init_level (1, braced_init_obstack);
              continue;
            }
 
@@ -7772,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,
-                                  constructor_index, 1, implicit);
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
              RESTORE_SPELLING_DEPTH (constructor_depth);
            }
 
@@ -7806,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,
-                                  constructor_index, 1, implicit);
+                                  constructor_index, 1, implicit,
+                                  braced_init_obstack);
            }
 
          constructor_index
@@ -7834,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,
-                                NULL_TREE, 1, implicit);
+                                NULL_TREE, 1, implicit,
+                                braced_init_obstack);
          constructor_fields = 0;
        }
 
@@ -7850,14 +8488,17 @@ process_init_element (struct c_expr value, bool implicit)
          while (constructor_stack != range_stack->stack)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1), true);
+             process_init_element (pop_init_level (1,
+                                                   braced_init_obstack),
+                                   true, braced_init_obstack);
            }
          for (p = range_stack;
               !p->range_end || tree_int_cst_equal (p->index, p->range_end);
               p = p->prev)
            {
              gcc_assert (constructor_stack->implicit);
-             process_init_element (pop_init_level (1), true);
+             process_init_element (pop_init_level (1, braced_init_obstack),
+                                   true, braced_init_obstack);
            }
 
          p->index = size_binop_loc (input_location,
@@ -7877,7 +8518,7 @@ process_init_element (struct c_expr value, bool implicit)
              p = p->next;
              if (!p)
                break;
-             push_init_level (2);
+             push_init_level (2, braced_init_obstack);
              p->stack = constructor_stack;
              if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
                p->index = p->range_start;
@@ -7941,7 +8582,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
         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
@@ -7962,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;
+         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;
@@ -7988,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;
-         }
+           }
+         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;
@@ -8078,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)
        {
-         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;
@@ -8088,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)
-       pedwarn (loc, 0, 
+       pedwarn (loc, 0,
                 "%<return%> with a value, in function returning void");
-      else 
+      else
        pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
@@ -8528,6 +9181,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
 tree
 c_process_expr_stmt (location_t loc, tree expr)
 {
+  tree exprv;
+
   if (!expr)
     return NULL_TREE;
 
@@ -8548,6 +9203,16 @@ c_process_expr_stmt (location_t loc, tree 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))
@@ -8653,11 +9318,13 @@ c_finish_stmt_expr (location_t loc, tree body)
       goto continue_searching;
     }
 
+  if (last == error_mark_node)
+    return last;
+
   /* In the case that the BIND_EXPR is not necessary, return the
      expression out from inside it.  */
-  if (last == error_mark_node
-      || (last == BIND_EXPR_BODY (body)
-         && BIND_EXPR_VARS (body) == NULL))
+  if (last == BIND_EXPR_BODY (body)
+      && BIND_EXPR_VARS (body) == NULL)
     {
       /* Even if this looks constant, do not allow it in a constant
         expression.  */
@@ -8734,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.  */
-  if (cur_stmt_list
+  if (building_stmt_list_p ()
       && STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
       && TREE_CODE (stmt) != BIND_EXPR)
     {
@@ -8765,6 +9432,88 @@ push_cleanup (tree decl, tree cleanup, bool eh_only)
   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.
@@ -8806,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.  */
-  tree real_result_type = NULL;
+  tree semantic_result_type = NULL;
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
@@ -8848,6 +9597,10 @@ build_binary_op (location_t location, enum tree_code code,
      precision.  */
   bool may_need_excess_precision;
 
+  /* True means this is a boolean operation that converts both its
+     operands to truth-values.  */
+  bool boolean_op = false;
+
   if (location == UNKNOWN_LOCATION)
     location = input_location;
 
@@ -8872,7 +9625,10 @@ build_binary_op (location_t location, enum tree_code code,
   else
     int_const = int_const_or_overflow = false;
 
-  if (convert_p)
+  /* Do not apply default conversion in mixed vector/scalar expression.  */
+  if (convert_p
+      && !((TREE_CODE (TREE_TYPE (op0)) == VECTOR_TYPE)
+          != (TREE_CODE (TREE_TYPE (op1)) == VECTOR_TYPE)))
     {
       op0 = default_conversion (op0);
       op1 = default_conversion (op1);
@@ -8944,6 +9700,51 @@ build_binary_op (location_t location, enum tree_code code,
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* In case when one of the operands of the binary operation is
+     a vector and another is a scalar -- convert scalar to vector.  */
+  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
+    {
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
+
+      switch (convert_flag)
+       {
+         case stv_error:
+           return error_mark_node;
+         case stv_firstarg:
+           {
+              bool maybe_const = true;
+              tree sc;
+              sc = c_fully_fold (op0, false, &maybe_const);
+              sc = save_expr (sc);
+              sc = convert (TREE_TYPE (type1), sc);
+              op0 = build_vector_from_val (type1, sc);
+              if (!maybe_const)
+                op0 = c_wrap_maybe_const (op0, true);
+              orig_type0 = type0 = TREE_TYPE (op0);
+              code0 = TREE_CODE (type0);
+              converted = 1;
+              break;
+           }
+         case stv_secondarg:
+           {
+             bool maybe_const = true;
+             tree sc;
+             sc = c_fully_fold (op1, false, &maybe_const);
+             sc = save_expr (sc);
+             sc = convert (TREE_TYPE (type0), sc);
+             op1 = build_vector_from_val (type0, sc);
+             if (!maybe_const)
+               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:
@@ -9075,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;
+         boolean_op = true;
        }
       if (code == TRUTH_ANDIF_EXPR)
        {
@@ -9105,7 +9907,21 @@ build_binary_op (location_t location, enum tree_code code,
         Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9132,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;
-         /* 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;
@@ -9142,7 +9959,21 @@ build_binary_op (location_t location, enum tree_code code,
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+         && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+       {
+         result_type = type0;
+         converted = 1;
+       }
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
          && code1 == INTEGER_TYPE)
        {
          if (TREE_CODE (op1) == INTEGER_CST)
@@ -9164,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;
-         /* 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;
@@ -9175,6 +10007,31 @@ build_binary_op (location_t location, enum tree_code code,
 
     case EQ_EXPR:
     case NE_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
        warning_at (location,
                    OPT_Wfloat_equal,
@@ -9187,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;
+      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+       {
+         if (TREE_CODE (op0) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op0, 0));
+           }
+         result_type = type0;
+       }
+      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+       {
+         if (TREE_CODE (op1) == ADDR_EXPR
+             && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+           {
+             if (code == EQ_EXPR)
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<false%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+             else
+               warning_at (location,
+                           OPT_Waddress,
+                           "the comparison will always evaluate as %<true%> "
+                           "for the address of %qD will never be NULL",
+                           TREE_OPERAND (op1, 0));
+           }
+         result_type = type1;
+       }
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
          tree tt0 = TREE_TYPE (type0);
          tree tt1 = TREE_TYPE (type1);
+         addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
+         addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
+         addr_space_t as_common = ADDR_SPACE_GENERIC;
+
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
          if (comp_target_types (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
          else if (VOID_TYPE_P (tt0))
            {
-             /* op0 != orig_op0 detects the case of something
-                whose value is 0 but which isn't a valid null ptr const.  */
-             if (pedantic && !null_pointer_constant_p (orig_op0)
-                 && TREE_CODE (tt1) == FUNCTION_TYPE)
+             if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
-             if (pedantic && !null_pointer_constant_p (orig_op1)
-                 && TREE_CODE (tt0) == FUNCTION_TYPE)
+             if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
@@ -9219,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)
-           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)
        {
@@ -9255,6 +10144,31 @@ build_binary_op (location_t location, enum tree_code code,
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                          (TYPE_MODE (TREE_TYPE (type0))), 0);
+          result_type = build_opaque_vector_type (intt,
+                                                 TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
           || code0 == FIXED_POINT_TYPE)
@@ -9263,6 +10177,10 @@ build_binary_op (location_t location, enum tree_code code,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
+         addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
+         addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+         addr_space_t as_common;
+
          if (comp_target_types (location, type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
@@ -9273,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 (null_pointer_constant_p (orig_op0)
+                      || null_pointer_constant_p (orig_op1))
+               warning_at (location, OPT_Wextra,
+                           "ordered comparison of pointer with null pointer");
+
+           }
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
            }
          else
            {
-             result_type = ptr_type_node;
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
              pedwarn (location, 0,
                       "comparison of distinct pointer types lacks a cast");
            }
@@ -9285,17 +10216,21 @@ build_binary_op (location_t location, enum tree_code code,
        {
          result_type = type0;
          if (pedantic)
-           pedwarn (location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ordered comparison of pointer with integer zero");
          else if (extra_warnings)
            warning_at (location, OPT_Wextra,
-                    "ordered comparison of pointer with integer zero");
+                       "ordered comparison of pointer with integer zero");
        }
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
-         pedwarn (location, OPT_pedantic, 
-                  "ordered comparison of pointer with integer zero");
+         if (pedantic)
+           pedwarn (location, OPT_pedantic,
+                    "ordered comparison of pointer with integer zero");
+         else if (extra_warnings)
+           warning_at (location, OPT_Wextra,
+                       "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
@@ -9338,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);
+         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;
        }
@@ -9359,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);
-             real_result_type = c_common_type (orig_type0, orig_type1);
+             semantic_result_type = c_common_type (orig_type0, orig_type1);
            }
          if (first_complex)
            {
@@ -9388,6 +10328,7 @@ build_binary_op (location_t location, enum tree_code code,
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = c_save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -9408,6 +10349,7 @@ build_binary_op (location_t location, enum tree_code code,
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = c_save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -9439,7 +10381,7 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten && none_complex)
        {
          final_type = result_type;
-         result_type = shorten_binary_op (result_type, op0, op1, 
+         result_type = shorten_binary_op (result_type, op0, op1,
                                           shorten == -1);
        }
 
@@ -9533,7 +10475,7 @@ build_binary_op (location_t location, enum tree_code code,
                warn_for_sign_compare (location, orig_op0_folded,
                                       orig_op1_folded, op0, op1,
                                       result_type, resultcode);
-             if (!in_late_binary_op)
+             if (!in_late_binary_op && !int_operands)
                {
                  if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
                    op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
@@ -9556,12 +10498,21 @@ build_binary_op (location_t location, enum tree_code code,
       return error_mark_node;
     }
 
+  if (build_type == NULL_TREE)
+    {
+      build_type = result_type;
+      if ((type0 != orig_type0 || type1 != orig_type1)
+         && !boolean_op)
+       {
+         gcc_assert (may_need_excess_precision && common);
+         semantic_result_type = c_common_type (orig_type0, orig_type1);
+       }
+    }
+
   if (!converted)
     {
-      if (TREE_TYPE (op0) != result_type)
-       op0 = convert_and_check (result_type, op0);
-      if (TREE_TYPE (op1) != result_type)
-       op1 = convert_and_check (result_type, op1);
+      op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
+      op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
 
       /* This can happen if one operand has a vector type, and the other
         has a different type.  */
@@ -9569,16 +10520,6 @@ build_binary_op (location_t location, enum tree_code code,
        return error_mark_node;
     }
 
-  if (build_type == NULL_TREE)
-    {
-      build_type = result_type;
-      if (type0 != orig_type0 || type1 != orig_type1)
-       {
-         gcc_assert (may_need_excess_precision && common);
-         real_result_type = c_common_type (orig_type0, orig_type1);
-       }
-    }
-
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
@@ -9599,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);
-  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;
 }
@@ -9628,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;
 
+    case VOID_TYPE:
+      error_at (location, "void value not ignored as it ought to be");
+      return error_mark_node;
+
     case FUNCTION_TYPE:
       gcc_unreachable ();
 
+    case VECTOR_TYPE:
+      error_at (location, "used vector type where scalar is required");
+      return error_mark_node;
+
     default:
       break;
     }
@@ -9640,8 +10589,8 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
   if (int_operands)
     expr = remove_c_maybe_const_expr (expr);
 
-  /* ??? Should we also give an error for void and vectors rather than
-     leaving those to give errors later?  */
+  /* ??? Should we also give an error for vectors rather than leaving
+     those to give errors later?  */
   expr = c_common_truthvalue_conversion (location, expr);
 
   if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
@@ -9795,6 +10744,8 @@ c_finish_omp_clauses (tree clauses)
                case PLUS_EXPR:
                case MULT_EXPR:
                case MINUS_EXPR:
+               case MIN_EXPR:
+               case MAX_EXPR:
                  break;
                case BIT_AND_EXPR:
                  r_name = "&";
@@ -9911,6 +10862,8 @@ c_finish_omp_clauses (tree clauses)
        case OMP_CLAUSE_DEFAULT:
        case OMP_CLAUSE_UNTIED:
        case OMP_CLAUSE_COLLAPSE:
+       case OMP_CLAUSE_FINAL:
+       case OMP_CLAUSE_MERGEABLE:
          pc = &OMP_CLAUSE_CHAIN (c);
          continue;
 
@@ -9940,6 +10893,10 @@ c_finish_omp_clauses (tree clauses)
                case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
                  break;
                case OMP_CLAUSE_DEFAULT_SHARED:
+                 /* const vars may be specified in firstprivate clause.  */
+                 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                     && TREE_READONLY (t))
+                   break;
                  share_name = "shared";
                  break;
                case OMP_CLAUSE_DEFAULT_PRIVATE:
@@ -9968,6 +10925,19 @@ c_finish_omp_clauses (tree clauses)
   return clauses;
 }
 
+/* Create a transaction node.  */
+
+tree
+c_finish_transaction (location_t loc, tree block, int flags)
+{
+  tree stmt = build_stmt (loc, TRANSACTION_EXPR, block);
+  if (flags & TM_STMT_ATTR_OUTER)
+    TRANSACTION_EXPR_OUTER (stmt) = 1;
+  if (flags & TM_STMT_ATTR_RELAXED)
+    TRANSACTION_EXPR_RELAXED (stmt) = 1;
+  return add_stmt (stmt);
+}
+
 /* Make a variant type in the proper way for C/C++, propagating qualifiers
    down to the element type of an array.  */
 
@@ -10006,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))
             {
-              tree unqualified_canon 
+              tree unqualified_canon
                 = build_array_type (TYPE_CANONICAL (element_type),
-                                    domain? TYPE_CANONICAL (domain) 
+                                    domain? TYPE_CANONICAL (domain)
                                           : NULL_TREE);
-              TYPE_CANONICAL (t) 
+              TYPE_CANONICAL (t)
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
           else