On 12/19/19 11:33 AM, Richard Sandiford wrote:
This test:

typedef unsigned int v4si __attribute__ ((vector_size(16)));
typedef unsigned char v16qi __attribute__ ((vector_size(16)));
extern v16qi x;
v4si &y = x;

ICEs with:

a.c:4:11: internal compiler error: in convert_like_real, at cp/call.c:7670

This started with r260780, which had the effect of making lvalue_kind
look through VIEW_CONVERT_EXPR in all cases, not just for location
wrappers.  This also means that:

typedef unsigned int v4si __attribute__ ((vector_size(16)));
typedef unsigned char v16qi __attribute__ ((vector_size(16)));
extern v16qi x;
v4si &y = reinterpret_cast<v4si>(x);

is now valid despite the result of the cast being an rvalue.

There might be two separate problems here:

(1) Vector conversions aren't being treated as rvalues when they should
     be.  The patch below attempts to fix that by calling rvalue on the
     input to the conversion, so that the tree looks the same as for:

       extern v16qi x;
       v4si &y = (v4si)x;

     which is already handled correctly.

Yes, I think this is the problem.

(2) The convert_like_real check seems to be trying (at least partially)
     to reproduce the logic in reference_binding that led to bad_p being
     set to true.  But the "from" type it's using is the result of the
     implicit conversion added by reference_binding rather than the
     "from" type that reference_binding was using.  AFAICT he result of
     that implicit converson should always be reference-compatible with
     the reference type, so we don't get the error we expected for that
     case.

     The patch doesn't attempt to fix this though.
I think this is only an issue because of the value category problem above; the implicit_conversion should produce an rvalue.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

OK.

Richard


2019-12-19  Richard Sandiford  <richard.sandif...@arm.com>

gcc/cp/
        PR c++/93014
        * cvt.c (ocp_convert): Apply rvalue to the source of vector
        conversions.
        * typeck.c (build_reinterpret_cast_1): Likewise.

gcc/testsuite/
        PR c++/93014
        * g++.dg/ext/vector39.C: New test.

Index: gcc/cp/cvt.c
===================================================================
--- gcc/cp/cvt.c        2019-12-10 09:17:17.688010184 +0000
+++ gcc/cp/cvt.c        2019-12-19 16:28:40.340411914 +0000
@@ -744,7 +744,7 @@ ocp_convert (tree type, tree expr, int c
        else if (TREE_CODE (type) == COMPLEX_TYPE)
        return convert_to_complex_maybe_fold (type, e, dofold);
        else if (VECTOR_TYPE_P (type))
-       return convert_to_vector (type, e);
+       return convert_to_vector (type, rvalue (e));
        else if (TREE_CODE (e) == TARGET_EXPR)
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
@@ -881,7 +881,7 @@ ocp_convert (tree type, tree expr, int c
                      in_vtype, type);
          return error_mark_node;
        }
-      return convert_to_vector (type, e);
+      return convert_to_vector (type, rvalue (e));
      }
    if (code == REAL_TYPE || code == COMPLEX_TYPE)
      {
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c     2019-12-19 13:21:34.914651487 +0000
+++ gcc/cp/typeck.c     2019-12-19 16:28:40.344411888 +0000
@@ -7858,7 +7858,7 @@ build_reinterpret_cast_1 (location_t loc
        return build_nop_reinterpret (type, expr);
      }
    else if (gnu_vector_type_p (type))
-    return convert_to_vector (type, expr);
+    return convert_to_vector (type, rvalue (expr));
    else if (gnu_vector_type_p (intype)
           && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
      return convert_to_integer_nofold (type, expr);
Index: gcc/testsuite/g++.dg/ext/vector39.C
===================================================================
--- /dev/null   2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/g++.dg/ext/vector39.C 2019-12-19 16:28:40.344411888 +0000
@@ -0,0 +1,96 @@
+// { dg-options "-flax-vector-conversions" }
+
+typedef unsigned char v16qi __attribute__((vector_size(16)));
+typedef unsigned int v4si __attribute__((vector_size(16)));
+
+extern v4si normal_v4si;
+extern const v4si const_v4si;
+extern v4si *normal_v4si_ptr;
+extern const v4si *const_v4si_ptr;
+extern v4si &normal_v4si_ref;
+extern const v4si &const_v4si_ref;
+
+extern v16qi normal_v16qi;
+extern const v16qi const_v16qi;
+extern v16qi *normal_v16qi_ptr;
+extern const v16qi *const_v16qi_ptr;
+extern v16qi &normal_v16qi_ref;
+extern const v16qi &const_v16qi_ref;
+
+namespace nonconst_refs {
+  v16qi &ref_normal_v4si = normal_v4si; // { dg-error {cannot bind non-const 
lvalue} }
+  v16qi &ref_const_v4si = const_v4si; // { dg-error {cannot bind non-const 
lvalue} }
+  v16qi &ref_normal_v4si_ptr = *normal_v4si_ptr; // { dg-error {cannot bind 
non-const lvalue} }
+  v16qi &ref_const_v4si_ptr = *const_v4si_ptr; // { dg-error {cannot bind 
non-const lvalue} }
+  v16qi &ref_normal_v4si_ref = normal_v4si_ref; // { dg-error {cannot bind 
non-const lvalue} }
+  v16qi &ref_const_v4si_ref = const_v4si_ref; // { dg-error {cannot bind 
non-const lvalue} }
+
+  v16qi &ref_normal_v16qi = normal_v16qi;
+  v16qi &ref_const_v16qi = const_v16qi; // { dg-error {discards qualifiers} }
+  v16qi &ref_normal_v16qi_ptr = *normal_v16qi_ptr;
+  v16qi &ref_const_v16qi_ptr = *const_v16qi_ptr; // { dg-error {discards 
qualifiers} }
+  v16qi &ref_normal_v16qi_ref = normal_v16qi_ref;
+  v16qi &ref_const_v16qi_ref = const_v16qi_ref; // { dg-error {discards 
qualifiers} }
+}
+
+#if __cplusplus >= 201103L
+namespace nonconst_rvalue_refs {
+  v16qi &&ref_normal_v4si = normal_v4si;
+  v16qi &&ref_const_v4si = const_v4si;
+  v16qi &&ref_normal_v4si_ptr = *normal_v4si_ptr;
+  v16qi &&ref_const_v4si_ptr = *const_v4si_ptr;
+  v16qi &&ref_normal_v4si_ref = normal_v4si_ref;
+  v16qi &&ref_const_v4si_ref = const_v4si_ref;
+
+  v16qi &&ref_normal_v16qi = normal_v16qi; // { dg-error {cannot bind rvalue reference} 
"" { target c++11 } }
+  v16qi &&ref_const_v16qi = const_v16qi; // { dg-error {cannot bind rvalue reference} 
"" { target c++11 } }
+  v16qi &&ref_normal_v16qi_ptr = *normal_v16qi_ptr; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+  v16qi &&ref_const_v16qi_ptr = *const_v16qi_ptr; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+  v16qi &&ref_normal_v16qi_ref = normal_v16qi_ref; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+  v16qi &&ref_const_v16qi_ref = const_v16qi_ref; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+}
+#endif
+
+namespace const_refs {
+  const v16qi &ref_normal_v4si = normal_v4si;
+  const v16qi &ref_const_v4si = const_v4si;
+  const v16qi &ref_normal_v4si_ptr = *normal_v4si_ptr;
+  const v16qi &ref_const_v4si_ptr = *const_v4si_ptr;
+  const v16qi &ref_normal_v4si_ref = normal_v4si_ref;
+  const v16qi &ref_const_v4si_ref = const_v4si_ref;
+
+  const v16qi &ref_normal_v16qi = normal_v16qi;
+  const v16qi &ref_const_v16qi = const_v16qi;
+  const v16qi &ref_normal_v16qi_ptr = *normal_v16qi_ptr;
+  const v16qi &ref_const_v16qi_ptr = *const_v16qi_ptr;
+  const v16qi &ref_normal_v16qi_ref = normal_v16qi_ref;
+  const v16qi &ref_const_v16qi_ref = const_v16qi_ref;
+}
+
+#if __cplusplus >= 201103L
+namespace const_rvalue_refs {
+  const v16qi &&ref_normal_v4si = normal_v4si;
+  const v16qi &&ref_const_v4si = const_v4si;
+  const v16qi &&ref_normal_v4si_ptr = *normal_v4si_ptr;
+  const v16qi &&ref_const_v4si_ptr = *const_v4si_ptr;
+  const v16qi &&ref_normal_v4si_ref = normal_v4si_ref;
+  const v16qi &&ref_const_v4si_ref = const_v4si_ref;
+
+  const v16qi &&ref_normal_v16qi = normal_v16qi; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+  const v16qi &&ref_const_v16qi = const_v16qi; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+  const v16qi &&ref_normal_v16qi_ptr = *normal_v16qi_ptr; // { dg-error {cannot bind 
rvalue reference} "" { target c++11 } }
+  const v16qi &&ref_const_v16qi_ptr = *const_v16qi_ptr; // { dg-error {cannot bind 
rvalue reference} "" { target c++11 } }
+  const v16qi &&ref_normal_v16qi_ref = normal_v16qi_ref; // { dg-error {cannot bind 
rvalue reference} "" { target c++11 } }
+  const v16qi &&ref_const_v16qi_ref = const_v16qi_ref; // { dg-error {cannot bind rvalue 
reference} "" { target c++11 } }
+}
+#endif
+
+namespace rvalue_reinterpret_refs {
+  v16qi &ref_normal_v4si = reinterpret_cast<v16qi>(normal_v4si); // { dg-error 
{cannot bind non-const lvalue} }
+  v16qi &ref_const_v4si = reinterpret_cast<v16qi>(const_v4si); // { dg-error 
{cannot bind non-const lvalue} }
+}
+
+namespace ref_reinterpret_refs {
+  v16qi &ref_normal_v4si = reinterpret_cast<v16qi &>(normal_v4si);
+  v16qi &ref_const_v4si = reinterpret_cast<v16qi &>(const_cast<v4si 
&>(const_v4si));
+}


Reply via email to