@@ -1201,19 +1201,13 @@ comptypes_verify (tree type1, tree type2)
/* 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);
@@ -3772,7 +3766,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. */
@@ -3932,7 +3927,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)
@@ -3945,15 +3940,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 (TREE_CODE (function) == FUNCTION_DECL)
+ {
+ 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 (TREE_CODE (t1) == ARRAY_TYPE);
+ gcc_assert (TREE_CODE (t2) == ARRAY_TYPE);
+
+ tree as = TYPE_MAX_VALUE (TYPE_DOMAIN (t1));
+ tree bs = TYPE_MAX_VALUE (TYPE_DOMAIN (t2));
+
+ if (!as || !bs)
+ continue;
+
+ as = fold_build2 (PLUS_EXPR, sizetype, as, size_one_node);
+ bs = fold_build2 (PLUS_EXPR, sizetype, bs, size_one_node);
+
+ if (function)
+ {
+
+ if (TREE_CODE (bs) == INTEGER_CST)
+ goto cont;
+
+ if (TREE_CODE (bs) == NOP_EXPR
+ && TREE_CODE (TREE_OPERAND (bs, 0)) == SAVE_EXPR)
+ {
+ tree bs1 = TREE_OPERAND (bs, 0);
+ tree bs2 = TREE_OPERAND (bs1, 0);
+
+ /* Another parameter of the current functions. */
+ if (TREE_CODE (bs2) == PARM_DECL
+ && (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 (TREE_CODE (bs2) == PARM_DECL
+ && 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 (TREE_CODE (bs2) == VAR_DECL)
+ {
+ 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;
@@ -4064,6 +4154,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. */
@@ -4176,7 +4272,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)
{
@@ -4231,7 +4327,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)
@@ -4243,6 +4339,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);
@@ -7422,7 +7543,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 (instr_expr != void_node)
{
ret = save_expr (ret);
@@ -50,5 +50,5 @@ 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,74 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+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);
+
+ b0(&A0);
+ b0(&A1);
+
+ b1(4, &A0);
+
+ 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);
+
+ d0(&C0);
+
+ d1(3, &C0);
+
+ e0(&C0);
+ e1(4, &C0);
+
+ f0(C0);
+
+ f1(4, 3, C0);
+ f1(4, 3, D0); // 3 != 4
+ abort();
+}
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fvla-bounds -fpermissive" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m;
+
+static void d0(char (*a)[4][m]) { }
+static void d1(int v, char (*a)[4][v]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ m = 3;
+
+ char C0[4][3];
+ char D0[3][4];
+
+ d1(3, &C0);
+
+ d0(&C0);
+ d0(&D0); /* { dg-warning "incompatible pointer type" } */
+ abort();
+}
new file mode 100644
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds -fpermissive" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m;
+
+static void d0(char (*a)[4][m]) { }
+static void d1(int v, char (*a)[4][v]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ m = 3;
+
+ char C0[4][3];
+ char D0[3][4];
+
+ d0(&C0);
+
+ d1(3, &C0);
+ d1(3, &D0); /* { dg-warning "incompatible pointer type" } */
+ // 3 != 4
+ abort();
+}
new file mode 100644
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds -fpermissive" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m, n;
+
+static void e0(char (*a)[n][3]) { }
+static void f0(char a[n][m]) { }
+
+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;
+
+ /* function arguments */
+
+ char C0[4][3];
+ char D0[3][4];
+
+ e0(&C0);
+ e1(4, &C0);
+
+ f1(4, 3, C0);
+ f1(4, 3, D0); // 3 != 4
+
+ f0(C0);
+ f0(D0); // 3 != 4
+ abort();
+}
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-fvla-bounds" } */
+
+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]);
+
+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,20 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+void b1(int m, char (*a)[m]);
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ char A0[3];
+ b1(4, &A0); // 4 != 3
+ abort();
+}
+
+void b1(int n, char (*a)[n]) { }
new file mode 100644
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+void b0(int n, char (*a)[n]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ char A0[3];
+ b0(4, &A0); // 4 != 3
+ abort();
+}
new file mode 100644
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+void b2(int m; char (*a)[m], int m) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ char A0[3];
+ b2(&A0, 4); // 4 != 3
+ abort();
+}
new file mode 100644
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+void b3(int m; char (*a)[m], int m);
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ char A0[3];
+ b3(&A0, 4); // 4 != 3
+ abort();
+}
+
+void b3(int m; char (*a)[m], int m) { }
new file mode 100644
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int n;
+void b4(char (*a)[n]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ char A0[3];
+ n = 4;
+ b4(&A0); // 4 != 3
+ abort();
+}
+
new file mode 100644
@@ -0,0 +1,73 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+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);
+
+ b0(&A0);
+ b0(&A1);
+
+ b1(4, &A0);
+
+ 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);
+
+ d0(&C0);
+ d1(3, &C0);
+
+ e0(&C0);
+ e1(4, &C0);
+
+ f0(C0);
+
+ f1(4, 3, C0);
+ f1(4, 3, D0); // 3 != 4
+ abort();
+}
new file mode 100644
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int n;
+void b5(char (*a)[n]);
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ char A0[3];
+ n = 4;
+ b5(&A0); // 4 != 3
+ abort();
+}
+
+void b5(char (*a)[n]) { }
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+static void a0(char (*a)[4]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ int u = 4;
+ int v = 3;
+
+ /* function arguments */
+
+ char A0[4];
+ char A1[u];
+ char B1[v];
+
+ a0(&A0);
+ a0(&A1);
+ a0(&B1); // 4 != 3
+ abort();
+}
new file mode 100644
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds -fpermissive" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void b1(int u, char (*a)[u]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ n = 4;
+
+ int u = 4;
+
+ char A0[4];
+ char A1[u];
+ char B0[3];
+
+ a0(&A0);
+ a0(&A1);
+
+ b1(4, &A0);
+
+ b0(&A0);
+ b0(&A1);
+ b0(&B0); // 4 != 3
+
+ abort();
+}
new file mode 100644
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int n;
+
+static void a0(char (*a)[4]) { }
+static void b0(char (*a)[n]) { }
+static void b1(int u, char (*a)[u]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ 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);
+
+ b0(&A0);
+ b0(&A1);
+
+ b1(4, &A0);
+ b1(4, &B0); // 4 != 3
+ abort();
+}
new file mode 100644
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m, n;
+
+static void c0(char (*a)[n][m]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ m = 3, n = 4;
+
+ int u = 4;
+ int v = 3;
+
+ /* function arguments */
+
+ char C0[4][3];
+ char C1[u][3];
+ char C2[4][v];
+ char C3[u][v];
+ char D0[3][4];
+
+ c0(&C0);
+ c0(&C1);
+ c0(&C2);
+ c0(&C3);
+ c0(&D0); // 4 != 4, 3 != 4
+ abort();
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m, n;
+
+static void c0(char (*a)[n][m]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ m = 3, n = 4;
+
+ int u = 4;
+ int v = 3;
+
+ /* function arguments */
+
+ char C0[4][3];
+ char C1[u][3];
+ char C2[4][v];
+ char C3[u][v];
+ char D0[3][4];
+ char D1[v][4];
+
+ c0(&C0);
+ c0(&C1);
+ c0(&C2);
+ c0(&C3);
+
+ c0(&D1); // 4 != 3, 3 != 4
+ abort();
+}
+
new file mode 100644
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m, n;
+
+static void c0(char (*a)[n][m]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ m = 3, n = 4;
+
+ int u = 4;
+ int v = 3;
+
+ /* function arguments */
+
+ 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];
+
+ c0(&C0);
+ c0(&C1);
+ c0(&C2);
+ c0(&C3);
+ c0(&D2); // 4 != 3, 3 != 4
+ abort();
+}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "-fvla-bounds" } */
+
+#include <signal.h>
+#include <stdlib.h>
+
+static void handler(int) { exit(0); }
+
+int m, n;
+
+static void c0(char (*a)[n][m]) { }
+
+int main()
+{
+ signal(SIGILL, handler);
+
+ m = 3, n = 4;
+
+ int u = 4;
+ int v = 3;
+
+ /* function arguments */
+
+ 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);
+ c0(&D3); // 4 != 3, 3 != 4
+ abort();
+}