[C++] Fix ICE for binding lax vector conversions to references (PR 93014)

Jason Merrill jason@redhat.com
Fri Dec 20 23:13:00 GMT 2019


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.sandiford@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));
> +}
> 



More information about the Gcc-patches mailing list