[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