Message ID | mptd0cty3ov.fsf@arm.com |
---|---|
State | New |
Headers | show |
Series | [C++] Make same_type_p return false for gnu_vector_type_p differences (PR 92789) | expand |
On 12/12/19 10:16 AM, Richard Sandiford wrote: > As Jason pointed out in the review of the C++ gnu_vector_type_p patch: > > https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00173.html > > the real fix for the XFAILs in acle/general-c++/gnu_vectors_*.C is to > make same_type_p return false for two types if one is gnu_vector_type_p > and the other isn't. This patch does that and fixes the fallout in the > way Jason suggested above. > > I'd said at the time that some of the tests require: > > /* If the constructor already has the array type, it's been through > digest_init, so we shouldn't try to do anything more. */ > bool digested = same_type_p (atype, TREE_TYPE (init)); > > (build_vec_init) to be true for gnu vectors built from non-gnu vectors. > I can no longer reproduce that, maybe because my original same_type_p > change was bogus or because something in the later sizeless type > support made it moot (or something else :-)). > > This means that sve-sizeless-2.C (the length-specific test) now reports > some errors for comparisons and pointer differences that sve-sizeless-1.C > (the length-agnostic test) already had. I think requiring a cast is OK > for those cases, since there's no reason to mix GNU and non-GNU versions > of the same vector in the same object. Even -flax-vector-conversions > would require a cast for different vector types here, for both C and C++. > > same_type_p had: > > else if (strict == COMPARE_STRUCTURAL) > return structural_comptypes (t1, t2, COMPARE_STRICT); > else > return structural_comptypes (t1, t2, strict); > > Since structural_comptypes ignored the COMPARE_STRUCTURAL bit of "strict" > before the patch, the "else if" was harmless but AFAICT unnecessary. The comment in cp-tree.h has > #define COMPARE_STRUCTURAL 8 /* The comparison is intended to be > structural. The actual comparison > will be identical to > COMPARE_STRICT. */ So introducing differences between COMPARE_STRUCTURAL and COMPARE_STRICT other than that the first always calls structural_comptypes and the second sometimes compares TYPE_CANONICAL instead is to be avoided. Do you want to use vector_types_convertible_p in similar_type_p? Jason
Jason Merrill <jason@redhat.com> writes: > On 12/12/19 10:16 AM, Richard Sandiford wrote: >> As Jason pointed out in the review of the C++ gnu_vector_type_p patch: >> >> https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00173.html >> >> the real fix for the XFAILs in acle/general-c++/gnu_vectors_*.C is to >> make same_type_p return false for two types if one is gnu_vector_type_p >> and the other isn't. This patch does that and fixes the fallout in the >> way Jason suggested above. >> >> I'd said at the time that some of the tests require: >> >> /* If the constructor already has the array type, it's been through >> digest_init, so we shouldn't try to do anything more. */ >> bool digested = same_type_p (atype, TREE_TYPE (init)); >> >> (build_vec_init) to be true for gnu vectors built from non-gnu vectors. >> I can no longer reproduce that, maybe because my original same_type_p >> change was bogus or because something in the later sizeless type >> support made it moot (or something else :-)). >> >> This means that sve-sizeless-2.C (the length-specific test) now reports >> some errors for comparisons and pointer differences that sve-sizeless-1.C >> (the length-agnostic test) already had. I think requiring a cast is OK >> for those cases, since there's no reason to mix GNU and non-GNU versions >> of the same vector in the same object. Even -flax-vector-conversions >> would require a cast for different vector types here, for both C and C++. >> >> same_type_p had: >> >> else if (strict == COMPARE_STRUCTURAL) >> return structural_comptypes (t1, t2, COMPARE_STRICT); >> else >> return structural_comptypes (t1, t2, strict); >> >> Since structural_comptypes ignored the COMPARE_STRUCTURAL bit of "strict" >> before the patch, the "else if" was harmless but AFAICT unnecessary. > > The comment in cp-tree.h has > >> #define COMPARE_STRUCTURAL 8 /* The comparison is intended to be >> structural. The actual comparison >> will be identical to >> COMPARE_STRICT. */ > > So introducing differences between COMPARE_STRUCTURAL and COMPARE_STRICT > other than that the first always calls structural_comptypes and the > second sometimes compares TYPE_CANONICAL instead is to be avoided. OK. > Do you want to use vector_types_convertible_p in similar_type_p? The problem then is that we'll apply -flax-vector-conversion rules too, which seems to be going too far beyond what [conv.qual] says. But that's probably a sign that I was wanting the wrong behaviour here. The main point is to ensure that similar GNU and non-GNU vectors remain interconveritble without -flax-vector-conversions, and without any warnings. There's no specific requirement to extend that to pointers, it just seemed like the natural thing to do at the time. So on reflection, I guess we should just accept the consequences of making the types !same_type_p. Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? If so, I'll follow up with a corresponding patch for C. Thanks, Richard 2019-12-19 Richard Sandiford <richard.sandiford@arm.com> gcc/cp/ PR c++/92789 * typeck.c (structural_comptypes): Make sure that two vector types agree on gnu_vector_type_p. gcc/testsuite/ PR c++/92789 * g++.dg/ext/sve-sizeless-2.C (statements): Expect pointer difference and comparisons between GNU and non-GNU types to be rejected. Expect __is_same to be false for such pairs. * g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C: Remove XFAILs. Expect conversions between SVE vector pointers and GNU vector pointers to be rejected. Test references. * g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C: Likewise. Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c 2019-12-19 16:28:40.344411888 +0000 +++ gcc/cp/typeck.c 2019-12-19 16:43:03.490702766 +0000 @@ -1425,7 +1425,8 @@ structural_comptypes (tree t1, tree t2, break; case VECTOR_TYPE: - if (maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) + if (gnu_vector_type_p (t1) != gnu_vector_type_p (t2) + || maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) return false; break; Index: gcc/testsuite/g++.dg/ext/sve-sizeless-2.C =================================================================== --- gcc/testsuite/g++.dg/ext/sve-sizeless-2.C 2019-12-13 10:21:18.000000000 +0000 +++ gcc/testsuite/g++.dg/ext/sve-sizeless-2.C 2019-12-19 16:43:03.490702766 +0000 @@ -183,8 +183,8 @@ statements (int n) // Pointer assignment. - gnu_sc_ptr = sve_sc_ptr; - sve_sc_ptr = gnu_sc_ptr; + gnu_sc_ptr = sve_sc_ptr; // { dg-error {invalid conversion from 'svint8_t\*' to 'int8x32_t\*'} } + sve_sc_ptr = gnu_sc_ptr; // { dg-error {invalid conversion from 'int8x32_t\*'[^\n]* to 'svint8_t\*'} } // Pointer arithmetic. @@ -197,8 +197,8 @@ statements (int n) sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } - gnu_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } - sve_sc_ptr - gnu_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } + gnu_sc_ptr - sve_sc_ptr; // { dg-error {invalid operands of types 'int8x32_t\*'[^\n]* and 'svint8_t\*' to binary 'operator-'} } + sve_sc_ptr - gnu_sc_ptr; // { dg-error {invalid operands of types 'svint8_t\*' and 'int8x32_t\*'[^\n]* to binary 'operator-'} } sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } @@ -210,18 +210,18 @@ statements (int n) sve_sc_ptr <= &sve_sc1; sve_sc_ptr > &sve_sc1; sve_sc_ptr >= &sve_sc1; - gnu_sc_ptr == sve_sc_ptr; - gnu_sc_ptr != sve_sc_ptr; - gnu_sc_ptr < sve_sc_ptr; - gnu_sc_ptr <= sve_sc_ptr; - gnu_sc_ptr > sve_sc_ptr; - gnu_sc_ptr >= sve_sc_ptr; - sve_sc_ptr == gnu_sc_ptr; - sve_sc_ptr != gnu_sc_ptr; - sve_sc_ptr < gnu_sc_ptr; - sve_sc_ptr <= gnu_sc_ptr; - sve_sc_ptr > gnu_sc_ptr; - sve_sc_ptr >= gnu_sc_ptr; + gnu_sc_ptr == sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr != sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr < sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr <= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr > sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr >= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr == gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr != gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr < gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr <= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr > gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr >= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } // New and delete. @@ -243,8 +243,8 @@ statements (int n) 0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} } 0 ? sve_sc1 : sve_sc1; 0 ? sve_sc_ptr : sve_sc_ptr; - 0 ? sve_sc_ptr : gnu_sc_ptr; - 0 ? gnu_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} } + 0 ? gnu_sc_ptr : sve_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} } // Function arguments. @@ -321,11 +321,11 @@ statements (int n) { typedef int f[__is_pod (svint8_t) ? 1 : -1]; } { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; } { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; } - { typedef int f[__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; } - { typedef int f[__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; } + { typedef int f[!__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; } + { typedef int f[!__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; } { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; } - { typedef int f[__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; } - { typedef int f[__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; } + { typedef int f[!__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; } + { typedef int f[!__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; } { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; } { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; } { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; } Index: gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C =================================================================== --- gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C 2019-12-13 10:21:18.000000000 +0000 +++ gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C 2019-12-19 16:43:03.490702766 +0000 @@ -36,14 +36,14 @@ f (svuint8_t sve_u1, svint8_t sve_s1, gnu_uint8_t init_gnu_u1 = 0; // { dg-error {cannot convert 'int' to 'gnu_uint8_t'[^\n]* in initialization} } gnu_uint8_t init_gnu_u2 = {}; - gnu_uint8_t init_gnu_u3 = { sve_u1 }; + gnu_uint8_t init_gnu_u3 = { sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u4 = { gnu_u1 }; gnu_uint8_t init_gnu_u5 = { sve_s1 }; // { dg-error {cannot convert 'svint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u6 = { gnu_s1 }; // { dg-error {cannot convert 'gnu_int8_t'[^\n]* to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u7 = { 0 }; gnu_uint8_t init_gnu_u8 = { sve_u1, sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u9 = { gnu_u1, gnu_u1 }; // { dg-error {cannot convert 'gnu_uint8_t'[^\n]* to 'unsigned char' in initialization} } - gnu_uint8_t init_gnu_u10 { sve_u1 }; + gnu_uint8_t init_gnu_u10 { sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u11 { gnu_u1 }; gnu_uint8_t init_gnu_u12 { sve_s1 }; // { dg-error {cannot convert 'svint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u13 { gnu_s1 }; // { dg-error {cannot convert 'gnu_int8_t'[^\n]* to 'unsigned char' in initialization} } @@ -69,7 +69,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1, (gnu_uint8_t) {}; (gnu_uint8_t) { 0 }; - (gnu_uint8_t) { sve_u1 }; + (gnu_uint8_t) { sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } (gnu_uint8_t) { gnu_u1 }; (gnu_uint8_t) { sve_s1 }; // { dg-error {cannot convert 'svint8_t' to 'unsigned char' in initialization} } (gnu_uint8_t) { gnu_s1 }; // { dg-error {cannot convert 'gnu_int8_t'[^\n]* to 'unsigned char' in initialization} } @@ -434,8 +434,8 @@ f (svuint8_t sve_u1, svint8_t sve_s1, // Conditional expressions. uc ? sve_u1 : sve_u1; - uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} "" { xfail *-*-* } } - uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} "" { xfail *-*-* } } + uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} } + uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} } uc ? gnu_u1 : gnu_u1; sve_u1 ? sve_u1 : sve_u1; // { dg-error {could not convert 'sve_u1' from 'svuint8_t' to 'bool'} } @@ -474,15 +474,29 @@ f (svuint8_t sve_u1, svint8_t sve_s1, static_assert(__is_literal_type(svuint8_t)); static_assert(__is_literal_type(gnu_uint8_t)); + // Pointers. + svuint8_t *sve_ptr1 = &sve_u1; - svuint8_t *sve_ptr2 = &gnu_u1; + svuint8_t *sve_ptr2 = &gnu_u1; // { dg-error {invalid conversion} } svuint8_t *sve_ptr3 = &sve_s1; // { dg-error {cannot convert 'svint8_t\*' to 'svuint8_t\*' in initialization} } svuint8_t *sve_ptr4 = &gnu_s1; // { dg-error {cannot convert 'gnu_int8_t\*'[^\n]* to 'svuint8_t\*' in initialization} } - gnu_uint8_t *gnu_ptr1 = &sve_u1; + gnu_uint8_t *gnu_ptr1 = &sve_u1; // { dg-error {invalid conversion} } gnu_uint8_t *gnu_ptr2 = &gnu_u1; gnu_uint8_t *gnu_ptr3 = &sve_s1; // { dg-error {cannot convert 'svint8_t\*' to 'gnu_uint8_t\*'} } gnu_uint8_t *gnu_ptr4 = &gnu_s1; // { dg-error {cannot convert 'gnu_int8_t\*'[^\n]* to 'gnu_uint8_t\*'} } + + // References. + + svuint8_t &sve_ref1 = sve_u1; + svuint8_t &sve_ref2 = gnu_u1; // { dg-error {cannot bind non-const lvalue reference} } + svuint8_t &sve_ref3 = sve_s1; // { dg-error {invalid initialization of reference of type 'svuint8_t\&' from expression of type 'svint8_t'} } + svuint8_t &sve_ref4 = gnu_s1; // { dg-error {invalid initialization of reference of type 'svuint8_t\&' from expression of type 'gnu_int8_t'} } + + gnu_uint8_t &gnu_ref1 = sve_u1; // { dg-error {cannot bind non-const lvalue reference} } + gnu_uint8_t &gnu_ref2 = gnu_u1; + gnu_uint8_t &gnu_ref3 = sve_s1; // { dg-error {invalid initialization of reference of type 'gnu_uint8_t\&} } + gnu_uint8_t &gnu_ref4 = gnu_s1; // { dg-error {invalid initialization of reference of type 'gnu_uint8_t\&} } } constexpr svuint8_t const1 (svuint8_t x) { return x; } Index: gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C =================================================================== --- gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C 2019-12-13 10:21:18.000000000 +0000 +++ gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C 2019-12-19 16:43:03.490702766 +0000 @@ -36,14 +36,14 @@ f (svuint8_t sve_u1, svint8_t sve_s1, gnu_uint8_t init_gnu_u1 = 0; // { dg-error {cannot convert 'int' to 'gnu_uint8_t'[^\n]* in initialization} } gnu_uint8_t init_gnu_u2 = {}; - gnu_uint8_t init_gnu_u3 = { sve_u1 }; + gnu_uint8_t init_gnu_u3 = { sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u4 = { gnu_u1 }; gnu_uint8_t init_gnu_u5 = { sve_s1 }; // { dg-error {cannot convert 'svint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u6 = { gnu_s1 }; // { dg-error {cannot convert 'gnu_int8_t'[^\n]* to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u7 = { 0 }; gnu_uint8_t init_gnu_u8 = { sve_u1, sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u9 = { gnu_u1, gnu_u1 }; // { dg-error {cannot convert 'gnu_uint8_t'[^\n]* to 'unsigned char' in initialization} } - gnu_uint8_t init_gnu_u10 { sve_u1 }; + gnu_uint8_t init_gnu_u10 { sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u11 { gnu_u1 }; gnu_uint8_t init_gnu_u12 { sve_s1 }; // { dg-error {cannot convert 'svint8_t' to 'unsigned char' in initialization} } gnu_uint8_t init_gnu_u13 { gnu_s1 }; // { dg-error {cannot convert 'gnu_int8_t'[^\n]* to 'unsigned char' in initialization} } @@ -69,7 +69,7 @@ f (svuint8_t sve_u1, svint8_t sve_s1, (gnu_uint8_t) {}; (gnu_uint8_t) { 0 }; - (gnu_uint8_t) { sve_u1 }; + (gnu_uint8_t) { sve_u1 }; // { dg-error {cannot convert 'svuint8_t' to 'unsigned char' in initialization} } (gnu_uint8_t) { gnu_u1 }; (gnu_uint8_t) { sve_s1 }; // { dg-error {cannot convert 'svint8_t' to 'unsigned char' in initialization} } (gnu_uint8_t) { gnu_s1 }; // { dg-error {cannot convert 'gnu_int8_t'[^\n]* to 'unsigned char' in initialization} } @@ -434,8 +434,8 @@ f (svuint8_t sve_u1, svint8_t sve_s1, // Conditional expressions. uc ? sve_u1 : sve_u1; - uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} "" { xfail *-*-* } } - uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} "" { xfail *-*-* } } + uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} } + uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} } uc ? gnu_u1 : gnu_u1; sve_u1 ? sve_u1 : sve_u1; // { dg-error {could not convert 'sve_u1' from 'svuint8_t' to 'bool'} } @@ -474,15 +474,29 @@ f (svuint8_t sve_u1, svint8_t sve_s1, static_assert(__is_literal_type(svuint8_t)); static_assert(__is_literal_type(gnu_uint8_t)); + // Pointers. + svuint8_t *sve_ptr1 = &sve_u1; - svuint8_t *sve_ptr2 = &gnu_u1; + svuint8_t *sve_ptr2 = &gnu_u1; // { dg-error {invalid conversion} } svuint8_t *sve_ptr3 = &sve_s1; // { dg-error {invalid conversion from 'svint8_t\*' to 'svuint8_t\*'} } svuint8_t *sve_ptr4 = &gnu_s1; // { dg-error {invalid conversion from 'gnu_int8_t\*'[^\n]* to 'svuint8_t\*'} } - gnu_uint8_t *gnu_ptr1 = &sve_u1; + gnu_uint8_t *gnu_ptr1 = &sve_u1; // { dg-error {invalid conversion} } gnu_uint8_t *gnu_ptr2 = &gnu_u1; gnu_uint8_t *gnu_ptr3 = &sve_s1; // { dg-error {invalid conversion from 'svint8_t\*' to 'gnu_uint8_t\*'} } gnu_uint8_t *gnu_ptr4 = &gnu_s1; // { dg-error {invalid conversion from 'gnu_int8_t\*'[^\n]* to 'gnu_uint8_t\*'} } + + // References. + + svuint8_t &sve_ref1 = sve_u1; + svuint8_t &sve_ref2 = gnu_u1; // { dg-error {cannot bind non-const lvalue reference} } + svuint8_t &sve_ref3 = sve_s1; // { dg-error {cannot bind non-const lvalue reference} } + svuint8_t &sve_ref4 = gnu_s1; // { dg-error {cannot bind non-const lvalue reference} } + + gnu_uint8_t &gnu_ref1 = sve_u1; // { dg-error {cannot bind non-const lvalue reference} } + gnu_uint8_t &gnu_ref2 = gnu_u1; + gnu_uint8_t &gnu_ref3 = sve_s1; // { dg-error {cannot bind non-const lvalue reference} } + gnu_uint8_t &gnu_ref4 = gnu_s1; // { dg-error {cannot bind non-const lvalue reference} } } constexpr svuint8_t const1 (svuint8_t x) { return x; }
On Thu, Dec 19, 2019 at 11:52 AM Richard Sandiford < richard.sandiford@arm.com> wrote: > Jason Merrill <jason@redhat.com> writes: > > On 12/12/19 10:16 AM, Richard Sandiford wrote: > >> As Jason pointed out in the review of the C++ gnu_vector_type_p patch: > >> > >> https://gcc.gnu.org/ml/gcc-patches/2019-12/msg00173.html > >> > >> the real fix for the XFAILs in acle/general-c++/gnu_vectors_*.C is to > >> make same_type_p return false for two types if one is gnu_vector_type_p > >> and the other isn't. This patch does that and fixes the fallout in the > >> way Jason suggested above. > >> > >> I'd said at the time that some of the tests require: > >> > >> /* If the constructor already has the array type, it's been > through > >> digest_init, so we shouldn't try to do anything more. */ > >> bool digested = same_type_p (atype, TREE_TYPE (init)); > >> > >> (build_vec_init) to be true for gnu vectors built from non-gnu vectors. > >> I can no longer reproduce that, maybe because my original same_type_p > >> change was bogus or because something in the later sizeless type > >> support made it moot (or something else :-)). > >> > >> This means that sve-sizeless-2.C (the length-specific test) now reports > >> some errors for comparisons and pointer differences that > sve-sizeless-1.C > >> (the length-agnostic test) already had. I think requiring a cast is OK > >> for those cases, since there's no reason to mix GNU and non-GNU versions > >> of the same vector in the same object. Even -flax-vector-conversions > >> would require a cast for different vector types here, for both C and > C++. > >> > >> same_type_p had: > >> > >> else if (strict == COMPARE_STRUCTURAL) > >> return structural_comptypes (t1, t2, COMPARE_STRICT); > >> else > >> return structural_comptypes (t1, t2, strict); > >> > >> Since structural_comptypes ignored the COMPARE_STRUCTURAL bit of > "strict" > >> before the patch, the "else if" was harmless but AFAICT unnecessary. > > > > The comment in cp-tree.h has > > > >> #define COMPARE_STRUCTURAL 8 /* The comparison is intended to be > > >> structural. The actual comparison > > >> will be identical to > > >> COMPARE_STRICT. */ > > > > So introducing differences between COMPARE_STRUCTURAL and COMPARE_STRICT > > other than that the first always calls structural_comptypes and the > > second sometimes compares TYPE_CANONICAL instead is to be avoided. > > OK. > > > Do you want to use vector_types_convertible_p in similar_type_p? > > The problem then is that we'll apply -flax-vector-conversion rules too, > which seems to be going too far beyond what [conv.qual] says. > > But that's probably a sign that I was wanting the wrong behaviour here. > The main point is to ensure that similar GNU and non-GNU vectors remain > interconveritble without -flax-vector-conversions, and without any > warnings. There's no specific requirement to extend that to pointers, > it just seemed like the natural thing to do at the time. > > So on reflection, I guess we should just accept the consequences of > making the types !same_type_p. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? > If so, I'll follow up with a corresponding patch for C. > OK. > >
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c 2019-12-06 10:31:11.286433308 +0000 +++ gcc/c-family/c-common.c 2019-12-12 15:13:55.789913884 +0000 @@ -923,11 +923,18 @@ bool_promoted_to_int_p (tree t) bool vector_targets_convertible_p (const_tree t1, const_tree t2) { - if (VECTOR_TYPE_P (t1) && VECTOR_TYPE_P (t2) - && (TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2)) + if (!VECTOR_TYPE_P (t1) || !VECTOR_TYPE_P (t2)) + return false; + + if ((TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2)) && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))) return true; + if (gnu_vector_type_p (t1) != gnu_vector_type_p (t2) + && known_eq (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) + && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) + return true; + return false; } Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c 2019-12-10 09:17:17.668010318 +0000 +++ gcc/cp/typeck.c 2019-12-12 15:13:55.789913884 +0000 @@ -1429,6 +1429,9 @@ structural_comptypes (tree t1, tree t2, if (maybe_ne (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2)) || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) return false; + if (strict == COMPARE_STRICT + && gnu_vector_type_p (t1) != gnu_vector_type_p (t2)) + return false; break; case TYPE_PACK_EXPANSION: @@ -1526,8 +1529,6 @@ comptypes (tree t1, tree t2, int strict) else return structural_comptypes (t1, t2, strict); } - else if (strict == COMPARE_STRUCTURAL) - return structural_comptypes (t1, t2, COMPARE_STRICT); else return structural_comptypes (t1, t2, strict); } @@ -1556,6 +1557,9 @@ similar_type_p (tree type1, tree type2) if (type1 == error_mark_node || type2 == error_mark_node) return false; + if (type1 == type2) + return true; + /* Informally, two types are similar if, ignoring top-level cv-qualification: * they are the same type; or * they are both pointers, and the pointed-to types are similar; or @@ -1564,8 +1568,18 @@ similar_type_p (tree type1, tree type2) * they are both arrays of the same size or both arrays of unknown bound, and the array element types are similar. */ - if (same_type_ignoring_top_level_qualifiers_p (type1, type2)) - return true; + tree unqual_type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED); + tree unqual_type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED); + if (VECTOR_TYPE_P (unqual_type1) && VECTOR_TYPE_P (unqual_type2)) + { + if (comptypes (unqual_type1, unqual_type2, COMPARE_STRUCTURAL)) + return true; + } + else + { + if (same_type_p (unqual_type1, unqual_type2)) + return true; + } if ((TYPE_PTR_P (type1) && TYPE_PTR_P (type2)) || (TYPE_PTRDATAMEM_P (type1) && TYPE_PTRDATAMEM_P (type2)) Index: gcc/testsuite/g++.dg/ext/sve-sizeless-2.C =================================================================== --- gcc/testsuite/g++.dg/ext/sve-sizeless-2.C 2019-12-06 18:22:12.084859448 +0000 +++ gcc/testsuite/g++.dg/ext/sve-sizeless-2.C 2019-12-12 15:13:55.793913855 +0000 @@ -197,8 +197,8 @@ statements (int n) sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } - gnu_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } - sve_sc_ptr - gnu_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } + gnu_sc_ptr - sve_sc_ptr; // { dg-error {invalid operands of types 'int8x32_t\*'[^\n]* and 'svint8_t\*' to binary 'operator-'} } + sve_sc_ptr - gnu_sc_ptr; // { dg-error {invalid operands of types 'svint8_t\*' and 'int8x32_t\*'[^\n]* to binary 'operator-'} } sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } @@ -210,18 +210,18 @@ statements (int n) sve_sc_ptr <= &sve_sc1; sve_sc_ptr > &sve_sc1; sve_sc_ptr >= &sve_sc1; - gnu_sc_ptr == sve_sc_ptr; - gnu_sc_ptr != sve_sc_ptr; - gnu_sc_ptr < sve_sc_ptr; - gnu_sc_ptr <= sve_sc_ptr; - gnu_sc_ptr > sve_sc_ptr; - gnu_sc_ptr >= sve_sc_ptr; - sve_sc_ptr == gnu_sc_ptr; - sve_sc_ptr != gnu_sc_ptr; - sve_sc_ptr < gnu_sc_ptr; - sve_sc_ptr <= gnu_sc_ptr; - sve_sc_ptr > gnu_sc_ptr; - sve_sc_ptr >= gnu_sc_ptr; + gnu_sc_ptr == sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr != sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr < sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr <= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr > sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + gnu_sc_ptr >= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr == gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr != gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr < gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr <= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr > gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } + sve_sc_ptr >= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} } // New and delete. @@ -243,8 +243,8 @@ statements (int n) 0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} } 0 ? sve_sc1 : sve_sc1; 0 ? sve_sc_ptr : sve_sc_ptr; - 0 ? sve_sc_ptr : gnu_sc_ptr; - 0 ? gnu_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} } + 0 ? gnu_sc_ptr : sve_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} } // Function arguments. @@ -321,11 +321,11 @@ statements (int n) { typedef int f[__is_pod (svint8_t) ? 1 : -1]; } { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; } { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; } - { typedef int f[__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; } - { typedef int f[__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; } + { typedef int f[!__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; } + { typedef int f[!__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; } { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; } - { typedef int f[__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; } - { typedef int f[__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; } + { typedef int f[!__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; } + { typedef int f[!__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; } { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; } { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; } { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; } Index: gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C =================================================================== --- gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C 2019-12-04 09:17:59.654022577 +0000 +++ gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_1.C 2019-12-12 15:13:55.793913855 +0000 @@ -434,8 +434,8 @@ f (svuint8_t sve_u1, svint8_t sve_s1, // Conditional expressions. uc ? sve_u1 : sve_u1; - uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} "" { xfail *-*-* } } - uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} "" { xfail *-*-* } } + uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} } + uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} } uc ? gnu_u1 : gnu_u1; sve_u1 ? sve_u1 : sve_u1; // { dg-error {could not convert 'sve_u1' from 'svuint8_t' to 'bool'} } Index: gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C =================================================================== --- gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C 2019-12-04 09:17:59.654022577 +0000 +++ gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/gnu_vectors_2.C 2019-12-12 15:13:55.793913855 +0000 @@ -434,8 +434,8 @@ f (svuint8_t sve_u1, svint8_t sve_s1, // Conditional expressions. uc ? sve_u1 : sve_u1; - uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} "" { xfail *-*-* } } - uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} "" { xfail *-*-* } } + uc ? gnu_u1 : sve_u1; // { dg-error {operands to '\?:' have different types 'gnu_uint8_t'[^\n]* and 'svuint8_t'} } + uc ? sve_u1 : gnu_u1; // { dg-error {operands to '\?:' have different types 'svuint8_t' and 'gnu_uint8_t'} } uc ? gnu_u1 : gnu_u1; sve_u1 ? sve_u1 : sve_u1; // { dg-error {could not convert 'sve_u1' from 'svuint8_t' to 'bool'} }