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-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 e429ce9d176..709410bcf19 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -12069,12 +12069,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 3ef1b6b483b..ec7746dc0da 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -2084,12 +2084,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) @@ -2102,7 +2108,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