Change default of non-overlapping address space conversion
authorRichard Henderson <rth@redhat.com>
Wed, 21 Oct 2015 20:31:26 +0000 (13:31 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 21 Oct 2015 20:31:26 +0000 (13:31 -0700)
The current default of making all undefined coversions being
set to null is not useful.  It has caused all users to lie
and say that spaces are subsets when they are not, just so
that they can override the conversion.

* expr.c (expand_expr_real_2): Use convert_modes on disjoint
address spaces.

From-SVN: r229142

gcc/ChangeLog
gcc/expr.c

index 8271924da317b926d2db78edfa428dd2c862fb9a..ec60f845bb704a02cb37bd00308b4703b0255704 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-21  Richard Henderson  <rth@redhat.com>
+
+       * expr.c (expand_expr_real_2): Use convert_modes on disjoint
+       address spaces.
+
 2015-10-21  Richard Sandiford  <richard.sandiford@arm.com>
 
        * builtins.c (fold_builtin_cabs): Delete.
index adde00d078abca0611528e3be2da67ab19bc6f36..da6887019288b0bc42aeb3bb4285b1cdb1ecc65e 100644 (file)
@@ -8171,34 +8171,40 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
     case ADDR_SPACE_CONVERT_EXPR:
       {
        tree treeop0_type = TREE_TYPE (treeop0);
-       addr_space_t as_to;
-       addr_space_t as_from;
 
        gcc_assert (POINTER_TYPE_P (type));
        gcc_assert (POINTER_TYPE_P (treeop0_type));
 
-       as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
-       as_from = TYPE_ADDR_SPACE (TREE_TYPE (treeop0_type));
+       addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type));
+       addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (treeop0_type));
 
         /* Conversions between pointers to the same address space should
           have been implemented via CONVERT_EXPR / NOP_EXPR.  */
        gcc_assert (as_to != as_from);
 
+       op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
+
         /* Ask target code to handle conversion between pointers
           to overlapping address spaces.  */
        if (targetm.addr_space.subset_p (as_to, as_from)
            || targetm.addr_space.subset_p (as_from, as_to))
          {
-           op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier);
            op0 = targetm.addr_space.convert (op0, treeop0_type, type);
-           gcc_assert (op0);
-           return op0;
          }
-
-       /* For disjoint address spaces, converting anything but
-          a null pointer invokes undefined behaviour.  We simply
-          always return a null pointer here.  */
-       return CONST0_RTX (mode);
+        else
+          {
+           /* For disjoint address spaces, converting anything but a null
+              pointer invokes undefined behaviour.  We truncate or extend the
+              value as if we'd converted via integers, which handles 0 as
+              required, and all others as the programmer likely expects.  */
+#ifndef POINTERS_EXTEND_UNSIGNED
+           const int POINTERS_EXTEND_UNSIGNED = 1;
+#endif
+           op0 = convert_modes (mode, TYPE_MODE (treeop0_type),
+                                op0, POINTERS_EXTEND_UNSIGNED);
+         }
+       gcc_assert (op0);
+       return op0;
       }
 
     case POINTER_PLUS_EXPR: