diff mbox series

[09/10] c: Fix bounds checking for VLA and construct VLA vector constants

Message ID 20241106114613.2972987-10-tejas.belagod@arm.com
State New
Headers show
Series aarch64: Enable C/C++ operations on SVE ACLE types. | expand

Commit Message

Tejas Belagod Nov. 6, 2024, 11:46 a.m. UTC
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                                | 15 ++++++++++-----
 .../aarch64/sve/acle/general-c/sizeless-1.c      |  1 +
 .../aarch64/sve/acle/general-c/sizeless-2.c      |  1 +
 gcc/tree.cc                                      | 16 +++++++++++-----
 4 files changed, 23 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 94959f7b8ad..7742b443780 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -11968,13 +11968,18 @@  retry:
 	{
 	  tree elttype = TYPE_MAIN_VARIANT (TREE_TYPE (constructor_type));
 
-	 /* Do a basic check of initializer size.  Note that vectors
-	    may not always have a fixed size derived from their type.  */
-	  if (known_lt (tree_to_poly_uint64 (constructor_max_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 f6823a498ab..20eecdad767 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
@@ -69,6 +69,7 @@  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, 2, 3, 4 }; /* { 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 63a2d7130e1..d3eb8a3727f 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
@@ -69,6 +69,7 @@  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, 2, 3, 4, 5, 6, 7, 8 }; /* { 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 ();