diff options
author | Tejas Belagod <tejas.belagod@arm.com> | 2024-09-05 14:48:18 +0530 |
---|---|---|
committer | Tejas Belagod <tejas.belagod@arm.com> | 2024-11-29 17:03:19 +0530 |
commit | 17b520a10cdaabbcbaeaf30fc5228986b368ce0c (patch) | |
tree | 53fbde5d9ad6a2739fec3f38932d42778b963dd4 | |
parent | 4f593db8803cc8df796314ca9e15a72c51d6bde9 (diff) | |
download | gcc-17b520a10cdaabbcbaeaf30fc5228986b368ce0c.zip gcc-17b520a10cdaabbcbaeaf30fc5228986b368ce0c.tar.gz gcc-17b520a10cdaabbcbaeaf30fc5228986b368ce0c.tar.bz2 |
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.
-rw-r--r-- | gcc/c/c-typeck.cc | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c | 12 | ||||
-rw-r--r-- | 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 23ce0fc..0189a80 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 b0389fa..747bac4 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 d16f40b..33cd216 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 74d13a8..83a0337 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 (); |