OSDN Git Service

PR c/42708
[pf3gnuchains/gcc-fork.git] / gcc / c-typeck.c
index 07d51a4..17bdbf9 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "c-tree.h"
+#include "c-lang.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "output.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "output.h"
@@ -86,7 +87,7 @@ static int type_lists_compatible_p (const_tree, const_tree, bool *);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
 static tree lookup_field (tree, tree);
 static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
                              tree);
-static tree pointer_diff (tree, tree);
+static tree pointer_diff (location_t, tree, tree);
 static tree convert_for_assignment (location_t, tree, tree, tree,
                                    enum impl_conv, bool, tree, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
 static tree convert_for_assignment (location_t, tree, tree, tree,
                                    enum impl_conv, bool, tree, tree, int);
 static tree valid_compound_expr_initializer (tree, tree);
@@ -283,14 +284,55 @@ c_type_promotes_to (tree type)
   return type;
 }
 
   return type;
 }
 
+/* Return true if between two named address spaces, whether there is a superset
+   named address space that encompasses both address spaces.  If there is a
+   superset, return which address space is the superset.  */
+
+static bool
+addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
+{
+  if (as1 == as2)
+    {
+      *common = as1;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as1, as2))
+    {
+      *common = as2;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as2, as1))
+    {
+      *common = as1;
+      return true;
+    }
+  else
+    return false;
+}
+
 /* Return a variant of TYPE which has all the type qualifiers of LIKE
    as well as those of TYPE.  */
 
 static tree
 qualify_type (tree type, tree like)
 {
 /* Return a variant of TYPE which has all the type qualifiers of LIKE
    as well as those of TYPE.  */
 
 static tree
 qualify_type (tree type, tree like)
 {
+  addr_space_t as_type = TYPE_ADDR_SPACE (type);
+  addr_space_t as_like = TYPE_ADDR_SPACE (like);
+  addr_space_t as_common;
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  If there isn't one, raise an error.  */
+  if (!addr_space_superset (as_type, as_like, &as_common))
+    {
+      as_common = as_type;
+      error ("%qT and %qT are in disjoint named address spaces",
+            type, like);
+    }
+
   return c_build_qualified_type (type,
   return c_build_qualified_type (type,
-                                TYPE_QUALS (type) | TYPE_QUALS (like));
+                                TYPE_QUALS_NO_ADDR_SPACE (type)
+                                | TYPE_QUALS_NO_ADDR_SPACE (like)
+                                | ENCODE_QUAL_ADDR_SPACE (as_common));
 }
 
 /* Return true iff the given tree T is a variable length array.  */
 }
 
 /* Return true iff the given tree T is a variable length array.  */
@@ -370,7 +412,8 @@ composite_type (tree t1, tree t2)
        bool t1_complete, t2_complete;
 
        /* We should not have any type quals on arrays at all.  */
        bool t1_complete, t2_complete;
 
        /* We should not have any type quals on arrays at all.  */
-       gcc_assert (!TYPE_QUALS (t1) && !TYPE_QUALS (t2));
+       gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
+                   && !TYPE_QUALS_NO_ADDR_SPACE (t2));
 
        t1_complete = COMPLETE_TYPE_P (t1);
        t2_complete = COMPLETE_TYPE_P (t2);
 
        t1_complete = COMPLETE_TYPE_P (t1);
        t2_complete = COMPLETE_TYPE_P (t2);
@@ -523,7 +566,7 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p2));
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p2));
-                       pedwarn (input_location, OPT_pedantic, 
+                       pedwarn (input_location, OPT_pedantic,
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -548,7 +591,7 @@ composite_type (tree t1, tree t2)
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p1));
                      {
                        TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
                                                         TREE_VALUE (p1));
-                       pedwarn (input_location, OPT_pedantic, 
+                       pedwarn (input_location, OPT_pedantic,
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
                                 "function types not truly compatible in ISO C");
                        goto parm_done;
                      }
@@ -584,6 +627,8 @@ common_pointer_type (tree t1, tree t2)
   tree pointed_to_2, mv2;
   tree target;
   unsigned target_quals;
   tree pointed_to_2, mv2;
   tree target;
   unsigned target_quals;
+  addr_space_t as1, as2, as_common;
+  int quals1, quals2;
 
   /* Save time if the two types are the same.  */
 
 
   /* Save time if the two types are the same.  */
 
@@ -615,10 +660,24 @@ common_pointer_type (tree t1, tree t2)
   /* For function types do not merge const qualifiers, but drop them
      if used inconsistently.  The middle-end uses these to mark const
      and noreturn functions.  */
   /* For function types do not merge const qualifiers, but drop them
      if used inconsistently.  The middle-end uses these to mark const
      and noreturn functions.  */
+  quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
+  quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
+
   if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
   if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
-    target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+    target_quals = (quals1 & quals2);
   else
   else
-    target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+    target_quals = (quals1 | quals2);
+
+  /* If the two named address spaces are different, determine the common
+     superset address space.  This is guaranteed to exist due to the
+     assumption that comp_target_type returned non-zero.  */
+  as1 = TYPE_ADDR_SPACE (pointed_to_1);
+  as2 = TYPE_ADDR_SPACE (pointed_to_2);
+  if (!addr_space_superset (as1, as2, &as_common))
+    gcc_unreachable ();
+
+  target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
+
   t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
   t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
   return build_type_attribute_variant (t1, attributes);
 }
@@ -1102,20 +1161,28 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
   return attrval == 2 && val == 1 ? 2 : val;
 }
 
   return attrval == 2 && val == 1 ? 2 : val;
 }
 
-/* Return 1 if TTL and TTR are pointers to types that are equivalent,
-   ignoring their qualifiers.  */
+/* Return 1 if TTL and TTR are pointers to types that are equivalent, ignoring
+   their qualifiers, except for named address spaces.  If the pointers point to
+   different named addresses, then we must determine if one address space is a
+   subset of the other.  */
 
 static int
 comp_target_types (location_t location, tree ttl, tree ttr)
 {
   int val;
 
 static int
 comp_target_types (location_t location, tree ttl, tree ttr)
 {
   int val;
-  tree mvl, mvr;
+  tree mvl = TREE_TYPE (ttl);
+  tree mvr = TREE_TYPE (ttr);
+  addr_space_t asl = TYPE_ADDR_SPACE (mvl);
+  addr_space_t asr = TYPE_ADDR_SPACE (mvr);
+  addr_space_t as_common;
   bool enum_and_int_p;
 
   bool enum_and_int_p;
 
+  /* Fail if pointers point to incompatible address spaces.  */
+  if (!addr_space_superset (asl, asr, &as_common))
+    return 0;
+
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
   /* Do not lose qualifiers on element types of array types that are
      pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  mvl = TREE_TYPE (ttl);
-  mvr = TREE_TYPE (ttr);
   if (TREE_CODE (mvl) != ARRAY_TYPE)
     mvl = TYPE_MAIN_VARIANT (mvl);
   if (TREE_CODE (mvr) != ARRAY_TYPE)
   if (TREE_CODE (mvl) != ARRAY_TYPE)
     mvl = TYPE_MAIN_VARIANT (mvl);
   if (TREE_CODE (mvr) != ARRAY_TYPE)
@@ -1625,9 +1692,9 @@ c_size_in_bytes (const_tree type)
     }
 
   /* Convert in case a char is more than one unit.  */
     }
 
   /* Convert in case a char is more than one unit.  */
-  return size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
-                    size_int (TYPE_PRECISION (char_type_node)
-                              / BITS_PER_UNIT));
+  return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+                        size_int (TYPE_PRECISION (char_type_node)
+                                  / BITS_PER_UNIT));
 }
 \f
 /* Return either DECL or its known constant value (if it has one).  */
 }
 \f
 /* Return either DECL or its known constant value (if it has one).  */
@@ -2040,7 +2107,7 @@ build_component_ref (location_t loc, tree datum, tree component)
    LOC is the location to use for the generated tree.  */
 
 tree
    LOC is the location to use for the generated tree.  */
 
 tree
-build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
+build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
 {
   tree pointer = default_conversion (ptr);
   tree type = TREE_TYPE (pointer);
 {
   tree pointer = default_conversion (ptr);
   tree type = TREE_TYPE (pointer);
@@ -2098,8 +2165,26 @@ build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
        }
     }
   else if (TREE_CODE (pointer) != ERROR_MARK)
-    error_at (loc,
-             "invalid type argument of %qs (have %qT)", errorstring, type);
+    switch (errstring)
+      {
+         case RO_ARRAY_INDEXING:
+           error_at (loc,
+                     "invalid type argument of array indexing (have %qT)",
+                     type);
+           break;
+         case RO_UNARY_STAR:
+           error_at (loc,
+                     "invalid type argument of unary %<*%> (have %qT)",
+                     type);
+           break;
+         case RO_ARROW:
+           error_at (loc,
+                     "invalid type argument of %<->%> (have %qT)",
+                     type);
+           break;
+         default:
+           gcc_unreachable ();
+      }
   return error_mark_node;
 }
 
   return error_mark_node;
 }
 
@@ -2194,10 +2279,10 @@ build_array_ref (location_t loc, tree array, tree index)
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
          while (TREE_CODE (foo) == COMPONENT_REF)
            foo = TREE_OPERAND (foo, 0);
          if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
-           pedwarn (loc, OPT_pedantic, 
+           pedwarn (loc, OPT_pedantic,
                     "ISO C forbids subscripting %<register%> array");
          else if (!flag_isoc99 && !lvalue_p (foo))
                     "ISO C forbids subscripting %<register%> array");
          else if (!flag_isoc99 && !lvalue_p (foo))
-           pedwarn (loc, OPT_pedantic, 
+           pedwarn (loc, OPT_pedantic,
                     "ISO C90 forbids subscripting non-lvalue array");
        }
 
                     "ISO C90 forbids subscripting non-lvalue array");
        }
 
@@ -2234,7 +2319,7 @@ build_array_ref (location_t loc, tree array, tree index)
 
       return build_indirect_ref
        (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
 
       return build_indirect_ref
        (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
-        "array indexing");
+        RO_ARRAY_INDEXING);
     }
 }
 \f
     }
 }
 \f
@@ -2280,7 +2365,7 @@ build_external_ref (location_t loc, tree id, int fun, tree *type)
     warn_deprecated_use (ref, NULL_TREE);
 
   /* Recursive call does not count as usage.  */
     warn_deprecated_use (ref, NULL_TREE);
 
   /* Recursive call does not count as usage.  */
-  if (ref != current_function_decl) 
+  if (ref != current_function_decl)
     {
       TREE_USED (ref) = 1;
     }
     {
       TREE_USED (ref) = 1;
     }
@@ -2499,7 +2584,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
   tree tem;
   int nargs;
   tree *argarray;
   tree tem;
   int nargs;
   tree *argarray;
-  
+
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -2586,7 +2671,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
       if (VOID_TYPE_P (return_type))
        {
          if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
       if (VOID_TYPE_P (return_type))
        {
          if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
-           pedwarn (input_location, 0,
+           pedwarn (loc, 0,
                     "function with qualified void return type called");
          return trap;
        }
                     "function with qualified void return type called");
          return trap;
        }
@@ -2599,7 +2684,7 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
                                          build_constructor (return_type, 0),
                                          false);
          else
                                          build_constructor (return_type, 0),
                                          false);
          else
-           rhs = fold_convert (return_type, integer_zero_node);
+           rhs = fold_convert_loc (loc, return_type, integer_zero_node);
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
 
          return require_complete_type (build2 (COMPOUND_EXPR, return_type,
                                                trap, rhs));
@@ -2623,23 +2708,24 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params,
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
     {
       if (require_constant_value)
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
     {
       if (require_constant_value)
-       result = fold_build_call_array_initializer (TREE_TYPE (fntype),
-                                                   function, nargs, argarray);
+       result =
+         fold_build_call_array_initializer_loc (loc, TREE_TYPE (fntype),
+                                                function, nargs, argarray);
       else
       else
-       result = fold_build_call_array (TREE_TYPE (fntype),
-                                       function, nargs, argarray);
+       result = fold_build_call_array_loc (loc, TREE_TYPE (fntype),
+                                           function, nargs, argarray);
       if (TREE_CODE (result) == NOP_EXPR
          && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST)
        STRIP_TYPE_NOPS (result);
     }
   else
       if (TREE_CODE (result) == NOP_EXPR
          && TREE_CODE (TREE_OPERAND (result, 0)) == INTEGER_CST)
        STRIP_TYPE_NOPS (result);
     }
   else
-    result = build_call_array (TREE_TYPE (fntype),
-                              function, nargs, argarray);
+    result = build_call_array_loc (loc, TREE_TYPE (fntype),
+                                  function, nargs, argarray);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     {
       if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     {
       if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
-       pedwarn (input_location, 0,
+       pedwarn (loc, 0,
                 "function with qualified void return type called");
       return result;
     }
                 "function with qualified void return type called");
       return result;
     }
@@ -2671,6 +2757,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
 {
   tree typetail, val;
   unsigned int parmnum;
 {
   tree typetail, val;
   unsigned int parmnum;
+  bool error_args = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
   const bool type_generic = fundecl
     && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
   bool type_generic_remove_excess_precision = false;
@@ -2940,6 +3027,8 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
        parmval = default_conversion (val);
 
       VEC_replace (tree, values, parmnum, parmval);
        parmval = default_conversion (val);
 
       VEC_replace (tree, values, parmnum, parmval);
+      if (parmval == error_mark_node)
+       error_args = true;
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
@@ -2953,7 +3042,7 @@ convert_arguments (tree typelist, VEC(tree,gc) *values,
       return -1;
     }
 
       return -1;
     }
 
-  return parmnum;
+  return error_args ? -1 : (int) parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
 }
 \f
 /* This is the entry point used by the parser to build unary operators
@@ -3036,8 +3125,8 @@ parser_build_binary_op (location_t location, enum tree_code code,
     warning_at (location, OPT_Waddress,
                "comparison with string literal results in unspecified behavior");
 
     warning_at (location, OPT_Waddress,
                "comparison with string literal results in unspecified behavior");
 
-  if (TREE_OVERFLOW_P (result.value) 
-      && !TREE_OVERFLOW_P (arg1.value) 
+  if (TREE_OVERFLOW_P (result.value)
+      && !TREE_OVERFLOW_P (arg1.value)
       && !TREE_OVERFLOW_P (arg2.value))
     overflow_warning (location, result.value);
 
       && !TREE_OVERFLOW_P (arg2.value))
     overflow_warning (location, result.value);
 
@@ -3058,19 +3147,51 @@ parser_build_binary_op (location_t location, enum tree_code code,
    The resulting tree has type int.  */
 
 static tree
    The resulting tree has type int.  */
 
 static tree
-pointer_diff (tree op0, tree op1)
+pointer_diff (location_t loc, tree op0, tree op1)
 {
   tree restype = ptrdiff_type_node;
 {
   tree restype = ptrdiff_type_node;
+  tree result, inttype;
 
 
+  addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
+  addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
   tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
   tree target_type = TREE_TYPE (TREE_TYPE (op0));
   tree con0, con1, lit0, lit1;
   tree orig_op1 = op1;
 
+  /* If the operands point into different address spaces, we need to
+     explicitly convert them to pointers into the common address space
+     before we can subtract the numerical address values.  */
+  if (as0 != as1)
+    {
+      addr_space_t as_common;
+      tree common_type;
+
+      /* Determine the common superset address space.  This is guaranteed
+        to exist because the caller verified that comp_target_types
+        returned non-zero.  */
+      if (!addr_space_superset (as0, as1, &as_common))
+       gcc_unreachable ();
+
+      common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+      op0 = convert (common_type, op0);
+      op1 = convert (common_type, op1);
+    }
+
+  /* Determine integer type to perform computations in.  This will usually
+     be the same as the result type (ptrdiff_t), but may need to be a wider
+     type if pointers for the address space are wider than ptrdiff_t.  */
+  if (TYPE_PRECISION (restype) < TYPE_PRECISION (TREE_TYPE (op0)))
+    inttype = lang_hooks.types.type_for_size
+               (TYPE_PRECISION (TREE_TYPE (op0)), 0);
+  else
+    inttype = restype;
+
+
   if (TREE_CODE (target_type) == VOID_TYPE)
   if (TREE_CODE (target_type) == VOID_TYPE)
-    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
             "pointer of type %<void *%> used in subtraction");
   if (TREE_CODE (target_type) == FUNCTION_TYPE)
             "pointer of type %<void *%> used in subtraction");
   if (TREE_CODE (target_type) == FUNCTION_TYPE)
-    pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+    pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
             "pointer to a function used in subtraction");
 
   /* If the conversion to ptrdiff_type does anything like widening or
             "pointer to a function used in subtraction");
 
   /* If the conversion to ptrdiff_type does anything like widening or
@@ -3122,18 +3243,22 @@ pointer_diff (tree op0, tree op1)
      Do not do default conversions on the minus operator
      in case restype is a short type.  */
 
      Do not do default conversions on the minus operator
      in case restype is a short type.  */
 
-  op0 = build_binary_op (input_location,
-                        MINUS_EXPR, convert (restype, op0),
-                        convert (restype, op1), 0);
+  op0 = build_binary_op (loc,
+                        MINUS_EXPR, convert (inttype, op0),
+                        convert (inttype, op1), 0);
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
-    error ("arithmetic on pointer to an incomplete type");
+    error_at (loc, "arithmetic on pointer to an incomplete type");
 
   /* This generates an error if op0 is pointer to incomplete type.  */
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
 
   /* This generates an error if op0 is pointer to incomplete type.  */
   op1 = c_size_in_bytes (target_type);
 
   /* Divide by the size, in easiest possible way.  */
-  return fold_build2 (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
+  result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
+                           op0, convert (inttype, op1));
+
+  /* Convert to final result type if necessary.  */
+  return convert (restype, result);
 }
 \f
 /* Construct and perhaps optimize a tree representation
 }
 \f
 /* Construct and perhaps optimize a tree representation
@@ -3203,7 +3328,7 @@ build_unary_op (location_t location,
        }
       else if (!noconvert)
        arg = default_conversion (arg);
        }
       else if (!noconvert)
        arg = default_conversion (arg);
-      arg = non_lvalue (arg);
+      arg = non_lvalue_loc (location, arg);
       break;
 
     case NEGATE_EXPR:
       break;
 
     case NEGATE_EXPR:
@@ -3230,7 +3355,7 @@ build_unary_op (location_t location,
       else if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
       else if (typecode == COMPLEX_TYPE)
        {
          code = CONJ_EXPR;
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
                   "ISO C does not support %<~%> for complex conjugation");
          if (!noconvert)
            arg = default_conversion (arg);
@@ -3274,7 +3399,7 @@ build_unary_op (location_t location,
          return error_mark_node;
        }
       arg = c_objc_common_truthvalue_conversion (location, arg);
          return error_mark_node;
        }
       arg = c_objc_common_truthvalue_conversion (location, arg);
-      ret = invert_truthvalue (arg);
+      ret = invert_truthvalue_loc (location, arg);
       /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
       if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
        location = EXPR_LOCATION (ret);
       /* If the TRUTH_NOT_EXPR has been folded, reset the location.  */
       if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret))
        location = EXPR_LOCATION (ret);
@@ -3284,7 +3409,8 @@ build_unary_op (location_t location,
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_REALPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1_loc (location,
+                              REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
        ret = arg;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
       else
        ret = arg;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
@@ -3295,9 +3421,11 @@ build_unary_op (location_t location,
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
       if (TREE_CODE (arg) == COMPLEX_CST)
        ret = TREE_IMAGPART (arg);
       else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
-       ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+       ret = fold_build1_loc (location,
+                              IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
       else
       else
-       ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg);
+       ret = omit_one_operand_loc (location, TREE_TYPE (arg),
+                               integer_zero_node, arg);
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
       if (eptype && TREE_CODE (eptype) == COMPLEX_TYPE)
        eptype = TREE_TYPE (eptype);
       goto return_build_unary_op;
@@ -3346,7 +3474,7 @@ build_unary_op (location_t location,
        {
          tree real, imag;
 
        {
          tree real, imag;
 
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
                   "ISO C does not support %<++%> and %<--%> on complex types");
 
          arg = stabilize_reference (arg);
@@ -3397,15 +3525,15 @@ build_unary_op (location_t location,
                     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
                     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
              {
                if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
-                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
                           "wrong type argument to increment");
                else
                           "wrong type argument to increment");
                else
-                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                 pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
                           "wrong type argument to decrement");
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
                           "wrong type argument to decrement");
              }
 
            inc = c_size_in_bytes (TREE_TYPE (argtype));
-           inc = fold_convert (sizetype, inc);
+           inc = fold_convert_loc (location, sizetype, inc);
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
          }
        else if (FRACT_MODE_P (TYPE_MODE (argtype)))
          {
@@ -3475,7 +3603,7 @@ build_unary_op (location_t location,
        {
          /* Don't let this be an lvalue.  */
          if (lvalue_p (TREE_OPERAND (arg, 0)))
        {
          /* Don't let this be an lvalue.  */
          if (lvalue_p (TREE_OPERAND (arg, 0)))
-           return non_lvalue (TREE_OPERAND (arg, 0));
+           return non_lvalue_loc (location, TREE_OPERAND (arg, 0));
          ret = TREE_OPERAND (arg, 0);
          goto return_build_unary_op;
        }
          ret = TREE_OPERAND (arg, 0);
          goto return_build_unary_op;
        }
@@ -3541,10 +3669,11 @@ build_unary_op (location_t location,
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
       if (val && TREE_CODE (val) == INDIRECT_REF
           && TREE_CONSTANT (TREE_OPERAND (val, 0)))
        {
-         tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
+         tree op0 = fold_convert_loc (location, sizetype,
+                                      fold_offsetof (arg, val)), op1;
 
 
-         op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
-         ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+         op1 = fold_convert_loc (location, argtype, TREE_OPERAND (val, 0));
+         ret = fold_build2_loc (location, POINTER_PLUS_EXPR, argtype, op1, op0);
          goto return_build_unary_op;
        }
 
          goto return_build_unary_op;
        }
 
@@ -3561,8 +3690,8 @@ build_unary_op (location_t location,
     argtype = TREE_TYPE (arg);
   if (TREE_CODE (arg) == INTEGER_CST)
     ret = (require_constant_value
     argtype = TREE_TYPE (arg);
   if (TREE_CODE (arg) == INTEGER_CST)
     ret = (require_constant_value
-          ? fold_build1_initializer (code, argtype, arg)
-          : fold_build1 (code, argtype, arg));
+          ? fold_build1_initializer_loc (location, code, argtype, arg)
+          : fold_build1_loc (location, code, argtype, arg));
   else
     ret = build1 (code, argtype, arg);
  return_build_unary_op:
   else
     ret = build1 (code, argtype, arg);
  return_build_unary_op:
@@ -3770,7 +3899,8 @@ c_mark_addressable (tree exp)
 
 tree
 build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
 
 tree
 build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
-                       tree op1, tree op2)
+                       tree op1, tree op1_original_type, tree op2,
+                       tree op2_original_type)
 {
   tree type1;
   tree type2;
 {
   tree type1;
   tree type2;
@@ -3843,6 +3973,20 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
        }
     }
 
        }
     }
 
+  if (warn_cxx_compat)
+    {
+      tree t1 = op1_original_type ? op1_original_type : TREE_TYPE (orig_op1);
+      tree t2 = op2_original_type ? op2_original_type : TREE_TYPE (orig_op2);
+
+      if (TREE_CODE (t1) == ENUMERAL_TYPE
+         && TREE_CODE (t2) == ENUMERAL_TYPE
+         && TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
+       warning_at (colon_loc, OPT_Wc___compat,
+                   ("different enum types in conditional is "
+                    "invalid in C++: %qT vs %qT"),
+                   t1, t2);
+    }
+
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
@@ -3891,10 +4035,19 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                     that folding in this case even without
                     warn_sign_compare to avoid warning options
                     possibly affecting code generation.  */
                     that folding in this case even without
                     warn_sign_compare to avoid warning options
                     possibly affecting code generation.  */
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_false_node);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_false_node);
+
+                 c_inhibit_evaluation_warnings
+                   += (ifexp == truthvalue_true_node);
                  op2 = c_fully_fold (op2, require_constant_value,
                                      &op2_maybe_const);
                  op2 = c_fully_fold (op2, require_constant_value,
                                      &op2_maybe_const);
+                 c_inhibit_evaluation_warnings
+                   -= (ifexp == truthvalue_true_node);
 
                  if (warn_sign_compare)
                    {
 
                  if (warn_sign_compare)
                    {
@@ -3909,17 +4062,9 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                                     "conditional expression"));
                    }
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
                                     "conditional expression"));
                    }
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-                   {
-                     op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1),
-                                   NULL, op1);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const;
-                   }
+                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
                  if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST)
                  if (!op2_maybe_const || TREE_CODE (op2) != INTEGER_CST)
-                   {
-                     op2 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op2),
-                                   NULL, op2);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op2) = !op2_maybe_const;
-                   }
+                   op2 = c_wrap_maybe_const (op2, !op2_maybe_const);
                }
            }
        }
                }
            }
        }
@@ -3933,12 +4078,22 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
     }
   else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
     {
+      addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+      addr_space_t as2 = TYPE_ADDR_SPACE (TREE_TYPE (type2));
+      addr_space_t as_common;
+
       if (comp_target_types (colon_loc, type1, type2))
        result_type = common_pointer_type (type1, type2);
       else if (null_pointer_constant_p (orig_op1))
       if (comp_target_types (colon_loc, type1, type2))
        result_type = common_pointer_type (type1, type2);
       else if (null_pointer_constant_p (orig_op1))
-       result_type = qualify_type (type2, type1);
+       result_type = type2;
       else if (null_pointer_constant_p (orig_op2))
       else if (null_pointer_constant_p (orig_op2))
-       result_type = qualify_type (type1, type2);
+       result_type = type1;
+      else if (!addr_space_superset (as1, as2, &as_common))
+       {
+         error_at (colon_loc, "pointers to disjoint address spaces "
+                   "used in conditional expression");
+         return error_mark_node;
+       }
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
       else if (VOID_TYPE_P (TREE_TYPE (type1)))
        {
          if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
@@ -3959,10 +4114,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
        }
       else
        {
        }
       else
        {
+         int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+
          if (!objc_ok)
            pedwarn (colon_loc, 0,
                     "pointer type mismatch in conditional expression");
          if (!objc_ok)
            pedwarn (colon_loc, 0,
                     "pointer type mismatch in conditional expression");
-         result_type = build_pointer_type (void_type_node);
+         result_type = build_pointer_type
+                         (build_qualified_type (void_type_node, qual));
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
        }
     }
   else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
@@ -4002,12 +4160,12 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
   /* Merge const and volatile flags of the incoming types.  */
   result_type
     = build_type_variant (result_type,
   /* Merge const and volatile flags of the incoming types.  */
   result_type
     = build_type_variant (result_type,
-                         TREE_READONLY (op1) || TREE_READONLY (op2),
-                         TREE_THIS_VOLATILE (op1) || TREE_THIS_VOLATILE (op2));
+                         TYPE_READONLY (type1) || TYPE_READONLY (type2),
+                         TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
 
 
-  if (result_type != TREE_TYPE (op1))
+  if (result_type != type1)
     op1 = convert_and_check (result_type, op1);
     op1 = convert_and_check (result_type, op1);
-  if (result_type != TREE_TYPE (op2))
+  if (result_type != type2)
     op2 = convert_and_check (result_type, op2);
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
     op2 = convert_and_check (result_type, op2);
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
@@ -4033,7 +4191,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                       && !TREE_OVERFLOW (orig_op2)));
     }
   if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
                       && !TREE_OVERFLOW (orig_op2)));
     }
   if (int_const || (ifexp_bcp && TREE_CODE (ifexp) == INTEGER_CST))
-    ret = fold_build3 (COND_EXPR, result_type, ifexp, op1, op2);
+    ret = fold_build3_loc (colon_loc, COND_EXPR, result_type, ifexp, op1, op2);
   else
     {
       ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
   else
     {
       ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
@@ -4089,7 +4247,7 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
                   && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
                   && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
            ; /* (void) a, (void) b, c */
          else
-           warning_at (loc, OPT_Wunused_value, 
+           warning_at (loc, OPT_Wunused_value,
                        "left-hand operand of comma expression has no effect");
        }
     }
                        "left-hand operand of comma expression has no effect");
        }
     }
@@ -4121,7 +4279,8 @@ 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
 /* 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.  */
+   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)
 
 static void
 handle_warn_cast_qual (tree type, tree otype)
@@ -4147,9 +4306,11 @@ handle_warn_cast_qual (tree type, tree otype)
         taken away.  */
       if (TREE_CODE (in_otype) == FUNCTION_TYPE
          && TREE_CODE (in_type) == FUNCTION_TYPE)
         taken away.  */
       if (TREE_CODE (in_otype) == FUNCTION_TYPE
          && TREE_CODE (in_type) == FUNCTION_TYPE)
-       added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+       added |= (TYPE_QUALS_NO_ADDR_SPACE (in_type)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (in_otype));
       else
       else
-       discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+       discarded |= (TYPE_QUALS_NO_ADDR_SPACE (in_otype)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (in_type));
     }
   while (TREE_CODE (in_type) == POINTER_TYPE
         && TREE_CODE (in_otype) == POINTER_TYPE);
     }
   while (TREE_CODE (in_type) == POINTER_TYPE
         && TREE_CODE (in_otype) == POINTER_TYPE);
@@ -4205,7 +4366,7 @@ handle_warn_cast_qual (tree type, tree otype)
   while (TREE_CODE (in_type) == POINTER_TYPE);
 }
 
   while (TREE_CODE (in_type) == POINTER_TYPE);
 }
 
-/* Build an expression representing a cast to type TYPE of expression EXPR.  
+/* Build an expression representing a cast to type TYPE of expression EXPR.
    LOC is the location of the cast-- typically the open paren of the cast.  */
 
 tree
    LOC is the location of the cast-- typically the open paren of the cast.  */
 
 tree
@@ -4252,7 +4413,7 @@ build_c_cast (location_t loc, tree type, tree expr)
     {
       if (TREE_CODE (type) == RECORD_TYPE
          || TREE_CODE (type) == UNION_TYPE)
     {
       if (TREE_CODE (type) == RECORD_TYPE
          || TREE_CODE (type) == UNION_TYPE)
-       pedwarn (loc, OPT_pedantic, 
+       pedwarn (loc, OPT_pedantic,
                 "ISO C forbids casting nonscalar to the same type");
     }
   else if (TREE_CODE (type) == UNION_TYPE)
                 "ISO C forbids casting nonscalar to the same type");
     }
   else if (TREE_CODE (type) == UNION_TYPE)
@@ -4268,10 +4429,14 @@ build_c_cast (location_t loc, tree type, tree expr)
       if (field)
        {
          tree t;
       if (field)
        {
          tree t;
+         bool maybe_const = true;
 
          pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type");
 
          pedwarn (loc, OPT_pedantic, "ISO C forbids casts to union type");
-         t = digest_init (loc, type,
-                          build_constructor_single (type, field, value),
+         t = c_fully_fold (value, false, &maybe_const);
+         t = build_constructor_single (type, field, t);
+         if (!maybe_const)
+           t = c_wrap_maybe_const (t, true);
+         t = digest_init (loc, type, t,
                           NULL_TREE, false, true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          return t;
                           NULL_TREE, false, true, 0);
          TREE_CONSTANT (t) = TREE_CONSTANT (value);
          return t;
@@ -4298,6 +4463,36 @@ build_c_cast (location_t loc, tree type, tree expr)
          && TREE_CODE (otype) == POINTER_TYPE)
        handle_warn_cast_qual (type, otype);
 
          && TREE_CODE (otype) == POINTER_TYPE)
        handle_warn_cast_qual (type, otype);
 
+      /* Warn about conversions between pointers to disjoint
+        address spaces.  */
+      if (TREE_CODE (type) == POINTER_TYPE
+         && TREE_CODE (otype) == POINTER_TYPE
+         && !null_pointer_constant_p (value))
+       {
+         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
          && TREE_CODE (type) == POINTER_TYPE
       /* Warn about possible alignment problems.  */
       if (STRICT_ALIGNMENT
          && TREE_CODE (type) == POINTER_TYPE
@@ -4387,7 +4582,7 @@ build_c_cast (location_t loc, tree type, tree expr)
 
   /* Don't let a cast be an lvalue.  */
   if (value == expr)
 
   /* Don't let a cast be an lvalue.  */
   if (value == expr)
-    value = non_lvalue (value);
+    value = non_lvalue_loc (loc, value);
 
   /* Don't allow the results of casting to floating-point or complex
      types be confused with actual constants, or casts involving
 
   /* Don't allow the results of casting to floating-point or complex
      types be confused with actual constants, or casts involving
@@ -4460,7 +4655,7 @@ c_cast_expr (location_t loc, struct c_type_name *type_name, tree expr)
 
 tree
 build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
 
 tree
 build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
-                  enum tree_code modifycode, 
+                  enum tree_code modifycode,
                   location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
                   location_t rhs_loc, tree rhs, tree rhs_origtype)
 {
   tree result;
@@ -4892,7 +5087,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                     certain things, it is okay to use a const or volatile
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
                     certain things, it is okay to use a const or volatile
                     function where an ordinary one is wanted, but not
                     vice-versa.  */
-                 if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+                 if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+                     & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
                    WARN_FOR_ASSIGNMENT (location, 0,
                                         G_("passing argument %d of %qE "
                                            "makes qualified function "
                    WARN_FOR_ASSIGNMENT (location, 0,
                                         G_("passing argument %d of %qE "
                                            "makes qualified function "
@@ -4906,7 +5102,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                                         G_("return makes qualified function "
                                            "pointer from unqualified"));
                }
                                         G_("return makes qualified function "
                                            "pointer from unqualified"));
                }
-             else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+             else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                WARN_FOR_ASSIGNMENT (location, 0,
                                     G_("passing argument %d of %qE discards "
                                        "qualifiers from pointer target type"),
                WARN_FOR_ASSIGNMENT (location, 0,
                                     G_("passing argument %d of %qE discards "
                                        "qualifiers from pointer target type"),
@@ -4921,10 +5118,10 @@ convert_for_assignment (location_t location, tree type, tree rhs,
            }
 
          if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
            }
 
          if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
-           pedwarn (location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ISO C prohibits argument conversion to union type");
 
                     "ISO C prohibits argument conversion to union type");
 
-         rhs = fold_convert (TREE_TYPE (memb), rhs);
+         rhs = fold_convert_loc (location, TREE_TYPE (memb), rhs);
          return build_constructor_single (type, memb, rhs);
        }
     }
          return build_constructor_single (type, memb, rhs);
        }
     }
@@ -4939,6 +5136,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
       tree mvr = ttr;
       bool is_opaque_pointer;
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
       tree mvr = ttr;
       bool is_opaque_pointer;
       int target_cmp = 0;   /* Cache comp_target_types () result.  */
+      addr_space_t asl;
+      addr_space_t asr;
 
       if (TREE_CODE (mvl) != ARRAY_TYPE)
        mvl = TYPE_MAIN_VARIANT (mvl);
 
       if (TREE_CODE (mvl) != ARRAY_TYPE)
        mvl = TYPE_MAIN_VARIANT (mvl);
@@ -4959,6 +5158,36 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                    "request for implicit conversion "
                    "from %qT to %qT not permitted in C++", rhstype, type);
 
                    "request for implicit conversion "
                    "from %qT to %qT not permitted in C++", rhstype, type);
 
+      /* See if the pointers point to incompatible address spaces.  */
+      asl = TYPE_ADDR_SPACE (ttl);
+      asr = TYPE_ADDR_SPACE (ttr);
+      if (!null_pointer_constant_p (rhs)
+         && asr != asl && !targetm.addr_space.subset_p (asr, asl))
+       {
+         switch (errtype)
+           {
+           case ic_argpass:
+             error_at (location, "passing argument %d of %qE from pointer to "
+                       "non-enclosed address space", parmnum, rname);
+             break;
+           case ic_assign:
+             error_at (location, "assignment from pointer to "
+                       "non-enclosed address space");
+             break;
+           case ic_init:
+             error_at (location, "initialization from pointer to "
+                       "non-enclosed address space");
+             break;
+           case ic_return:
+             error_at (location, "return from pointer to "
+                       "non-enclosed address space");
+             break;
+           default:
+             gcc_unreachable ();
+           }
+         return error_mark_node;
+       }
+
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
       if (warn_missing_format_attribute
       /* Check if the right-hand side has a format attribute but the
         left-hand side doesn't.  */
       if (warn_missing_format_attribute
@@ -5022,7 +5251,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
-             if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
+             if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
                {
                  /* Types differing only by the presence of the 'volatile'
                     qualifier are acceptable if the 'volatile' has been added
                {
                  /* Types differing only by the presence of the 'volatile'
                     qualifier are acceptable if the 'volatile' has been added
@@ -5062,7 +5292,8 @@ convert_for_assignment (location_t location, tree type, tree rhs,
                 that say the function will not do certain things,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
                 that say the function will not do certain things,
                 it is okay to use a const or volatile function
                 where an ordinary one is wanted, but not vice-versa.  */
-             if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
+             if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
                WARN_FOR_ASSIGNMENT (location, 0,
                                     G_("passing argument %d of %qE makes "
                                        "qualified function pointer "
                WARN_FOR_ASSIGNMENT (location, 0,
                                     G_("passing argument %d of %qE makes "
                                        "qualified function pointer "
@@ -5226,7 +5457,7 @@ store_init_value (location_t init_loc, tree decl, tree init, tree origtype)
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
   STRIP_TYPE_NOPS (value);
 
   /* ANSI wants warnings about out-of-range constant initializers.  */
   STRIP_TYPE_NOPS (value);
-  if (TREE_STATIC (decl)) 
+  if (TREE_STATIC (decl))
     constant_expression_warning (value);
 
   /* Check if we need to set array size from compound literal size.  */
     constant_expression_warning (value);
 
   /* Check if we need to set array size from compound literal size.  */
@@ -5411,7 +5642,7 @@ pedwarn_init (location_t location, int opt, const char *msgid)
     pedwarn (location, opt, "(near initialization for %qs)", 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
 
    OPT is the OPT_W* value corresponding to the warning option that
    controls this warning.  MSGID identifies the message.  The
@@ -5439,7 +5670,7 @@ maybe_warn_string_init (tree type, struct c_expr expr)
       && TREE_CODE (type) == ARRAY_TYPE
       && TREE_CODE (expr.value) == STRING_CST
       && expr.original_code != STRING_CST)
       && TREE_CODE (type) == ARRAY_TYPE
       && TREE_CODE (expr.value) == STRING_CST
       && expr.original_code != STRING_CST)
-    pedwarn_init (input_location, OPT_pedantic, 
+    pedwarn_init (input_location, OPT_pedantic,
                  "array initialized from parenthesized string constant");
 }
 
                  "array initialized from parenthesized string constant");
 }
 
@@ -5546,16 +5777,26 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
              && TYPE_SIZE (type) != 0
          TREE_TYPE (inside_init) = type;
          if (TYPE_DOMAIN (type) != 0
              && TYPE_SIZE (type) != 0
-             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+             && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+           {
+             unsigned HOST_WIDE_INT len = TREE_STRING_LENGTH (inside_init);
+
              /* Subtract the size of a single (possibly wide) character
                 because it's ok to ignore the terminating null char
                 that is counted in the length of the constant.  */
              /* Subtract the size of a single (possibly wide) character
                 because it's ok to ignore the terminating null char
                 that is counted in the length of the constant.  */
-             && 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
-                                      TREE_STRING_LENGTH (inside_init)
-                                      - (TYPE_PRECISION (typ1)
-                                         / BITS_PER_UNIT)))
-           pedwarn_init (init_loc, 0, 
-                         "initializer-string for array of chars is too long");
+             if (0 > compare_tree_int (TYPE_SIZE_UNIT (type),
+                                       (len
+                                        - (TYPE_PRECISION (typ1)
+                                           / BITS_PER_UNIT))))
+               pedwarn_init (init_loc, 0,
+                             ("initializer-string for array of chars "
+                              "is too long"));
+             else if (warn_cxx_compat
+                      && 0 > compare_tree_int (TYPE_SIZE_UNIT (type), len))
+               warning_at (init_loc, OPT_Wc___compat,
+                           ("initializer-string for array chars "
+                            "is too long for C++"));
+           }
 
          return inside_init;
        }
 
          return inside_init;
        }
@@ -7291,8 +7532,8 @@ output_init_element (tree value, tree origtype, bool strict_string, tree type,
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     constructor_unfilled_index
   /* Advance the variable that indicates sequential elements output.  */
   if (TREE_CODE (constructor_type) == ARRAY_TYPE)
     constructor_unfilled_index
-      = size_binop (PLUS_EXPR, constructor_unfilled_index,
-                   bitsize_one_node);
+      = size_binop_loc (input_location, PLUS_EXPR, constructor_unfilled_index,
+                       bitsize_one_node);
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
   else if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
       constructor_unfilled_fields
@@ -7607,9 +7848,9 @@ process_init_element (struct c_expr value, bool implicit)
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
                constructor_bit_index
              /* For a record, keep track of end position of last field.  */
              if (DECL_SIZE (constructor_fields))
                constructor_bit_index
-                 = size_binop (PLUS_EXPR,
-                               bit_position (constructor_fields),
-                               DECL_SIZE (constructor_fields));
+                 = size_binop_loc (input_location, PLUS_EXPR,
+                                   bit_position (constructor_fields),
+                                   DECL_SIZE (constructor_fields));
 
              /* If the current field was the first one not yet written out,
                 it isn't now, so update.  */
 
              /* If the current field was the first one not yet written out,
                 it isn't now, so update.  */
@@ -7744,7 +7985,8 @@ process_init_element (struct c_expr value, bool implicit)
            }
 
          constructor_index
            }
 
          constructor_index
-           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+           = size_binop_loc (input_location, PLUS_EXPR,
+                             constructor_index, bitsize_one_node);
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
@@ -7776,7 +8018,8 @@ process_init_element (struct c_expr value, bool implicit)
            }
 
          constructor_index
            }
 
          constructor_index
-           = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
+           = size_binop_loc (input_location,
+                             PLUS_EXPR, constructor_index, bitsize_one_node);
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
 
          if (!value.value)
            /* If we are doing the bookkeeping for an element that was
@@ -7825,7 +8068,8 @@ process_init_element (struct c_expr value, bool implicit)
              process_init_element (pop_init_level (1), true);
            }
 
              process_init_element (pop_init_level (1), true);
            }
 
-         p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
+         p->index = size_binop_loc (input_location,
+                                    PLUS_EXPR, p->index, bitsize_one_node);
          if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
            finish = 1;
 
          if (tree_int_cst_equal (p->index, p->range_end) && !p->prev)
            finish = 1;
 
@@ -7876,7 +8120,7 @@ build_asm_stmt (tree cv_qualifier, tree args)
    are subtly different.  We use a ASM_EXPR node to represent this.  */
 tree
 build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
    are subtly different.  We use a ASM_EXPR node to represent this.  */
 tree
 build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
-               tree clobbers, bool simple)
+               tree clobbers, tree labels, bool simple)
 {
   tree tail;
   tree args;
 {
   tree tail;
   tree args;
@@ -7890,7 +8134,7 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
   noutputs = list_length (outputs);
   oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
 
   noutputs = list_length (outputs);
   oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
 
-  string = resolve_asm_operand_names (string, outputs, inputs);
+  string = resolve_asm_operand_names (string, outputs, inputs, labels);
 
   /* Remove output conversions that change the type but not the mode.  */
   for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
 
   /* Remove output conversions that change the type but not the mode.  */
   for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
@@ -7960,7 +8204,11 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
       TREE_VALUE (tail) = input;
     }
 
       TREE_VALUE (tail) = input;
     }
 
-  args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers);
+  /* ASMs with labels cannot have outputs.  This should have been
+     enforced by the parser.  */
+  gcc_assert (outputs == NULL || labels == NULL);
+
+  args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
 
   /* asm statements without outputs, including simple ones, are treated
      as volatile.  */
 
   /* asm statements without outputs, including simple ones, are treated
      as volatile.  */
@@ -8038,7 +8286,7 @@ c_finish_return (location_t loc, tree retval, tree origtype)
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
        {
       if ((warn_return_type || flag_isoc99)
          && valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
        {
-         pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type, 
+         pedwarn_c99 (loc, flag_isoc99 ? 0 : OPT_Wreturn_type,
                       "%<return%> with no value, in "
                       "function returning non-void");
          no_warning = true;
                       "%<return%> with no value, in "
                       "function returning non-void");
          no_warning = true;
@@ -8048,9 +8296,9 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
     {
       current_function_returns_null = 1;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
-       pedwarn (loc, 0, 
+       pedwarn (loc, 0,
                 "%<return%> with a value, in function returning void");
                 "%<return%> with a value, in function returning void");
-      else 
+      else
        pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
        pedwarn (loc, OPT_pedantic, "ISO C forbids "
                 "%<return%> with expression, in function returning void");
     }
@@ -8332,9 +8580,8 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
     found:
 
       if (COND_EXPR_ELSE (inner_if))
     found:
 
       if (COND_EXPR_ELSE (inner_if))
-        warning (OPT_Wparentheses,
-                 "%Hsuggest explicit braces to avoid ambiguous %<else%>",
-                 &if_locus);
+        warning_at (if_locus, OPT_Wparentheses,
+                    "suggest explicit braces to avoid ambiguous %<else%>");
     }
 
   stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
     }
 
   stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
@@ -8392,11 +8639,12 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
            }
 
          t = build_and_jump (&blab);
            }
 
          t = build_and_jump (&blab);
-         exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
          if (cond_is_first)
          if (cond_is_first)
-           SET_EXPR_LOCATION (exit, start_locus);
+           exit = fold_build3_loc (start_locus,
+                               COND_EXPR, void_type_node, cond, exit, t);
          else
          else
-           SET_EXPR_LOCATION (exit, input_location);
+           exit = fold_build3_loc (input_location,
+                               COND_EXPR, void_type_node, cond, exit, t);
        }
 
       add_stmt (top);
        }
 
       add_stmt (top);
@@ -8613,16 +8861,17 @@ c_finish_stmt_expr (location_t loc, tree body)
       goto continue_searching;
     }
 
       goto continue_searching;
     }
 
+  if (last == error_mark_node)
+    return last;
+
   /* In the case that the BIND_EXPR is not necessary, return the
      expression out from inside it.  */
   /* In the case that the BIND_EXPR is not necessary, return the
      expression out from inside it.  */
-  if (last == error_mark_node
-      || (last == BIND_EXPR_BODY (body)
-         && BIND_EXPR_VARS (body) == NULL))
+  if (last == BIND_EXPR_BODY (body)
+      && BIND_EXPR_VARS (body) == NULL)
     {
       /* Even if this looks constant, do not allow it in a constant
         expression.  */
     {
       /* Even if this looks constant, do not allow it in a constant
         expression.  */
-      last = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (last), NULL_TREE, last);
-      C_MAYBE_CONST_EXPR_NON_CONST (last) = 1;
+      last = c_wrap_maybe_const (last, true);
       /* Do not warn if the return value of a statement expression is
         unused.  */
       TREE_NO_WARNING (last) = 1;
       /* Do not warn if the return value of a statement expression is
         unused.  */
       TREE_NO_WARNING (last) = 1;
@@ -8650,7 +8899,7 @@ c_finish_stmt_expr (location_t loc, tree body)
     val = TREE_OPERAND (val, 0);
 
   *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
     val = TREE_OPERAND (val, 0);
 
   *last_p = build2 (MODIFY_EXPR, void_type_node, tmp, val);
-  SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
+  SET_EXPR_LOCATION (*last_p, EXPR_LOCATION (last));
 
   {
     tree t = build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
 
   {
     tree t = build4 (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
@@ -8911,12 +9160,12 @@ build_binary_op (location_t location, enum tree_code code,
       /* Handle the pointer + int case.  */
       if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
       /* Handle the pointer + int case.  */
       if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (PLUS_EXPR, op0, op1);
+         ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
          goto return_build_binary_op;
        }
       else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
        {
          goto return_build_binary_op;
        }
       else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (PLUS_EXPR, op1, op0);
+         ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
          goto return_build_binary_op;
        }
       else
          goto return_build_binary_op;
        }
       else
@@ -8929,13 +9178,13 @@ build_binary_op (location_t location, enum tree_code code,
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
          && comp_target_types (location, type0, type1))
        {
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
          && comp_target_types (location, type0, type1))
        {
-         ret = pointer_diff (op0, op1);
+         ret = pointer_diff (location, op0, op1);
          goto return_build_binary_op;
        }
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
          goto return_build_binary_op;
        }
       /* Handle pointer minus int.  Just like pointer plus int.  */
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
        {
-         ret = pointer_int_sum (MINUS_EXPR, op0, op1);
+         ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
          goto return_build_binary_op;
        }
       else
          goto return_build_binary_op;
        }
       else
@@ -9152,24 +9401,34 @@ build_binary_op (location_t location, enum tree_code code,
        {
          tree tt0 = TREE_TYPE (type0);
          tree tt1 = TREE_TYPE (type1);
        {
          tree tt0 = TREE_TYPE (type0);
          tree tt1 = TREE_TYPE (type1);
+         addr_space_t as0 = TYPE_ADDR_SPACE (tt0);
+         addr_space_t as1 = TYPE_ADDR_SPACE (tt1);
+         addr_space_t as_common = ADDR_SPACE_GENERIC;
+
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
          if (comp_target_types (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
          /* Anything compares with void *.  void * compares with anything.
             Otherwise, the targets must be compatible
             and both must be object or both incomplete.  */
          if (comp_target_types (location, type0, type1))
            result_type = common_pointer_type (type0, type1);
+         else if (null_pointer_constant_p (orig_op0))
+           result_type = type1;
+         else if (null_pointer_constant_p (orig_op1))
+           result_type = type0;
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
          else if (VOID_TYPE_P (tt0))
            {
          else if (VOID_TYPE_P (tt0))
            {
-             /* op0 != orig_op0 detects the case of something
-                whose value is 0 but which isn't a valid null ptr const.  */
-             if (pedantic && !null_pointer_constant_p (orig_op0)
-                 && TREE_CODE (tt1) == FUNCTION_TYPE)
+             if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
          else if (VOID_TYPE_P (tt1))
            {
-             if (pedantic && !null_pointer_constant_p (orig_op1)
-                 && TREE_CODE (tt0) == FUNCTION_TYPE)
+             if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "comparison of %<void *%> with function pointer");
            }
@@ -9180,7 +9439,11 @@ build_binary_op (location_t location, enum tree_code code,
                       "comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
                       "comparison of distinct pointer types lacks a cast");
 
          if (result_type == NULL_TREE)
-           result_type = ptr_type_node;
+           {
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
+           }
        }
       else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
        }
       else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
        {
@@ -9224,6 +9487,10 @@ build_binary_op (location_t location, enum tree_code code,
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
        short_compare = 1;
       else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
        {
+         addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (type0));
+         addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (type1));
+         addr_space_t as_common;
+
          if (comp_target_types (location, type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
          if (comp_target_types (location, type0, type1))
            {
              result_type = common_pointer_type (type0, type1);
@@ -9235,9 +9502,17 @@ build_binary_op (location_t location, enum tree_code code,
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "ordered comparisons of pointers to functions");
            }
                pedwarn (location, OPT_pedantic, "ISO C forbids "
                         "ordered comparisons of pointers to functions");
            }
+         else if (!addr_space_superset (as0, as1, &as_common))
+           {
+             error_at (location, "comparison of pointers to "
+                       "disjoint address spaces");
+             return error_mark_node;
+           }
          else
            {
          else
            {
-             result_type = ptr_type_node;
+             int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
+             result_type = build_pointer_type
+                             (build_qualified_type (void_type_node, qual));
              pedwarn (location, 0,
                       "comparison of distinct pointer types lacks a cast");
            }
              pedwarn (location, 0,
                       "comparison of distinct pointer types lacks a cast");
            }
@@ -9246,7 +9521,7 @@ build_binary_op (location_t location, enum tree_code code,
        {
          result_type = type0;
          if (pedantic)
        {
          result_type = type0;
          if (pedantic)
-           pedwarn (location, OPT_pedantic, 
+           pedwarn (location, OPT_pedantic,
                     "ordered comparison of pointer with integer zero");
          else if (extra_warnings)
            warning_at (location, OPT_Wextra,
                     "ordered comparison of pointer with integer zero");
          else if (extra_warnings)
            warning_at (location, OPT_Wextra,
@@ -9255,7 +9530,7 @@ build_binary_op (location_t location, enum tree_code code,
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
       else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
        {
          result_type = type1;
-         pedwarn (location, OPT_pedantic, 
+         pedwarn (location, OPT_pedantic,
                   "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
                   "ordered comparison of pointer with integer zero");
        }
       else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
@@ -9400,7 +9675,7 @@ build_binary_op (location_t location, enum tree_code code,
       if (shorten && none_complex)
        {
          final_type = result_type;
       if (shorten && none_complex)
        {
          final_type = result_type;
-         result_type = shorten_binary_op (result_type, op0, op1, 
+         result_type = shorten_binary_op (result_type, op0, op1,
                                           shorten == -1);
        }
 
                                           shorten == -1);
        }
 
@@ -9417,6 +9692,7 @@ build_binary_op (location_t location, enum tree_code code,
            unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
 
          if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
            unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
 
          if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
+             && tree_int_cst_sgn (op1) > 0
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
              && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
              /* We can shorten only if the shift count is less than the
                 number of bits in the smaller type size.  */
              && compare_tree_int (op1, TYPE_PRECISION (TREE_TYPE (arg0))) < 0
@@ -9475,10 +9751,12 @@ build_binary_op (location_t location, enum tree_code code,
                     build_conditional_expr.  This requires the
                     "original" values to be folded, not just op0 and
                     op1.  */
                     build_conditional_expr.  This requires the
                     "original" values to be folded, not just op0 and
                     op1.  */
+                 c_inhibit_evaluation_warnings++;
                  op0 = c_fully_fold (op0, require_constant_value,
                                      &op0_maybe_const);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
                  op0 = c_fully_fold (op0, require_constant_value,
                                      &op0_maybe_const);
                  op1 = c_fully_fold (op1, require_constant_value,
                                      &op1_maybe_const);
+                 c_inhibit_evaluation_warnings--;
                  orig_op0_folded = c_fully_fold (orig_op0,
                                                  require_constant_value,
                                                  NULL);
                  orig_op0_folded = c_fully_fold (orig_op0,
                                                  require_constant_value,
                                                  NULL);
@@ -9494,17 +9772,9 @@ build_binary_op (location_t location, enum tree_code code,
              if (!in_late_binary_op)
                {
                  if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
              if (!in_late_binary_op)
                {
                  if (!op0_maybe_const || TREE_CODE (op0) != INTEGER_CST)
-                   {
-                     op0 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op0),
-                                   NULL, op0);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op0) = !op0_maybe_const;
-                   }
+                   op0 = c_wrap_maybe_const (op0, !op0_maybe_const);
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
                  if (!op1_maybe_const || TREE_CODE (op1) != INTEGER_CST)
-                   {
-                     op1 = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (op1),
-                                   NULL, op1);
-                     C_MAYBE_CONST_EXPR_NON_CONST (op1) = !op1_maybe_const;
-                   }
+                   op1 = c_wrap_maybe_const (op1, !op1_maybe_const);
                }
            }
        }
                }
            }
        }
@@ -9548,8 +9818,9 @@ build_binary_op (location_t location, enum tree_code code,
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
-          ? fold_build2_initializer (resultcode, build_type, op0, op1)
-          : fold_build2 (resultcode, build_type, op0, op1));
+          ? fold_build2_initializer_loc (location, resultcode, build_type,
+                                         op0, op1)
+          : fold_build2_loc (location, resultcode, build_type, op0, op1));
   else
     ret = build2 (resultcode, build_type, op0, op1);
   if (final_type != 0)
   else
     ret = build2 (resultcode, build_type, op0, op1);
   if (final_type != 0)
@@ -9971,11 +10242,11 @@ c_build_qualified_type (tree type, int type_quals)
           else if (TYPE_CANONICAL (element_type) != element_type
                    || (domain && TYPE_CANONICAL (domain) != domain))
             {
           else if (TYPE_CANONICAL (element_type) != element_type
                    || (domain && TYPE_CANONICAL (domain) != domain))
             {
-              tree unqualified_canon 
+              tree unqualified_canon
                 = build_array_type (TYPE_CANONICAL (element_type),
                 = build_array_type (TYPE_CANONICAL (element_type),
-                                    domain? TYPE_CANONICAL (domain) 
+                                    domain? TYPE_CANONICAL (domain)
                                           : NULL_TREE);
                                           : NULL_TREE);
-              TYPE_CANONICAL (t) 
+              TYPE_CANONICAL (t)
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
           else
                 = c_build_qualified_type (unqualified_canon, type_quals);
             }
           else