Hi! Old OpenMP standard versions for standalone directives just said that they shouldn't be placed in places where it would make a difference for parsing other statements whether the directive is ignored or not, later versions of the standard clarified it (not completely correctly) to after if, while, do, switch and label (clearly also missing other cases like after for, else). But what both C and C++ FEs implement is everything except after label. This patch attempts to change the C and C++ FEs to also use pragma_stmt on statements after labels (labeled-statement in C++ grammar).
Bootstrapped/regtested on x86_64-linux and i686-linux, will commit tomorrow if there are no objections. 2015-11-26 Jakub Jelinek <ja...@redhat.com> PR c/63326 * c-parser.c (c_parser_compound_statement_nostart): If last_label is true, use pragma_stmt instead of pragma_compound as second c_parser_pragma argument. (c_parser_omp_ordered, c_parser_omp_target_update, c_parser_omp_target_enter_data, c_parser_omp_target_exit_data): Pass false as second argument to c_parser_skip_to_pragma_eol after diagnosing standalone directives used in pragma_stmt context. * parser.c (cp_parser_statement): Clear in_compound after labels. * gcc.dg/gomp/barrier-2.c (f2): Expect another error after label. * c-c++-common/gomp/pr63326.c: New test. * testsuite/libgomp.c/cancel-parallel-2.c (foo): Add semicolon in between case label and OpenMP standalone directives. * testsuite/libgomp.c++/cancel-parallel-2.C (foo): Likewise. --- gcc/c/c-parser.c.jj 2015-11-25 09:49:54.000000000 +0100 +++ gcc/c/c-parser.c 2015-11-26 14:26:39.757928416 +0100 @@ -4729,7 +4729,8 @@ c_parser_compound_statement_nostart (c_p syntactically. This ensures that the user doesn't put them places that would turn into syntax errors if the directive were ignored. */ - if (c_parser_pragma (parser, pragma_compound)) + if (c_parser_pragma (parser, + last_label ? pragma_stmt : pragma_compound)) last_label = false, last_stmt = true; } else if (c_parser_next_token_is (parser, CPP_EOF)) @@ -14988,7 +14989,7 @@ c_parser_omp_ordered (c_parser *parser, error_at (loc, "%<#pragma omp ordered%> with %<depend> clause may " "only be used in compound statements"); - c_parser_skip_to_pragma_eol (parser); + c_parser_skip_to_pragma_eol (parser, false); return false; } @@ -15636,7 +15637,7 @@ c_parser_omp_target_update (location_t l error_at (loc, "%<#pragma omp target update%> may only be " "used in compound statements"); - c_parser_skip_to_pragma_eol (parser); + c_parser_skip_to_pragma_eol (parser, false); return false; } @@ -15696,7 +15697,7 @@ c_parser_omp_target_enter_data (location error_at (loc, "%<#pragma omp target enter data%> may only be " "used in compound statements"); - c_parser_skip_to_pragma_eol (parser); + c_parser_skip_to_pragma_eol (parser, false); return NULL_TREE; } @@ -15781,7 +15782,7 @@ c_parser_omp_target_exit_data (location_ error_at (loc, "%<#pragma omp target exit data%> may only be " "used in compound statements"); - c_parser_skip_to_pragma_eol (parser); + c_parser_skip_to_pragma_eol (parser, false); return NULL_TREE; } --- gcc/cp/parser.c.jj 2015-11-25 09:49:55.000000000 +0100 +++ gcc/cp/parser.c 2015-11-26 15:04:16.914842804 +0100 @@ -10003,6 +10003,7 @@ cp_parser_statement (cp_parser* parser, Parse the label, and then use tail recursion to parse the statement. */ cp_parser_label_for_labeled_statement (parser, std_attrs); + in_compound = false; goto restart; case RID_IF: @@ -10100,6 +10101,7 @@ cp_parser_statement (cp_parser* parser, the statement. */ cp_parser_label_for_labeled_statement (parser, std_attrs); + in_compound = false; goto restart; } } --- gcc/testsuite/gcc.dg/gomp/barrier-2.c.jj 2008-09-05 12:54:26.000000000 +0200 +++ gcc/testsuite/gcc.dg/gomp/barrier-2.c 2015-11-26 15:27:50.990679259 +0100 @@ -16,7 +16,7 @@ void f1(void) void f2(void) { label: /* { dg-error "label at end of compound statement" } */ - #pragma omp barrier + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ } void f3(_Bool p) --- gcc/testsuite/c-c++-common/gomp/pr63326.c.jj 2015-11-26 13:54:17.572711016 +0100 +++ gcc/testsuite/c-c++-common/gomp/pr63326.c 2015-11-26 15:15:01.658689775 +0100 @@ -0,0 +1,479 @@ +/* PR c/63326 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +void +f1 (int x) +{ + int i; + if (x) + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + if (x) + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + if (x) + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + if (x) + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + #pragma omp parallel + { + if (x) + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + if (x) + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + if (x) + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + if (x) + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + if (x) + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + if (x) + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + if (x) + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; +} + +void +f2 (int x) +{ + int i; + while (x) + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + while (x) + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + while (x) + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + while (x) + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + #pragma omp parallel + { + while (x) + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + while (x) + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + while (x) + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + while (x) + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + while (x) + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + while (x) + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + while (x) + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; +} + +void +f3 (int x) +{ + int i; + for (x = 0; x < 10; x++) + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + for (x = 0; x < 10; x++) + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + for (x = 0; x < 10; x++) + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + for (x = 0; x < 10; x++) + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + #pragma omp parallel + { + for (x = 0; x < 10; x++) + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + for (x = 0; x < 10; x++) + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + for (x = 0; x < 10; x++) + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + for (x = 0; x < 10; x++) + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + for (x = 0; x < 10; x++) + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + for (x = 0; x < 10; x++) + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + for (x = 0; x < 10; x++) + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; +} + +void +f4 (int x) +{ + int i; + { + do + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + { + do + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + { + do + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + { + do + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + #pragma omp parallel + { + do + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + #pragma omp parallel + { + do + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + { + do + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + { + do + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + } + { + do + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + { + do + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ + { + do + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + while (0); + } /* { dg-error "before" "" { target c++ } } */ +} + +void +f5 (int x) +{ + int i; + switch (x) + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + switch (x) + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + switch (x) + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + switch (x) + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + #pragma omp parallel + { + switch (x) + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + switch (x) + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + switch (x) + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + switch (x) + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + switch (x) + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + switch (x) + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; +} + +void +f6 (int x) +{ + int i; + switch (x) + { + case 1: + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + case 1: + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + case 1: + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + case 1: + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + switch (x) + { + case 1: + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + } + #pragma omp parallel + { + switch (x) + { + case 1: + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + switch (x) + { + case 1: + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + case 1: + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + } + switch (x) + { + case 1: + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + case 1: + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + case 1: + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; + } +} + +void +f7 (int x) +{ + int i; + switch (x) + { + default: + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + default: + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + default: + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + default: + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + switch (x) + { + default: + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + } + #pragma omp parallel + { + switch (x) + { + default: + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + switch (x) + { + default: + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + default: + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + } + switch (x) + { + default: + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + default: + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + } + switch (x) + { + default: + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; + } +} + +void +f8 (int x) +{ + int i; + lab1: + #pragma omp barrier /* { dg-error "may only be used in compound statements" } */ + ; + lab2: + #pragma omp flush /* { dg-error "may only be used in compound statements" } */ + ; + lab3: + #pragma omp taskwait /* { dg-error "may only be used in compound statements" } */ + ; + lab4: + #pragma omp taskyield /* { dg-error "may only be used in compound statements" } */ + ; + #pragma omp parallel + { + lab5: + #pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp parallel + { + lab6: + #pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */ + ; + } + #pragma omp for ordered(1) + for (i = 0; i < 16; i++) + { + lab7: + #pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */ + ; + lab8: + #pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */ + ; + } + lab9: + #pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */ + ; + lab10: + #pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */ + ; + lab11: + #pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */ + ; +} --- libgomp/testsuite/libgomp.c/cancel-parallel-2.c.jj 2013-10-11 11:23:59.000000000 +0200 +++ libgomp/testsuite/libgomp.c/cancel-parallel-2.c 2015-11-26 15:35:47.477857521 +0100 @@ -13,7 +13,7 @@ foo (int *x) int thr = omp_get_thread_num (); switch (x[thr]) { - case 4: + case 4:; #pragma omp cancel parallel break; case 3: @@ -27,7 +27,7 @@ foo (int *x) case 2: usleep (1000); /* FALLTHRU */ - case 1: + case 1:; #pragma omp cancellation point parallel break; } --- libgomp/testsuite/libgomp.c++/cancel-parallel-2.C.jj 2013-10-11 11:23:59.000000000 +0200 +++ libgomp/testsuite/libgomp.c++/cancel-parallel-2.C 2015-11-26 15:36:04.280615978 +0100 @@ -17,7 +17,7 @@ foo (int *x) int thr = omp_get_thread_num (); switch (x[thr]) { - case 4: + case 4:; #pragma omp cancel parallel break; case 3: @@ -31,7 +31,7 @@ foo (int *x) case 2: usleep (1000); /* FALLTHRU */ - case 1: + case 1:; #pragma omp cancellation point parallel break; } Jakub