This patch adds support for checking bounds of SVE ACLE vector initialization
constructors. It also adds support to construct vector constant from init
constructors.
gcc/ChangeLog:
* c/c-typeck.cc (process_init_element): Add check to restrict
constructor length to the minimum vector length allowed.
* tree.cc (build_vector_from_ctor): Add support to construct VLA vector
constants from init constructors.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/sve/acle/general-c/sizeless-1.c: Update test to
test initialize error.
* gcc.target/aarch64/sve/acle/general-c/sizeless-2.c: Likewise.
---
gcc/c/c-typeck.cc | 16 +++++++++++-----
.../aarch64/sve/acle/general-c/sizeless-1.c | 13 +++++++++++++
.../aarch64/sve/acle/general-c/sizeless-2.c | 12 ++++++++++++
gcc/tree.cc | 16 +++++++++++-----
4 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 201d75d2e9c..5110c3678aa 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -11979,12 +11979,18 @@ retry:
{
tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
- /* Do a basic check of initializer size. Note that vectors
- always have a fixed size derived from their type. */
- if (tree_int_cst_lt (constructor_max_index, constructor_index))
+ /* Do a basic check of initializer size. Note that vectors
+ may not always have a fixed size derived from their type. */
+ if (maybe_lt (tree_to_poly_uint64 (constructor_max_index),
+ tree_to_poly_uint64 (constructor_index)))
{
- pedwarn_init (loc, 0,
- "excess elements in vector initializer");
+ /* Diagose VLA out-of-bounds as errors. */
+ if (tree_to_poly_uint64 (constructor_max_index).is_constant())
+ pedwarn_init (loc, 0,
+ "excess elements in vector initializer");
+ else
+ error_init (loc, "excess elements in vector initializer");
+
break;
}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
index b0389fa00a8..747bac464a5 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
@@ -38,6 +38,8 @@ void ext_consume_sve_sc (svint8_t);
void ext_consume_varargs (int, ...);
svint8_t ext_produce_sve_sc ();
+extern int bar (void);
+
/* Main tests for statements and expressions. */
void
@@ -69,6 +71,17 @@ statements (int n)
int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing
type 'int' using type 'svint8_t'} } */
int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when
initializing type 'int' using type 'svint8_t'} } */
+ svint32_t init_sve_vc1 = { 0, 1 };
+ svint32_t init_sve_vc2 = { 0, bar () };
+ svint32_t init_sve_vc3 = { bar (), n };
+ svint32_t init_sve_vc4 = { 0, 1, 2, 3 };
+ svint32_t init_sve_vc5 = { 0, 1, bar (), 3 };
+ svint32_t init_sve_vc6 = { 0, 1, 2, 3, 4 }; /* { dg-error {excess elements
in vector initializer} } */
+ svint32_t init_sve_vc7 = { 0, 1, 2, 3, bar () }; /* { dg-error {excess
elements in vector initializer} } */
+ svint32_t init_sve_vc8 = { 0, 1, 2, 3, 4, 5 }; /* { dg-error {excess
elements in vector initializer} } */
+ svint32_t init_sve_vc9 = { 0, bar (), 2, 3, 4, n }; /* { dg-error {excess
elements in vector initializer} } */
+
+
/* Compound literals. */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
index d16f40b5f2a..33cd21610ea 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
@@ -38,6 +38,8 @@ void ext_consume_sve_sc (svint8_t);
void ext_consume_varargs (int, ...);
svint8_t ext_produce_sve_sc ();
+extern int bar (void);
+
/* Main tests for statements and expressions. */
void
@@ -69,6 +71,16 @@ statements (int n)
int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing
type 'int' using type 'svint8_t'} } */
int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when
initializing type 'int' using type 'svint8_t'} } */
+ svint32_t init_sve_vc1 = { 0, 1 };
+ svint32_t init_sve_vc2 = { 0, bar () };
+ svint32_t init_sve_vc3 = { bar (), n };
+ svint32_t init_sve_vc4 = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ svint32_t init_sve_vc5 = { 0, 1, bar (), 3, 4, 5, 6, 7 };
+ svint32_t init_sve_vc6 = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /* { dg-warning
{excess elements in vector initializer} } */
+ svint32_t init_sve_vc7 = { 0, 1, 2, 3, bar (), 5, 6, 7, 8 }; /* { dg-warning
{excess elements in vector initializer} } */
+ svint32_t init_sve_vc8 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; /* {
dg-warning {excess elements in vector initializer} } */
+ svint32_t init_sve_vc9 = { 0, bar (), 2, 3, 4, 5, 6, 7, 8, 9, n }; /* {
dg-warning {excess elements in vector initializer} } */
+
/* Compound literals. */
diff --git a/gcc/tree.cc b/gcc/tree.cc
index b4c059d3b0d..0c524be4a9a 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -2072,12 +2072,18 @@ build_vector_from_ctor (tree type, const
vec<constructor_elt, va_gc> *v)
if (vec_safe_length (v) == 0)
return build_zero_cst (type);
- unsigned HOST_WIDE_INT idx, nelts;
+ unsigned HOST_WIDE_INT idx, nelts, step = 1;
tree value;
- /* We can't construct a VECTOR_CST for a variable number of elements. */
- nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
- tree_vector_builder vec (type, nelts, 1);
+ /* If the vector is a VLA, build a VLA constant vector. */
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts))
+ {
+ nelts = constant_lower_bound (TYPE_VECTOR_SUBPARTS (type));
+ gcc_assert (vec_safe_length (v) <= nelts);
+ step = 2;
+ }
+
+ tree_vector_builder vec (type, nelts, step);
FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
{
if (TREE_CODE (value) == VECTOR_CST)
@@ -2090,7 +2096,7 @@ build_vector_from_ctor (tree type, const
vec<constructor_elt, va_gc> *v)
else
vec.quick_push (value);
}
- while (vec.length () < nelts)
+ while (vec.length () < nelts * step)
vec.quick_push (build_zero_cst (TREE_TYPE (type)));
return vec.build ();
--
2.25.1