[2/4] c: runtime checking for assigment of VM types 2/4

Message ID 2ef9124eecefe8f39eab9557e5ce76f42e8d6c7c.camel@tugraz.at
State Unresolved
Headers
Series [1/4] c: runtime checking for assigment of VM types 1/4 |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Martin Uecker Nov. 18, 2023, 9:13 p.m. UTC
  Support instrumentation of function arguments for functions
called via a declaration.  We can support only simple size
expressions without side effects, because the run-time
instrumentation is done before the call, but the expressions
are evaluated in the callee.

gcc/c:
	* c-typeck.cc (process_vm_constraints): Add support
	for instrumenting function arguments.
	(convert_arguments): Instrument function arguments.
	(convert_for_assigmnent): Adapt.

gcc/testsuide/gcc.dg:
	* vla-bounds-func-1.c: Update.
	* vla-bounds-func-2.c: New test.
	* vla-bounds-func-3.c: New test.
	* vla-bounds-func-4.c: New test.
	* vla-bounds-func-5.c: New test.
	* vla-bounds-func-6.c: New test.
	* vla-bounds-func-7.c: New test.
	* vla-bounds-func-8.c: New test.
	* vla-bounds-func-9.c: New test.
	* vla-bounds-func-10.c: New test.
	* vla-bounds-func-11.c: New test.
	* vla-bounds-func-12.c: New test.
	* vla-bounds-func-13.c: New test.
	* vla-bounds-func-14.c: New test.
	* vla-bounds-func-15.c: New test.
	* vla-bounds-func-16.c: New test.
	* vla-bounds-func-17.c: New test.
	* vla-bounds-func-18.c: New test.
	* vla-bounds-func-19.c: New test.
	* vla-bounds-func-20.c: New test.
---
 gcc/c/c-typeck.cc                         | 151 +++++++++++++++++++---
 gcc/testsuite/gcc.dg/vla-bounds-func-1.c  |   4 +-
 gcc/testsuite/gcc.dg/vla-bounds-func-10.c |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-11.c |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-12.c |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-13.c |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-14.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-15.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-16.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-17.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-18.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-19.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-2.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-20.c |  45 +++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-3.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-4.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-5.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-6.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-7.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-8.c  |  99 ++++++++++++++
 gcc/testsuite/gcc.dg/vla-bounds-func-9.c  |  99 ++++++++++++++
 21 files changed, 1641 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-10.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-11.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-12.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-13.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-14.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-15.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-16.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-17.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-18.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-19.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-2.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-20.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-3.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-4.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-5.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-6.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-7.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-8.c
 create mode 100644 gcc/testsuite/gcc.dg/vla-bounds-func-9.c
  

Patch

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index cb5887b6255..b65fc450940 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1067,19 +1067,13 @@  common_type (tree t1, tree t2)
 /* Instrument assignment of variably modified types.  */
 
 static tree
-c_instrument_vm_assign (location_t loc, tree a, tree b)
+c_instrument_vm_assign (location_t loc, tree a, tree b, tree as, tree bs)
 {
   gcc_assert (flag_vla_bounds);
 
   gcc_assert (TREE_CODE (a) == ARRAY_TYPE);
   gcc_assert (TREE_CODE (b) == ARRAY_TYPE);
 
-  tree as = TYPE_MAX_VALUE (TYPE_DOMAIN (a));
-  tree bs = TYPE_MAX_VALUE (TYPE_DOMAIN (b));
-
-  as = fold_build2 (PLUS_EXPR, sizetype, as, size_one_node);
-  bs = fold_build2 (PLUS_EXPR, sizetype, bs, size_one_node);
-
   tree t = build2 (NE_EXPR, boolean_type_node, as, bs);
   tree tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
 
@@ -3286,7 +3280,8 @@  static tree
 convert_argument (location_t ploc, tree function, tree fundecl,
 		  tree type, tree origtype, tree val, tree valtype,
 		  bool npc, tree rname, int parmnum, int argnum,
-		  bool excess_precision, int warnopt)
+		  bool excess_precision, int warnopt,
+		  struct instrument_data **instr_vec)
 {
   /* Formal parm type is specified by a function prototype.  */
 
@@ -3446,7 +3441,7 @@  convert_argument (location_t ploc, tree function, tree fundecl,
 						    val, origtype, ic_argpass,
 						    npc, fundecl, function,
 						    parmnum + 1, warnopt,
-						    NULL);
+						    instr_vec);
 
   if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
       && INTEGRAL_TYPE_P (type)
@@ -3459,15 +3454,110 @@  convert_argument (location_t ploc, tree function, tree fundecl,
 
 /* Process all constraints for variably-modified types.  */
 
-static tree
+tree
 process_vm_constraints (location_t location,
-			struct instrument_data **instr_vec)
+			struct instrument_data **instr_vec,
+			tree function, tree fundecl, vec<tree, va_gc> *values)
 {
   tree instr_expr = void_node;
+  tree args = NULL;
+
+  /* Find the arguments for the function declaration / type.  */
+  if (function)
+    {
+      if (FUNCTION_DECL == TREE_CODE (function))
+	{
+	  fundecl = function;
+	  args = DECL_ARGUMENTS (fundecl);
+	}
+      else
+	{
+	  /* Functions called via pointers are not yet supported.  */
+	  return void_node;
+	}
+    }
 
   for (struct instrument_data* d = *instr_vec; d; d = d->next)
     {
-      tree in = c_instrument_vm_assign (location, d->t1, d->t2);
+      tree t1 = d->t1;
+      tree t2 = d->t2;
+
+      gcc_assert (ARRAY_TYPE == TREE_CODE (t1));
+      gcc_assert (ARRAY_TYPE == TREE_CODE (t2));
+
+      tree as = TYPE_MAX_VALUE (TYPE_DOMAIN (t1));
+      tree bs = TYPE_MAX_VALUE (TYPE_DOMAIN (t2));
+
+      gcc_assert (as);
+      gcc_assert (bs);
+
+      as = fold_build2 (PLUS_EXPR, sizetype, as, size_one_node);
+      bs = fold_build2 (PLUS_EXPR, sizetype, bs, size_one_node);
+
+      if (function)
+	{
+
+	  if (INTEGER_CST == TREE_CODE (bs))
+	    goto cont;
+
+	  if (NOP_EXPR == TREE_CODE (bs)
+	      && SAVE_EXPR == TREE_CODE (TREE_OPERAND (bs, 0)))
+	    {
+	      tree bs1 = TREE_OPERAND (bs, 0);
+	      tree bs2 = TREE_OPERAND (bs1, 0);
+
+	      /* Another parameter of the current functions.  */
+	      if (PARM_DECL == TREE_CODE (bs2)
+		  && (DECL_CONTEXT (bs2) == fundecl
+		      || DECL_CONTEXT (bs2) == NULL))
+		{
+		  tree arg = args;
+		  int pos = 0;
+		  while (arg)
+		   {
+		     if (arg == bs2)
+		       {
+			 bs = (*values)[pos];
+			 bs = save_expr (bs);
+			 bs = build1 (NOP_EXPR, sizetype, bs);
+			 break;
+		       }
+		     pos++;
+		     arg = DECL_CHAIN (arg);
+		   }
+		  if (!arg)
+		    goto giveup;
+		  goto cont;
+		}
+
+	      /*  A parameter of an enclosing function.  */
+	      if (PARM_DECL == TREE_CODE (bs2)
+		  && DECL_CONTEXT (bs2) != fundecl)
+		{
+		  bs2 = unshare_expr (bs2);
+		  bs1 = save_expr (bs2);
+		  bs = build1 (NOP_EXPR, sizetype, bs1);
+		  goto cont;
+		}
+
+	      /*  A variable with enclosing scope.  */
+	      if (VAR_DECL == TREE_CODE (bs2))
+		{
+		  bs2 = unshare_expr (bs2);
+		  bs1 = save_expr (bs2);
+		  bs = build1 (NOP_EXPR, sizetype, bs1);
+		  goto cont;
+		}
+	    }
+	giveup:
+	  /*  Give up.  If we do not understand a size expression, we can
+	      also not instrument any of the others because it may have
+	      side effects affecting them.  (We could restart and instrument
+	      only the ones with integer constants.)   */
+	    return void_node;
+	}
+cont:
+      tree in = c_instrument_vm_assign (location, t1, t2, as, bs);
       instr_expr = fold_build2 (COMPOUND_EXPR, void_type_node, in, instr_expr);
     }
   return instr_expr;
@@ -3578,6 +3668,12 @@  convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 	  }
     }
 
+  struct instrument_data *instr_first = NULL;
+  struct instrument_data **instr_vec = NULL;
+
+  if (flag_vla_bounds)
+    instr_vec = &instr_first;
+
   /* Scan the given expressions (VALUES) and types (TYPELIST), producing
      individual converted arguments.  */
 
@@ -3690,7 +3786,7 @@  convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 	  tree origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum];
 	  parmval = convert_argument (ploc, function, fundecl, type, origtype,
 				      val, valtype, npc, rname, parmnum, argnum,
-				      excess_precision, 0);
+				      excess_precision, 0, instr_vec);
 	}
       else if (promote_float_arg)
         {
@@ -3745,7 +3841,7 @@  convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 	  convert_argument (ploc, function, fundecl, builtin_type, origtype,
 			    val, valtype, npc, rname, parmnum, argnum,
 			    excess_precision,
-			    OPT_Wbuiltin_declaration_mismatch);
+			    OPT_Wbuiltin_declaration_mismatch, NULL);
 	}
 
       if (typetail)
@@ -3757,6 +3853,31 @@  convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
 
   gcc_assert (parmnum == vec_safe_length (values));
 
+  if (instr_vec)
+    {
+      if (0 < parmnum && instr_vec && instr_first != NULL)
+	{
+	  tree instr_expr = process_vm_constraints (loc, instr_vec, function, fundecl, values);
+	  /* We have to make sure that all parameters are evaluated first,
+	     because we may use size expressions in it to check bounds.  */
+	  if (void_node != instr_expr)
+	    {
+	      tree parmval = (*values)[0];
+	      parmval = save_expr (parmval);
+	      instr_expr = fold_build2 (COMPOUND_EXPR, void_type_node, parmval, instr_expr);
+	      parmval = fold_build2 (COMPOUND_EXPR, TREE_TYPE (parmval), instr_expr, parmval);
+	      (*values)[0] = parmval;
+	    }
+	}
+      while (instr_first)
+	{
+	  struct instrument_data *next = instr_first->next;
+	  free (instr_first);
+	  instr_first = next;
+	}
+      instr_vec = NULL;
+    }
+
   if (typetail != NULL_TREE && TREE_VALUE (typetail) != void_type_node)
     {
       error_at (loc, "too few arguments to function %qE", function);
@@ -6850,7 +6971,7 @@  convert_for_assignment (location_t location, location_t expr_loc, tree type,
 	{
 	  /* We have to make sure that the rhs is evaluated first,
 	     because we may use size expressions in it to check bounds.  */
-	  tree instr_expr = process_vm_constraints (location, instr_vec);
+	  tree instr_expr = process_vm_constraints (location, instr_vec, NULL, NULL, NULL);
 	  if (void_node != instr_expr)
 	    {
 	      ret = save_expr (ret);
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-1.c b/gcc/testsuite/gcc.dg/vla-bounds-func-1.c
index e4856017419..dd5f3e76b50 100644
--- a/gcc/testsuite/gcc.dg/vla-bounds-func-1.c
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-fcheck-vla-bounds" } */
+/* { dg-options "-fvla-bounds" } */
 
 // make sure we do not ICE on any of these
 
@@ -51,6 +51,6 @@  int c(int u, char (*a)[u]) { }
 int d(void)
 {
 	char a[3];
-	c(3, &a);
+	c(3, &a);		/* "Function call not instrumented." */
 }
 
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-10.c b/gcc/testsuite/gcc.dg/vla-bounds-func-10.c
new file mode 100644
index 00000000000..19942d2de95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-10.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-11.c b/gcc/testsuite/gcc.dg/vla-bounds-func-11.c
new file mode 100644
index 00000000000..42859b0bd14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-11.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+TRY(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* "incompatible pointer type" */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-12.c b/gcc/testsuite/gcc.dg/vla-bounds-func-12.c
new file mode 100644
index 00000000000..94334792b62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-12.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* "incompatible pointer type" */
+	// 3 != 4
+
+	d1(3, &C0);
+TRY(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-13.c b/gcc/testsuite/gcc.dg/vla-bounds-func-13.c
new file mode 100644
index 00000000000..95c47e9587d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-13.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* "incompatible pointer type" */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* "incompatible pointer type" */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+TRY(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-14.c b/gcc/testsuite/gcc.dg/vla-bounds-func-14.c
new file mode 100644
index 00000000000..8ac1262e222
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-14.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+ERROR(	b1(4, &A0); )	// 4 != 3
+ERROR(	b0(4, &A0); )	// 4 != 3
+
+ERROR(	b2(&A0, 4); )	// 4 != 3
+	
+ERROR(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+ERROR(	b4(&A0); )	// 4 != 3
+
+ERROR(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-15.c b/gcc/testsuite/gcc.dg/vla-bounds-func-15.c
new file mode 100644
index 00000000000..ef59f6cad4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-15.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+TRY(	b1(4, &A0); )	// 4 != 3
+ERROR(	b0(4, &A0); )	// 4 != 3
+
+ERROR(	b2(&A0, 4); )	// 4 != 3
+	
+ERROR(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+ERROR(	b4(&A0); )	// 4 != 3
+
+ERROR(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-16.c b/gcc/testsuite/gcc.dg/vla-bounds-func-16.c
new file mode 100644
index 00000000000..710871e6db1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-16.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+ERROR(	b1(4, &A0); )	// 4 != 3
+TRY(	b0(4, &A0); )	// 4 != 3
+
+ERROR(	b2(&A0, 4); )	// 4 != 3
+	
+ERROR(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+ERROR(	b4(&A0); )	// 4 != 3
+
+ERROR(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-17.c b/gcc/testsuite/gcc.dg/vla-bounds-func-17.c
new file mode 100644
index 00000000000..f2522030831
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-17.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+ERROR(	b1(4, &A0); )	// 4 != 3
+ERROR(	b0(4, &A0); )	// 4 != 3
+
+TRY(	b2(&A0, 4); )	// 4 != 3
+	
+ERROR(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+ERROR(	b4(&A0); )	// 4 != 3
+
+ERROR(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-18.c b/gcc/testsuite/gcc.dg/vla-bounds-func-18.c
new file mode 100644
index 00000000000..779dd370c8f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-18.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+ERROR(	b1(4, &A0); )	// 4 != 3
+ERROR(	b0(4, &A0); )	// 4 != 3
+
+ERROR(	b2(&A0, 4); )	// 4 != 3
+	
+TRY(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+ERROR(	b4(&A0); )	// 4 != 3
+
+ERROR(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-19.c b/gcc/testsuite/gcc.dg/vla-bounds-func-19.c
new file mode 100644
index 00000000000..7a129d2851f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-19.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+ERROR(	b1(4, &A0); )	// 4 != 3
+ERROR(	b0(4, &A0); )	// 4 != 3
+
+ERROR(	b2(&A0, 4); )	// 4 != 3
+	
+ERROR(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+TRY(	b4(&A0); )	// 4 != 3
+
+ERROR(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-2.c b/gcc/testsuite/gcc.dg/vla-bounds-func-2.c
new file mode 100644
index 00000000000..19942d2de95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-2.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-20.c b/gcc/testsuite/gcc.dg/vla-bounds-func-20.c
new file mode 100644
index 00000000000..8532a2f3223
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-20.c
@@ -0,0 +1,45 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+
+
+void b0(int n, char (*a)[n]) { }
+void b1(int m, char (*a)[m]);
+void b2(int m; char (*a)[m], int m) { }
+void b3(int m; char (*a)[m], int m);
+int n;
+void b4(char (*a)[n]) { }
+void b5(char (*a)[n]);
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	char A0[3];
+ERROR(	b1(4, &A0); )	// 4 != 3
+ERROR(	b0(4, &A0); )	// 4 != 3
+
+ERROR(	b2(&A0, 4); )	// 4 != 3
+	
+ERROR(	b3(&A0, 4); )   // 4 != 3
+
+	n = 4;
+ERROR(	b4(&A0); )	// 4 != 3
+
+TRY(	b5(&A0); )	// 4 != 3
+}
+
+
+void b1(int n, char (*a)[n]) { }
+void b3(int m; char (*a)[m], int m) { }
+void b5(char (*a)[n]) { }
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-3.c b/gcc/testsuite/gcc.dg/vla-bounds-func-3.c
new file mode 100644
index 00000000000..d21337f1de0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-3.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-O1 -fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+TRY(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* "incompatible pointer type" */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* "incompatible pointer type" */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-4.c b/gcc/testsuite/gcc.dg/vla-bounds-func-4.c
new file mode 100644
index 00000000000..14a0efae913
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-4.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...)
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+TRY(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* "incompatible pointer type" */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* "incompatible pointer type" */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-5.c b/gcc/testsuite/gcc.dg/vla-bounds-func-5.c
new file mode 100644
index 00000000000..57f641695a0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-5.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+TRY(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-6.c b/gcc/testsuite/gcc.dg/vla-bounds-func-6.c
new file mode 100644
index 00000000000..88986a8bf23
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-6.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+TRY(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-7.c b/gcc/testsuite/gcc.dg/vla-bounds-func-7.c
new file mode 100644
index 00000000000..788d3243c58
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-7.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+TRY(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-8.c b/gcc/testsuite/gcc.dg/vla-bounds-func-8.c
new file mode 100644
index 00000000000..c0cbf85b647
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-8.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+TRY(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-9.c b/gcc/testsuite/gcc.dg/vla-bounds-func-9.c
new file mode 100644
index 00000000000..3e65106f053
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-bounds-func-9.c
@@ -0,0 +1,99 @@ 
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+#define TRY(...) __VA_ARGS__ __builtin_abort();
+#define ERROR(...) if (0) { __VA_ARGS__ }
+
+int m, n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void c0(char (*a)[n][m]) { }
+static void d0(char (*a)[4][m]) { }
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+static void b1(int u, char (*a)[u]) { }
+static void c1(int u, int v, char (*a)[u][v]) { }
+static void d1(int v, char (*a)[4][v]) { }
+static void e1(int u, char (*a)[u][3]) { }
+static void f1(int u, int v, char a[u][v]) { }
+
+
+
+int main()
+{
+	signal(SIGILL, handler);
+
+	m = 3, n = 4;
+
+	int u = 4;
+	int v = 3;
+
+	/* function arguments */
+
+	char A0[4];
+	char A1[u];
+	char B0[3];
+	char B1[v];
+
+	a0(&A0);
+	a0(&A1);
+	a0(&B0);	/* { dg-warning "incompatible pointer type" } */
+ERROR(	a0(&B1); )	// 4 != 3
+
+	b0(&A0);
+	b0(&A1);
+ERROR(	b0(&B0); )	// 4 != 3
+
+ERROR(	b0(&B1); )	// 4 != 3
+
+	b1(4, &A0);
+ERROR(	b1(4, &B0); )	// 4 != 3
+
+	char C0[4][3];
+	char C1[u][3];
+	char C2[4][v];
+	char C3[u][v];
+	char D0[3][4];
+	char D1[v][4];
+	char D2[3][u];
+	char D3[v][u];
+
+	c0(&C0);
+	c0(&C1);
+	c0(&C2);
+	c0(&C3);
+ERROR(	c0(&D0); ) // 4 != 4, 3 != 4
+
+ERROR(	c0(&D1); ) // 4 != 3, 3 != 4
+	
+ERROR(	c0(&D2); ) // 4 != 3, 3 != 4
+	
+TRY(	c0(&D3); ) // 4 != 3, 3 != 4
+	
+	d0(&C0);
+ERROR(	d0(&D0); ) 	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	d1(3, &C0);
+ERROR(	d1(3, &D0); )	/* { dg-warning "incompatible pointer type" } */
+	// 3 != 4
+
+	e0(&C0);
+	e0(&D0);	/* { dg-warning "incompatible pointer type" } */
+	e1(4, &C0);
+	e1(4, &D0);	/* { dg-warning "incompatible pointer type" } */
+
+	f0(C0);
+ERROR(	f0(D0); ) 	// 3 != 4
+
+	f1(4, 3, C0);
+	f1(4, 3, D0);	// 3 != 4
+}
+