Hi!

This patch fixes ICEs if a non-lvalue vector (say cast of one vector
to another vector type) was subscripted and used as lhs.
The following patch, if *vecp is not lvalue, will copy it to a temporary
variable which can be made addressable for the subscription, and afterwards
wrap it into a NON_LVALUE_EXPR so that it is properly rejected if later used
on the lhs.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2014-11-20  Jakub Jelinek  <ja...@redhat.com>

        PR target/63764
c-family/
        * c-common.h (convert_vector_to_pointer_for_subscript): Change
        return type to bool.
        * c-common.c: Include gimple-expr.c.
        (convert_vector_to_pointer_for_subscript): Change return type to
        bool.  If *vecp is not lvalue_p and has VECTOR_TYPE, return true
        and copy it into a TARGET_EXPR and use that instead of *vecp
        directly.
c/
        * c-typeck.c (build_array_ref): Adjust
        convert_vector_to_pointer_for_subscript caller.  If it returns true,
        call non_lvalue_loc on the result.
cp/
        * typeck.c (cp_build_array_ref): Adjust
        convert_vector_to_pointer_for_subscript caller.  If it returns true,
        call non_lvalue_loc on the result.
testsuite/
        * c-c++-common/pr63764-1.c: New test.
        * c-c++-common/pr63764-2.c: New test.

--- gcc/c-family/c-common.h.jj  2014-11-19 15:39:26.606065628 +0100
+++ gcc/c-family/c-common.h     2014-11-20 08:38:02.527655971 +0100
@@ -1310,7 +1310,7 @@ extern tree build_userdef_literal (tree
                                   enum overflow_type overflow,
                                   tree num_string);
 
-extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
+extern bool convert_vector_to_pointer_for_subscript (location_t, tree *, tree);
 
 /* Possibe cases of scalar_to_vector conversion.  */
 enum stv_conv {
--- gcc/c-family/c-common.c.jj  2014-11-19 15:39:26.606065628 +0100
+++ gcc/c-family/c-common.c     2014-11-20 08:50:21.000573676 +0100
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.
 #include "target-def.h"
 #include "gimplify.h"
 #include "wide-int-print.h"
+#include "gimple-expr.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -12030,22 +12031,47 @@ build_userdef_literal (tree suffix_id, t
 }
 
 /* For vector[index], convert the vector to a
-   pointer of the underlying type.  */
-void
+   pointer of the underlying type.  Return true if the resulting
+   ARRAY_REF should not be an lvalue.  */
+
+bool
 convert_vector_to_pointer_for_subscript (location_t loc,
-                                        tree* vecp, tree index)
+                                        tree *vecp, tree index)
 {
+  bool ret = false;
   if (TREE_CODE (TREE_TYPE (*vecp)) == VECTOR_TYPE)
     {
       tree type = TREE_TYPE (*vecp);
       tree type1;
 
+      ret = !lvalue_p (*vecp);
       if (TREE_CODE (index) == INTEGER_CST)
         if (!tree_fits_uhwi_p (index)
             || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type))
           warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
 
-      c_common_mark_addressable_vec (*vecp);
+      if (ret)
+       {
+         tree tmp = create_tmp_var_raw (type, NULL);
+         DECL_SOURCE_LOCATION (tmp) = loc;
+         *vecp = c_save_expr (*vecp);
+         if (TREE_CODE (*vecp) == C_MAYBE_CONST_EXPR)
+           {
+             bool non_const = C_MAYBE_CONST_EXPR_NON_CONST (*vecp);
+             *vecp = C_MAYBE_CONST_EXPR_EXPR (*vecp);
+             *vecp
+               = c_wrap_maybe_const (build4 (TARGET_EXPR, type, tmp,
+                                             *vecp, NULL_TREE, NULL_TREE),
+                                     non_const);
+           }
+         else
+           *vecp = build4 (TARGET_EXPR, type, tmp, *vecp,
+                           NULL_TREE, NULL_TREE);
+         SET_EXPR_LOCATION (*vecp, loc);
+         c_common_mark_addressable_vec (tmp);
+       }
+      else
+       c_common_mark_addressable_vec (*vecp);
       type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
       type1 = build_pointer_type (TREE_TYPE (*vecp));
       bool ref_all = TYPE_REF_CAN_ALIAS_ALL (type1);
@@ -12065,6 +12091,7 @@ convert_vector_to_pointer_for_subscript
       *vecp = build1 (ADDR_EXPR, type1, *vecp);
       *vecp = convert (type, *vecp);
     }
+  return ret;
 }
 
 /* Determine which of the operands, if any, is a scalar that needs to be
--- gcc/c/c-typeck.c.jj 2014-11-19 15:39:24.044113650 +0100
+++ gcc/c/c-typeck.c    2014-11-20 08:38:02.534655847 +0100
@@ -2495,7 +2495,8 @@ build_array_ref (location_t loc, tree ar
 
   gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
 
-  convert_vector_to_pointer_for_subscript (loc, &array, index);
+  bool non_lvalue
+    = convert_vector_to_pointer_for_subscript (loc, &array, index);
 
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
@@ -2557,6 +2558,8 @@ build_array_ref (location_t loc, tree ar
            | TREE_THIS_VOLATILE (array));
       ret = require_complete_type (rval);
       protected_set_expr_location (ret, loc);
+      if (non_lvalue)
+       ret = non_lvalue_loc (loc, ret);
       return ret;
     }
   else
@@ -2569,9 +2572,12 @@ build_array_ref (location_t loc, tree ar
       gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
       gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
 
-      return build_indirect_ref
-       (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
-        RO_ARRAY_INDEXING);
+      ret = build_indirect_ref (loc, build_binary_op (loc, PLUS_EXPR, ar,
+                                                     index, 0),
+                               RO_ARRAY_INDEXING);
+      if (non_lvalue)
+       ret = non_lvalue_loc (loc, ret);
+      return ret;
     }
 }
 
--- gcc/cp/typeck.c.jj  2014-11-20 08:32:14.913826919 +0100
+++ gcc/cp/typeck.c     2014-11-20 08:38:02.536655812 +0100
@@ -3072,7 +3072,8 @@ cp_build_array_ref (location_t loc, tree
       break;
     }
 
-  convert_vector_to_pointer_for_subscript (loc, &array, idx);
+  bool non_lvalue
+    = convert_vector_to_pointer_for_subscript (loc, &array, idx);
 
   if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
     {
@@ -3155,6 +3156,8 @@ cp_build_array_ref (location_t loc, tree
       ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
                                          complain);
       protected_set_expr_location (ret, loc);
+      if (non_lvalue)
+       ret = non_lvalue_loc (loc, ret);
       return ret;
     }
 
@@ -3194,6 +3197,8 @@ cp_build_array_ref (location_t loc, tree
                                  RO_ARRAY_INDEXING,
                                  complain);
     protected_set_expr_location (ret, loc);
+    if (non_lvalue)
+      ret = non_lvalue_loc (loc, ret);
     return ret;
   }
 }
--- gcc/testsuite/c-c++-common/pr63764-1.c.jj   2014-11-20 08:38:02.537655794 
+0100
+++ gcc/testsuite/c-c++-common/pr63764-1.c      2014-11-20 08:38:02.537655794 
+0100
@@ -0,0 +1,21 @@
+/* PR target/63764 */
+/* { dg-do compile } */
+
+#define A __attribute__((vector_size (4 * sizeof (float))))
+typedef float V A;
+
+void
+fn1 (V *x)
+{
+  V a = *x;
+  ((V) a)[0] = 0;      /* { dg-error "lvalue required as left operand of 
assignment" } */
+  *x = a;
+}
+
+void
+fn2 (V *x)
+{
+  float A a = *x;
+  ((float A) a)[0] = 0;        /* { dg-error "lvalue required as left operand 
of assignment" } */
+  *x = a;
+}
--- gcc/testsuite/c-c++-common/pr63764-2.c.jj   2014-11-20 08:38:02.537655794 
+0100
+++ gcc/testsuite/c-c++-common/pr63764-2.c      2014-11-20 08:38:02.537655794 
+0100
@@ -0,0 +1,35 @@
+/* PR target/63764 */
+/* { dg-do compile } */
+
+#define A __attribute__((vector_size (4 * sizeof (float))))
+typedef float V A;
+
+float
+fn1 (V *x)
+{
+  V a = *x;
+  return ((V) a)[0];
+}
+
+float
+fn2 (V *x)
+{
+  float A a = *x;
+  return ((float A) a)[0];
+}
+
+void
+fn3 (V *x)
+{
+  V a = *x;
+  a[0] = 0;
+  *x = a;
+}
+
+void
+fn4 (V *x)
+{
+  float A a = *x;
+  a[0] = 0;
+  *x = a;
+}

        Jakub

Reply via email to