From 410df0843dbf08280813165bca72cfdaa21c8f23 Mon Sep 17 00:00:00 2001 From: Sandra Loosemore Date: Thu, 24 Aug 2023 17:35:01 +0000 Subject: OpenMP: New C/C++ testcases for imperfectly nested loops. gcc/testsuite/ChangeLog * c-c++-common/gomp/imperfect-attributes.c: New. * c-c++-common/gomp/imperfect-badloops.c: New. * c-c++-common/gomp/imperfect-blocks.c: New. * c-c++-common/gomp/imperfect-extension.c: New. * c-c++-common/gomp/imperfect-gotos.c: New. * c-c++-common/gomp/imperfect-invalid-scope.c: New. * c-c++-common/gomp/imperfect-labels.c: New. * c-c++-common/gomp/imperfect-legacy-syntax.c: New. * c-c++-common/gomp/imperfect-pragmas.c: New. * c-c++-common/gomp/imperfect1.c: New. * c-c++-common/gomp/imperfect2.c: New. * c-c++-common/gomp/imperfect3.c: New. * c-c++-common/gomp/imperfect4.c: New. * c-c++-common/gomp/imperfect5.c: New. libgomp/ChangeLog * testsuite/libgomp.c-c++-common/imperfect1.c: New. * testsuite/libgomp.c-c++-common/imperfect2.c: New. * testsuite/libgomp.c-c++-common/imperfect3.c: New. * testsuite/libgomp.c-c++-common/imperfect4.c: New. * testsuite/libgomp.c-c++-common/imperfect5.c: New. * testsuite/libgomp.c-c++-common/imperfect6.c: New. * testsuite/libgomp.c-c++-common/target-imperfect1.c: New. * testsuite/libgomp.c-c++-common/target-imperfect2.c: New. * testsuite/libgomp.c-c++-common/target-imperfect3.c: New. * testsuite/libgomp.c-c++-common/target-imperfect4.c: New. --- .../c-c++-common/gomp/imperfect-attributes.c | 81 ++++++++++ .../c-c++-common/gomp/imperfect-badloops.c | 50 ++++++ gcc/testsuite/c-c++-common/gomp/imperfect-blocks.c | 75 +++++++++ .../c-c++-common/gomp/imperfect-extension.c | 55 +++++++ gcc/testsuite/c-c++-common/gomp/imperfect-gotos.c | 174 +++++++++++++++++++++ .../c-c++-common/gomp/imperfect-invalid-scope.c | 77 +++++++++ gcc/testsuite/c-c++-common/gomp/imperfect-labels.c | 85 ++++++++++ .../c-c++-common/gomp/imperfect-legacy-syntax.c | 44 ++++++ .../c-c++-common/gomp/imperfect-pragmas.c | 85 ++++++++++ gcc/testsuite/c-c++-common/gomp/imperfect1.c | 38 +++++ gcc/testsuite/c-c++-common/gomp/imperfect2.c | 34 ++++ gcc/testsuite/c-c++-common/gomp/imperfect3.c | 52 ++++++ gcc/testsuite/c-c++-common/gomp/imperfect4.c | 33 ++++ gcc/testsuite/c-c++-common/gomp/imperfect5.c | 95 +++++++++++ 14 files changed, 978 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-badloops.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-blocks.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-extension.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-gotos.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-invalid-scope.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-labels.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-legacy-syntax.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect-pragmas.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect2.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect3.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect4.c create mode 100644 gcc/testsuite/c-c++-common/gomp/imperfect5.c (limited to 'gcc') diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c b/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c new file mode 100644 index 0000000..776295c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-attributes.c @@ -0,0 +1,81 @@ +/* { dg-do compile { target { c || c++11 } } } */ + +/* Check that a nested FOR loop with standard c/c++ attributes on it + is treated as intervening code, since it doesn't match the grammar + for canonical loop nest form. */ + +extern void do_something (void); + +void imperfect1 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + { + [[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } +} + +void perfect1 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + { + [[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } +} + +/* Similar, but put the attributes on a block wrapping the nested loop + instead. */ + +void imperfect2 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + { + [[]] + { + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } + } +} + +void perfect2 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + { + [[]] + { + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } + } +} + +/* Make sure attributes are accepted in the innermost loop body, which has + no intervening code restrictions. */ + +void imperfect3 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { + [[]] do_something (); + } +} + +void perfect3 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { + [[]] do_something (); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-badloops.c b/gcc/testsuite/c-c++-common/gomp/imperfect-badloops.c new file mode 100644 index 0000000..dfd40b6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-badloops.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ + +/* This test case is expected to fail due to errors. */ + +int f1 (int depth, int iter); +int f2 (int depth, int iter); +void do_something (void); + +void s1 (int a1, int a2, int a3) +{ + int i, j, k; + +#pragma omp for collapse(3) + for (i = 0; i < a1; i++) + { + f1 (0, i); + if (a1 < a2) + { + int z = 0; + while (z < i) /* { dg-error "loop not permitted in intervening code " } */ + { + do_something (); + z++; + } + do /* { dg-error "loop not permitted in intervening code " } */ + { + do_something (); + z--; + } while (z >= 0); + } + for (j = 0; j < a2; j++) + { + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + if (a1 < a3) + { + int z; + for (z = 0; z < i; z++) /* { dg-error "loop not permitted in intervening code " } */ + { + do_something (); + } + } + f2 (0, i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-blocks.c b/gcc/testsuite/c-c++-common/gomp/imperfect-blocks.c new file mode 100644 index 0000000..0fea58f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-blocks.c @@ -0,0 +1,75 @@ +/* { dg-do compile } */ + +/* Check that compound statements in intervening code are correctly + handled. */ + +extern void do_something (void); + +void imperfect1 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + { + {} + for (int j = 0; j < y; j++) + do_something (); + } +} + +void perfect1 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "inner loops must be perfectly nested" } */ + { + {} + for (int j = 0; j < y; j++) + do_something (); + } +} + +void imperfect2 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + { + for (int j = 0; j < y; j++) + do_something (); + {} + } +} + +void perfect2 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < y; j++) + do_something (); + {} + } +} + +void imperfect3 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + { + { do_something (); } + for (int j = 0; j < y; j++) + do_something (); + { do_something (); } + } +} + +void perfect3 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "inner loops must be perfectly nested" } */ + { + { do_something (); } + for (int j = 0; j < y; j++) + do_something (); + { do_something (); } + } +} + diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-extension.c b/gcc/testsuite/c-c++-common/gomp/imperfect-extension.c new file mode 100644 index 0000000..a8a8f9e --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-extension.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ + +/* Check that __extension__ introduces intervening code. */ + +extern void do_something (void); + +void imperfect1 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + { + __extension__ ({ + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + }); + } +} + +void perfect1 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + { + __extension__ ({ + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + }); + } +} + +/* Check that we don't barf on __extension__ in the inner loop body. */ +void imperfect2 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { + __extension__ ({ + do_something (); + }); + } +} + +void perfect2 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { + __extension__ ({ + do_something (); + }); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-gotos.c b/gcc/testsuite/c-c++-common/gomp/imperfect-gotos.c new file mode 100644 index 0000000..897eed2 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-gotos.c @@ -0,0 +1,174 @@ +/* { dg-do compile } */ + +/* This file contains tests that are expected to fail. */ + + +/* These jumps are all OK since they are to/from the same structured block. */ + +void f1a (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + goto a; a:; + for (int j = 0; j < 64; ++j) + { + goto c; c:; + } + goto b; b:; + } +} + +/* Jump around loop body to/from different structured blocks of intervening + code. */ +void f2a (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + goto a; a:; + if (i > 16) goto b; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + for (int j = 0; j < 64; ++j) + { + goto c; c:; + } + goto b; b:; + } +} + +/* Jump into loop body from intervening code. */ +void f3a (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + goto a; a:; + if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + for (int j = 0; j < 64; ++j) + { + c: + ; + } + goto b; b:; + } +} + +/* Jump out of loop body to intervening code. */ +void f4a (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + goto a; a:; + for (int j = 0; j < 64; ++j) + if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + c: + ; + goto b; b:; + } +} + +/* The next group of tests use the GNU extension for local labels. Expected + behavior is the same as the above group. */ + +/* These jumps are all OK since they are to/from the same structured block. */ + +void f1b (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + __label__ a, b, c; + goto a; a:; + for (int j = 0; j < 64; ++j) + { + goto c; c:; + } + goto b; b:; + } +} + +/* Jump around loop body to/from different structured blocks of intervening + code. */ +void f2b (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + __label__ a, b, c; + goto a; a:; + if (i > 16) goto b; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + for (int j = 0; j < 64; ++j) + { + goto c; c:; + } + goto b; b:; + } +} + +/* Jump into loop body from intervening code. */ +void f3b (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + __label__ a, b, c; + goto a; a:; + if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + for (int j = 0; j < 64; ++j) + { + c: + ; + } + goto b; b:; + } +} + +/* Jump out of loop body to intervening code. */ +void f4b (void) +{ +#pragma omp for collapse(2) + for (int i = 0; i < 64; ++i) + { + __label__ a, b, c; + goto a; a:; + for (int j = 0; j < 64; ++j) + if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + c: + ; + goto b; b:; + } +} + +/* Test that the even the valid jumps are rejected when intervening code + is not allowed at all. */ + +void f1c (void) +{ +#pragma omp for ordered(2) + for (int i = 0; i < 64; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + goto a; a:; + for (int j = 0; j < 64; ++j) + { + goto c; c:; + } + goto b; b:; + } +} + +void f1d (void) +{ +#pragma omp for ordered(2) + for (int i = 0; i < 64; ++i) /* { dg-error "inner loops must be perfectly nested" } */ + { + __label__ a, b, c; + goto a; a:; + for (int j = 0; j < 64; ++j) + { + goto c; c:; + } + goto b; b:; + } +} + diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-invalid-scope.c b/gcc/testsuite/c-c++-common/gomp/imperfect-invalid-scope.c new file mode 100644 index 0000000..5c24aae --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-invalid-scope.c @@ -0,0 +1,77 @@ +/* { dg-do compile } */ + +/* Check that various cases of invalid references to variables bound + in an intervening code scope are diagnosed and do not ICE. This test + is expected to produce errors. */ + +extern void foo (int, int); + +void f1 (void) +{ +#pragma omp for collapse (2) + for (int i = 0; i < 64; i++) + { + int v = (i + 4) * 2; + for (int j = v; j < 64; j++) /* { dg-error "initializer is bound in intervening code" } */ + foo (i, j); + } +} + +void f2 (void) +{ +#pragma omp for collapse (2) + for (int i = 0; i < 64; i++) + { + int v = (i + 4) * 2; + for (int j = 0; j < v; j++) /* { dg-error "end test is bound in intervening code" } */ + foo (i, j); + } +} + +void f3 (void) +{ +#pragma omp for collapse (2) + for (int i = 0; i < 64; i++) + { + int v = (i + 4) * 2; + for (int j = 0; j < 64; j = j + v) /* { dg-error "increment expression is bound in intervening code" } */ + foo (i, j); + } +} + +void f4 (void) +{ +#pragma omp for collapse (2) + for (int i = 0; i < 64; i++) + { + int v = 8; + for (int j = v; j < 64; j++) /* { dg-error "initializer is bound in intervening code" } */ + foo (i, j); + } +} + +void f5 (void) +{ +#pragma omp for collapse (2) + for (int i = 0; i < 64; i++) + { + int j; + for (j = 0; j < 64; j++) /* { dg-error "loop variable is bound in intervening code" } */ + foo (i, j); + } +} + +void f6 (void) +{ +#pragma omp for collapse (2) + for (int i = 0; i < 64; i++) + { + int j; + { + int v = 8; + for (j = v; j < 64; j++) /* { dg-error "loop variable is bound in intervening code" } */ + /* { dg-error "initializer is bound in intervening code" "" { target *-*-* } .-1 } */ + foo (i, j); + } + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-labels.c b/gcc/testsuite/c-c++-common/gomp/imperfect-labels.c new file mode 100644 index 0000000..b7a7a4c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-labels.c @@ -0,0 +1,85 @@ +/* { dg-do compile } */ + +/* Check that a nested FOR loop with a label on it is treated as + intervening code, since it doesn't match the grammar for canonical + loop nest form. */ + +extern void do_something (void); + +void imperfect1 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + { + foo: + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } +} + +void perfect1 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + { + foo: + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } +} + + +/* Similar, but put the label on a block wrapping the nested loop instead. */ + +void imperfect2 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + { + foo: + { + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } + } +} + +void perfect2 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + { + foo: + { + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } + } +} + +/* Sanity check that labels are allowed in the innermost loop body. */ + +void imperfect3 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { + foo: + do_something (); + } +} + +void perfect3 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { + foo: + do_something (); + } +} + diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-legacy-syntax.c b/gcc/testsuite/c-c++-common/gomp/imperfect-legacy-syntax.c new file mode 100644 index 0000000..571e067 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-legacy-syntax.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ + +/* Braces may enclose a nested FOR even when intervening code is not + permitted. Before GCC implemented OpenMP 5.1 canonical loop syntax + and support for intervening code, it used to ignore empty statements + instead of treating them as intervening code; as an extension, those + are still accepted without complaint even in constructs where intervening + code is not supposed to be valid. */ + +void s1 (int a1, int a2, int a3) +{ + int i, j, k; + +#pragma omp for ordered(3) + for (i = 0; i < a1; i++) + { + for (j = 0; j < a2; j++) + { + for (k = 0; k < a3; k++) + { + } + } + } +} + +void s2 (int a1, int a2, int a3) +{ + int i, j, k; + +#pragma omp for ordered(3) + for (i = 0; i < a1; i++) + { + ; + for (j = 0; j < a2; j++) + { + ; + for (k = 0; k < a3; k++) + { + } + ; + } + ; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect-pragmas.c b/gcc/testsuite/c-c++-common/gomp/imperfect-pragmas.c new file mode 100644 index 0000000..a9f5522 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect-pragmas.c @@ -0,0 +1,85 @@ +/* { dg-do compile } */ + +/* Check that non-statement pragmas are accepted in a canonical loop nest + even when perfect nesting is required. */ + +extern void do_something (void); + +void imperfect1 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + { +#pragma GCC diagnostic push + for (int j = 0; j < y; j++) + do_something (); +#pragma GCC diagnostic pop + } +} + +void perfect1 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) + { +#pragma GCC diagnostic push + for (int j = 0; j < y; j++) + do_something (); +#pragma GCC diagnostic pop + } +} + + +/* "GCC unroll" is a statement pragma that consumes the following loop as + a substatement. Thus, the inner loop should be treated as intervening + code rather than part of the loop nest. */ + +void imperfect2 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + { +#pragma GCC unroll 4 + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } +} + +void perfect2 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */ + /* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */ + { +#pragma GCC unroll 4 + for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */ + do_something (); + } +} + + +/* Check that statement pragmas are accepted in the innermost loop body. */ + +void imperfect3 (int x, int y) +{ +#pragma omp for collapse (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { +#pragma GCC unroll 4 + for (int k = 0; k < 4; k++) + do_something (); + } +} + +void perfect3 (int x, int y) +{ +#pragma omp for ordered (2) + for (int i = 0; i < x; i++) + for (int j = 0; j < y; j++) + { +#pragma GCC unroll 4 + for (int k = 0; k < 4; k++) + do_something (); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect1.c b/gcc/testsuite/c-c++-common/gomp/imperfect1.c new file mode 100644 index 0000000..705626a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect1.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ + +/* This test case is expected to fail due to errors. */ + +int f1 (int depth, int iter); +int f2 (int depth, int iter); + +void s1 (int a1, int a2, int a3) +{ + int i, j, k; + +#pragma omp for collapse(3) + for (i = 0; i < a1; i++) + { + f1 (0, i); + for (j = 0; j < a2; j++) + { +#pragma omp barrier /* { dg-error "intervening code must not contain OpenMP directives" } */ + f1 (1, j); + if (i == 2) + continue; /* { dg-error "invalid exit" } */ + else + break; /* { dg-error "invalid exit" } */ + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + for (k = 0; k < a3; k++) /* { dg-error "loop not permitted in intervening code " } */ + { + f1 (2, k); + f2 (2, k); + } + f2 (0, i); + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect2.c b/gcc/testsuite/c-c++-common/gomp/imperfect2.c new file mode 100644 index 0000000..dff17dd --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect2.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ + +/* This test case is expected to fail due to errors. */ + +/* These functions that are part of the OpenMP runtime API would ordinarily + be declared in omp.h, but we don't have that here. */ +extern int omp_get_num_threads(void); +extern int omp_get_max_threads(void); + +int f1 (int depth, int iter); +int f2 (int depth, int iter); + +void s1 (int a1, int a2, int a3) +{ + int i, j, k; +#pragma omp for collapse(3) + for (i = 0; i < a1; i++) + { + f1 (0, i); + for (j = 0; j < omp_get_num_threads (); j++) /* This is OK */ + { + f1 (1, omp_get_num_threads ()); /* { dg-error "not permitted in intervening code" } */ + for (k = omp_get_num_threads (); k < a3; k++) /* This is OK */ + { + f1 (2, omp_get_num_threads ()); + f2 (2, omp_get_max_threads ()); + } + f2 (1, omp_get_max_threads ()); /* { dg-error "not permitted in intervening code" } */ + } + f2 (0, i); + } +} + + diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect3.c b/gcc/testsuite/c-c++-common/gomp/imperfect3.c new file mode 100644 index 0000000..b2b46c1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect3.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ + +/* This test case is expected to fail due to errors. */ + +/* Test that the imperfectly-nested loops with the ordered clause gives + an error, and that there is only one error (and not one on every + intervening statement). */ + +int f1 (int depth, int iter); +int f2 (int depth, int iter); + +void s1 (int a1, int a2, int a3) +{ + int i, j, k; + + /* This loop without intervening code ought to be OK. */ +#pragma omp for ordered(3) + for (i = 0; i < a1; i++) + { + for (j = 0; j < a2; j++) + { + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); +#pragma omp ordered doacross(source:omp_cur_iteration) +#pragma omp ordered doacross(sink: i - 2, j + 2, k - 1) + } + } + } + + /* Now add intervening code. */ +#pragma omp for ordered(3) + for (i = 0; i < a1; i++) /* { dg-error "inner loops must be perfectly nested" } */ + { + f1 (0, i); + for (j = 0; j < a2; j++) + { + f1 (1, j); + for (k = 0; k < a3; k++) + { + f1 (2, k); + f2 (2, k); +#pragma omp ordered doacross(source:omp_cur_iteration) +#pragma omp ordered doacross(sink: i - 2, j + 2, k - 1) + } + f2 (1, j); + } + f2 (0, i); + } +} + diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect4.c b/gcc/testsuite/c-c++-common/gomp/imperfect4.c new file mode 100644 index 0000000..1a0c07c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect4.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ + +/* This test case is expected to fail due to errors. */ + +int f1 (int depth, int iter); +int f2 (int depth, int iter); + +void s1 (int a1, int a2, int a3) +{ + int i, j, k; + +#pragma omp for collapse(4) + for (i = 0; i < a1; i++) /* { dg-error "not enough nested loops" } */ + { + f1 (0, i); + for (j = 0; j < a2; j++) + { + f1 (1, j); + for (k = 0; k < a3; k++) + { + /* According to the grammar, this is intervening code; we + don't know that we are also missing a nested for loop + until we have parsed this whole compound expression. */ +#pragma omp barrier /* { dg-error "intervening code must not contain OpenMP directives" } */ + f1 (2, k); + f2 (2, k); + } + f2 (1, j); + } + f2 (0, i); + } +} + diff --git a/gcc/testsuite/c-c++-common/gomp/imperfect5.c b/gcc/testsuite/c-c++-common/gomp/imperfect5.c new file mode 100644 index 0000000..da92578 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/imperfect5.c @@ -0,0 +1,95 @@ +/* { dg-do compile } */ + +/* This test case is expected to fail due to errors. */ + +#define N 30 +#define M 3 + +int a[N][M], b[N][M], c[N][M]; + +extern void dostuff (int, int); + +/* good1 and good2 should compile without error. */ +void +good1 (void) +{ + int x, shift; + + x = 0; + #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift) + for (int i = 0; i < N; i++) + { + for (int j = 0; j < M; j++) + { + x += a[i][j]; + x += b[i][j]; +#pragma omp scan inclusive(x) + shift = i + 29*j; + c[i][j] = x + shift; + } + } +} + +void +good2 (void) +{ + int x, shift; + x = 0; + + #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift) + for (int i = 0; i < N; i++) + { + for (int j = 0; j < M; j++) + { + shift = i + 29*j; + c[i][j] = x + shift; +#pragma omp scan exclusive(x) + x += a[i][j]; + x += b[i][j]; + } + } +} + +/* Adding intervening code should trigger an error. */ + +void +bad1 (void) +{ + int x, shift; + + x = 0; + #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift) + for (int i = 0; i < N; i++) /* { dg-error "inner loops must be perfectly nested" } */ + { + dostuff (i, 0); + for (int j = 0; j < M; j++) + { + x += a[i][j]; + x += b[i][j]; +#pragma omp scan inclusive(x) + shift = i + 29*j; + c[i][j] = x + shift; + } + } +} + +void +bad2 (void) +{ + int x, shift; + x = 0; + + #pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift) + for (int i = 0; i < N; i++) /* { dg-error "inner loops must be perfectly nested" } */ + { + for (int j = 0; j < M; j++) + { + shift = i + 29*j; + c[i][j] = x + shift; +#pragma omp scan exclusive(x) + x += a[i][j]; + x += b[i][j]; + } + dostuff (i, 1); + } +} -- cgit v1.1