From: Tejas Belagod Date: Thu, 5 Sep 2024 09:18:18 +0000 (+0530) Subject: c: Fix constructor bounds checking for VLA and construct VLA vector constants X-Git-Tag: basepoints/gcc-16~3773 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=17b520a10cdaabbcbaeaf30fc5228986b368ce0c;p=thirdparty%2Fgcc.git c: Fix constructor bounds checking for VLA and construct VLA vector constants 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/c/ChangeLog: * c-typeck.cc (process_init_element): Add check to restrict constructor length to the minimum vector length allowed. gcc/ChangeLog: * 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. --- diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 23ce0fc788dc..0189a800c11f 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -12083,12 +12083,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 b0389fa00a85..747bac464a56 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 d16f40b5f2a4..33cd21610eaf 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 74d13a8d5832..83a03374a325 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -2084,12 +2084,18 @@ build_vector_from_ctor (tree type, const vec *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 *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 ();