Hi! As has been clarified, it is intentional that nothing directive is accepted in substatements of selection and looping statements and after labels and is handled as if the directive just isn't there, so that void foo (int x) { if (x) #pragma omp metadirective when (...:nothing) when (...:parallel) bar (); } behaves consistently; declarative and stand-alone directives aren't allowed at that point, but constructs are parsed with the following statement as the construct body and nothing or missing default on metadirective therefore should handle the following statement as part of the if substatement instead of having nothing as the substatement and bar done unconditionally after the if.
Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk. 2021-08-18 Jakub Jelinek <ja...@redhat.com> gcc/c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_NOTHING. * c-pragma.c (omp_pragmas): Add nothing directive. * c-omp.c (omp_directives): Uncomment nothing directive entry. gcc/c/ * c-parser.c (c_parser_omp_nothing): New function. (c_parser_pragma): Handle PRAGMA_OMP_NOTHING. gcc/cp/ * parser.c (cp_parser_omp_nothing): New function. (cp_parser_pragma): Handle PRAGMA_OMP_NOTHING. gcc/testsuite/ * c-c++-common/gomp/nothing-1.c: New test. * g++.dg/gomp/attrs-1.C (bar): Add nothing directive test. * g++.dg/gomp/attrs-2.C (bar): Likewise. * g++.dg/gomp/attrs-9.C: Likewise. libgomp/ * testsuite/libgomp.c-c++-common/nothing-1.c: New test. --- gcc/c-family/c-pragma.h.jj 2021-08-17 16:34:27.337162267 +0200 +++ gcc/c-family/c-pragma.h 2021-08-18 10:37:24.315862393 +0200 @@ -57,6 +57,7 @@ enum pragma_kind { PRAGMA_OMP_FLUSH, PRAGMA_OMP_FOR, PRAGMA_OMP_LOOP, + PRAGMA_OMP_NOTHING, PRAGMA_OMP_MASKED, PRAGMA_OMP_MASTER, PRAGMA_OMP_ORDERED, --- gcc/c-family/c-pragma.c.jj 2021-08-17 16:34:27.337162267 +0200 +++ gcc/c-family/c-pragma.c 2021-08-18 10:37:24.322862295 +0200 @@ -1328,6 +1328,7 @@ static const struct omp_pragma_def omp_p { "depobj", PRAGMA_OMP_DEPOBJ }, { "end", PRAGMA_OMP_END_DECLARE_TARGET }, { "flush", PRAGMA_OMP_FLUSH }, + { "nothing", PRAGMA_OMP_NOTHING }, { "requires", PRAGMA_OMP_REQUIRES }, { "scope", PRAGMA_OMP_SCOPE }, { "section", PRAGMA_OMP_SECTION }, --- gcc/c-family/c-omp.c.jj 2021-08-17 09:29:41.399205020 +0200 +++ gcc/c-family/c-omp.c 2021-08-18 10:37:24.330862182 +0200 @@ -3007,8 +3007,8 @@ static const struct c_omp_directive omp_ C_OMP_DIR_CONSTRUCT, true }, /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE, C_OMP_DIR_???, ??? }, */ - /* { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING, - C_OMP_DIR_UTILITY, false }, */ + { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING, + C_OMP_DIR_UTILITY, false }, /* ordered with depend clause is C_OMP_DIR_STANDALONE. */ { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED, C_OMP_DIR_CONSTRUCT, true }, --- gcc/c/c-parser.c.jj 2021-08-18 10:20:44.518932305 +0200 +++ gcc/c/c-parser.c 2021-08-18 10:37:24.332862154 +0200 @@ -1578,6 +1578,7 @@ static tree c_parser_omp_for_loop (locat static void c_parser_omp_taskwait (c_parser *); static void c_parser_omp_taskyield (c_parser *); static void c_parser_omp_cancel (c_parser *); +static void c_parser_omp_nothing (c_parser *); enum pragma_context { pragma_external, pragma_struct, pragma_param, pragma_stmt, pragma_compound }; @@ -12480,6 +12481,10 @@ c_parser_pragma (c_parser *parser, enum c_parser_omp_requires (parser); return false; + case PRAGMA_OMP_NOTHING: + c_parser_omp_nothing (parser); + return false; + case PRAGMA_OMP_ORDERED: return c_parser_omp_ordered (parser, context, if_p); @@ -21908,6 +21913,16 @@ c_parser_omp_taskloop (location_t loc, c return ret; } +/* OpenMP 5.1 + #pragma omp nothing new-line */ + +static void +c_parser_omp_nothing (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); +} + /* Main entry point to parsing most OpenMP pragmas. */ static void --- gcc/cp/parser.c.jj 2021-08-18 10:20:44.523932234 +0200 +++ gcc/cp/parser.c 2021-08-18 10:37:24.336862098 +0200 @@ -45564,6 +45564,16 @@ cp_parser_omp_requires (cp_parser *parse } +/* OpenMP 5.1: + #pragma omp nothing new-line */ + +static void +cp_parser_omp_nothing (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_skip_to_pragma_eol (parser, pragma_tok); +} + + /* OpenMP 4.5: #pragma omp taskloop taskloop-clause[optseq] new-line for-loop @@ -46673,6 +46683,10 @@ cp_parser_pragma (cp_parser *parser, enu } return cp_parser_omp_requires (parser, pragma_tok); + case PRAGMA_OMP_NOTHING: + cp_parser_omp_nothing (parser, pragma_tok); + return false; + case PRAGMA_OMP_ORDERED: if (context != pragma_stmt && context != pragma_compound) goto bad_stmt; --- gcc/testsuite/c-c++-common/gomp/nothing-1.c.jj 2021-08-18 10:38:12.299187443 +0200 +++ gcc/testsuite/c-c++-common/gomp/nothing-1.c 2021-08-17 15:25:37.215306202 +0200 @@ -0,0 +1,37 @@ +#pragma omp nothing + +struct S +{ + #pragma omp nothing + int s; +}; + +int +foo (int i) +{ + #pragma omp nothing + if (0) + #pragma omp nothing + i++; + if (1) + ; + else + #pragma omp nothing + i++; + switch (0) + #pragma omp nothing + { + default: + break; + } + while (0) + #pragma omp nothing + i++; + for (; 0;) + #pragma omp nothing + i++; + lab: + #pragma omp nothing + i++; + return i; +} --- gcc/testsuite/g++.dg/gomp/attrs-1.C.jj 2021-08-17 09:29:41.838199049 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-1.C 2021-08-18 10:48:30.539491077 +0200 @@ -111,6 +111,7 @@ void bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) { + [[omp::directive (nothing)]]; [[omp::directive (for simd private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) order(concurrent) allocate (f))]] --- gcc/testsuite/g++.dg/gomp/attrs-2.C.jj 2021-08-17 09:29:41.838199049 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-2.C 2021-08-18 10:48:53.926162111 +0200 @@ -111,6 +111,7 @@ void bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) { + [[omp::directive (nothing)]]; [[omp::directive (for simd, private (p),firstprivate (f),lastprivate (l),linear (ll:1),reduction(+:r),schedule(static, 4),collapse(1),nowait, safelen(8),simdlen(4),aligned(q: 32),nontemporal(ntm),if(i1),order(concurrent),allocate (f))]] --- gcc/testsuite/g++.dg/gomp/attrs-9.C.jj 2021-07-31 09:35:18.801178476 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-9.C 2021-08-18 10:49:27.330692232 +0200 @@ -13,3 +13,4 @@ int b, c; int d; [[omp::directive (end declare target)]]; [[omp::directive (end declare target)]]; +[[omp::directive (nothing)]]; --- libgomp/testsuite/libgomp.c-c++-common/nothing-1.c.jj 2021-08-18 10:41:12.909646914 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/nothing-1.c 2021-08-18 10:41:07.562722125 +0200 @@ -0,0 +1,47 @@ +#include <stdlib.h> + +#pragma omp nothing + +struct S +{ + #pragma omp nothing + int s; +}; + +int +foo (int i) +{ + #pragma omp nothing + if (0) + #pragma omp nothing + i++; + if (1) + ; + else + #pragma omp nothing + i++; + switch (0) + #pragma omp nothing + { + default: + break; + } + while (0) + #pragma omp nothing + i++; + for (; 0;) + #pragma omp nothing + i++; + lab: + #pragma omp nothing + i++; + return i; +} + +int +main () +{ + if (foo (5) != 6 || foo (-2) != -1) + abort (); + return 0; +} Jakub