@@ -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);
@@ -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." */
}
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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]) { }
+
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+
new file mode 100644
@@ -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
+}
+