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

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
+}
+
-- 
2.39.2



Reply via email to