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 | 2 +- gcc/testsuite/gcc.dg/vla-bounds-func-10.c | 74 +++++++++++ gcc/testsuite/gcc.dg/vla-bounds-func-11.c | 28 ++++ gcc/testsuite/gcc.dg/vla-bounds-func-12.c | 29 +++++ gcc/testsuite/gcc.dg/vla-bounds-func-13.c | 37 ++++++ gcc/testsuite/gcc.dg/vla-bounds-func-14.c | 15 +++ gcc/testsuite/gcc.dg/vla-bounds-func-15.c | 20 +++ gcc/testsuite/gcc.dg/vla-bounds-func-16.c | 18 +++ gcc/testsuite/gcc.dg/vla-bounds-func-17.c | 18 +++ gcc/testsuite/gcc.dg/vla-bounds-func-18.c | 20 +++ gcc/testsuite/gcc.dg/vla-bounds-func-19.c | 21 +++ gcc/testsuite/gcc.dg/vla-bounds-func-2.c | 73 +++++++++++ gcc/testsuite/gcc.dg/vla-bounds-func-20.c | 22 ++++ gcc/testsuite/gcc.dg/vla-bounds-func-3.c | 28 ++++ gcc/testsuite/gcc.dg/vla-bounds-func-4.c | 37 ++++++ gcc/testsuite/gcc.dg/vla-bounds-func-5.c | 40 ++++++ gcc/testsuite/gcc.dg/vla-bounds-func-6.c | 36 ++++++ gcc/testsuite/gcc.dg/vla-bounds-func-7.c | 39 ++++++ gcc/testsuite/gcc.dg/vla-bounds-func-8.c | 38 ++++++ gcc/testsuite/gcc.dg/vla-bounds-func-9.c | 39 ++++++ 21 files changed, 769 insertions(+), 16 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 59940a29b53..c0132a22e21 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -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); diff --git a/gcc/testsuite/gcc.dg/vla-bounds-func-1.c b/gcc/testsuite/gcc.dg/vla-bounds-func-1.c index 8256999fc50..378c6073688 100644 --- a/gcc/testsuite/gcc.dg/vla-bounds-func-1.c +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-1.c @@ -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." */ } 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..ad1b6e44923 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-10.c @@ -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(); +} 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..45095023d18 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-11.c @@ -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(); +} 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..2c033761eac --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-12.c @@ -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(); +} 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..3919f320643 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-13.c @@ -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(); +} 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..10678d10237 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-14.c @@ -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]) { } + 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..778a7c03219 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-15.c @@ -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]) { } 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..1da4d2632f2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-16.c @@ -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(); +} 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..2b52391ef59 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-17.c @@ -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(); +} 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..61395c22e8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-18.c @@ -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) { } 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..4b57580ac94 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-19.c @@ -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(); +} + 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..f00c7e15774 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-2.c @@ -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(); +} 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..c0c7a9c637b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-20.c @@ -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]) { } 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..90e37d65365 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-3.c @@ -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(); +} 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..9b7173fee46 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-4.c @@ -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(); +} 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..37ff64148ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-5.c @@ -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(); +} 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..c678e6b450a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-6.c @@ -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(); +} 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..40a6252dbc7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-7.c @@ -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(); +} + 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..d89d7465fd5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-8.c @@ -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(); +} 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..2f71edb208a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vla-bounds-func-9.c @@ -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(); +} -- 2.39.2