diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2020-08-01 12:41:28 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2020-08-01 12:41:28 +0100 |
commit | 7d599ad27b9bcf5165f87710f1abc64bbabd06ae (patch) | |
tree | 78482380b2a17a1775290b757897bdf39bbbbaef /gcc/c | |
parent | 197f1e8c14306fc97ff91f9fb4262e70f45eedef (diff) | |
download | gcc-7d599ad27b9bcf5165f87710f1abc64bbabd06ae.zip gcc-7d599ad27b9bcf5165f87710f1abc64bbabd06ae.tar.gz gcc-7d599ad27b9bcf5165f87710f1abc64bbabd06ae.tar.bz2 |
c: Fix bogus vector initialisation error [PR96377]
One of the problems in this PR was that if we had:
vector_type1 array[] = { vector_value1 };
process_init_element would only treat vector_value1 as initialising
a vector_type1 if they had the same TYPE_MAIN_VARIANT. This has
several problems:
(1) It gives confusing error messages if the vector types are
incompatible. (Tested by gcc.dg/pr96377-1.c.)
(2) It means that we reject code that should be valid with
-flax-vector-conversions. (Tested by gcc.dg/pr96377-2.c.)
(3) On arm and aarch64 targets, it means that we reject some
initializers that mix Advanced SIMD and standard GNU vectors.
These vectors have traditionally had different TYPE_MAIN_VARIANTs
because they have different mangling schemes. (Tested by
gcc.dg/pr96377-[3-6].c.)
(4) It means that we reject SVE initializers that should be valid.
(Tested by gcc.target/aarch64/sve/gnu_vectors_[34].c.)
(5) After r11-1741-g:31427b974ed7b7dd54e2 we reject:
arm_neon_type1 array[] = { k ^ arm_neon_value1 };
because applying the binary operator to arm_neon_value1 strips
the "Advanced SIMD type" attributes that were added in that patch.
Stripping the attributes is problematic for other reasons though,
so that still needs to be fixed separately.
g++.target/aarch64/sve/gnu_vectors_[34].C already pass.
gcc/c/
PR c/96377
* c-typeck.c (process_init_element): Split test for whether to
recurse into a record, union or array into...
(initialize_elementwise_p): ...this new function. Don't recurse
into a vector type if the initialization value is also a vector.
gcc/testsuite/
PR c/96377
* gcc.dg/pr96377-1.c: New test.
* gcc.dg/pr96377-2.c: Likewise.
* gcc.dg/pr96377-3.c: Likewise.
* gcc.dg/pr96377-4.c: Likewise.
* gcc.dg/pr96377-5.c: Likewise.
* gcc.dg/pr96377-6.c: Likewise.
* gcc.target/aarch64/pr96377-1.c: Likewise.
* gcc.target/aarch64/sve/acle/general-c/gnu_vectors_3.c: Likewise.
* gcc.target/aarch64/sve/acle/general-c/gnu_vectors_4.c: Likewise.
* g++.target/aarch64/sve/acle/general-c++/gnu_vectors_3.C: Likewise.
* g++.target/aarch64/sve/acle/general-c++/gnu_vectors_4.C: Likewise.
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/c-typeck.c | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index fb5c288..0d639b60 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -9956,6 +9956,47 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) goto retry; } +/* Expression VALUE coincides with the start of type TYPE in a braced + initializer. Return true if we should treat VALUE as initializing + the first element of TYPE, false if we should treat it as initializing + TYPE as a whole. + + If the initializer is clearly invalid, the question becomes: + which choice gives the best error message? */ + +static bool +initialize_elementwise_p (tree type, tree value) +{ + if (type == error_mark_node || value == error_mark_node) + return false; + + gcc_checking_assert (TYPE_MAIN_VARIANT (type) == type); + + tree value_type = TREE_TYPE (value); + if (value_type == error_mark_node) + return false; + + /* GNU vectors can be initialized elementwise. However, treat any + kind of vector value as initializing the vector type as a whole, + regardless of whether the value is a GNU vector. Such initializers + are valid if and only if they would have been valid in a non-braced + initializer like: + + TYPE foo = VALUE; + + so recursing into the vector type would be at best confusing or at + worst wrong. For example, when -flax-vector-conversions is in effect, + it's possible to initialize a V8HI from a V4SI, even though the vectors + have different element types and different numbers of elements. */ + if (gnu_vector_type_p (type)) + return !VECTOR_TYPE_P (value_type); + + if (AGGREGATE_TYPE_P (type)) + return type != TYPE_MAIN_VARIANT (value_type); + + return false; +} + /* Add one non-braced element to the current constructor level. This adjusts the current position within the constructor's type. This may also start or terminate implicit levels @@ -10135,11 +10176,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, /* Otherwise, if we have come to a subaggregate, and we don't have an element of its type, push into it. */ else if (value.value != NULL_TREE - && value.value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype - && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE - || gnu_vector_type_p (fieldtype))) + && initialize_elementwise_p (fieldtype, value.value)) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -10227,11 +10264,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, /* Otherwise, if we have come to a subaggregate, and we don't have an element of its type, push into it. */ else if (value.value != NULL_TREE - && value.value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != fieldtype - && (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE - || fieldcode == UNION_TYPE - || gnu_vector_type_p (fieldtype))) + && initialize_elementwise_p (fieldtype, value.value)) { push_init_level (loc, 1, braced_init_obstack); continue; @@ -10270,11 +10303,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, /* Otherwise, if we have come to a subaggregate, and we don't have an element of its type, push into it. */ else if (value.value != NULL_TREE - && value.value != error_mark_node - && TYPE_MAIN_VARIANT (TREE_TYPE (value.value)) != elttype - && (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE - || eltcode == UNION_TYPE - || gnu_vector_type_p (elttype))) + && initialize_elementwise_p (elttype, value.value)) { push_init_level (loc, 1, braced_init_obstack); continue; |