diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index a66f43f6dc2..869a811ed90 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -18976,6 +18976,31 @@ c_parser_omp_flush (c_parser *parser) c_finish_omp_flush (loc, mo); } +/* Parse an OpenMP structured block sequence. KIND is the corresponding + separating directive. */ + +static tree +c_parser_omp_structured_block_sequence (c_parser *parser, + enum pragma_kind kind) +{ + tree stmt = push_stmt_list (); + c_parser_statement (parser, NULL); + do + { + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + break; + if (c_parser_next_token_is (parser, CPP_EOF)) + break; + + if (kind != PRAGMA_NONE + && c_parser_peek_token (parser)->pragma_kind == kind) + break; + c_parser_statement (parser, NULL); + } + while (1); + return pop_stmt_list (stmt); +} + /* OpenMP 5.0: scan-loop-body: @@ -18997,7 +19022,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) return; } - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19032,7 +19057,7 @@ c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) error ("expected %<#pragma omp scan%>"); clauses = c_finish_omp_clauses (clauses, C_ORT_OMP); - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE); substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19860,6 +19885,8 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context, section-directive[opt] structured-block section-sequence section-directive structured-block + OpenMP 5.1 allows structured-block-sequence instead of structured-block. + SECTIONS_LOC is the location of the #pragma omp sections. */ static tree @@ -19881,7 +19908,8 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser) if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION) { - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19907,7 +19935,8 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser) error_suppress = true; } - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c7005eb1a8f..0818d66be07 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40136,14 +40136,12 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save) } static tree -cp_parser_omp_structured_block (cp_parser *parser, bool *if_p, - bool disallow_omp_attrs = true) +cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) { tree stmt = begin_omp_structured_block (); unsigned int save = cp_parser_begin_omp_structured_block (parser); - if (disallow_omp_attrs) - parser->omp_attrs_forbidden_p = true; + parser->omp_attrs_forbidden_p = true; cp_parser_statement (parser, NULL_TREE, false, if_p); cp_parser_end_omp_structured_block (parser, save); @@ -42001,6 +41999,43 @@ cp_parser_omp_section_scan (cp_parser *parser, const char *directive, return true; } +/* Parse an OpenMP structured block sequence. KIND is the corresponding + separating directive. */ + +static tree +cp_parser_omp_structured_block_sequence (cp_parser *parser, + enum pragma_kind kind) +{ + tree stmt = begin_omp_structured_block (); + unsigned int save = cp_parser_begin_omp_structured_block (parser); + + cp_parser_statement (parser, NULL_TREE, false, NULL); + while (true) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + + if (token->type == CPP_CLOSE_BRACE + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL + || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END) + || (kind != PRAGMA_NONE + && cp_parser_pragma_kind (token) == kind)) + break; + + if (kind != PRAGMA_NONE + && cp_parser_omp_section_scan (parser, + kind == PRAGMA_OMP_SCAN + ? "scan" : "section", false)) + break; + + cp_parser_statement (parser, NULL_TREE, false, NULL); + } + + cp_parser_end_omp_structured_block (parser, save); + return finish_omp_structured_block (stmt); +} + + /* OpenMP 5.0: scan-loop-body: @@ -42015,11 +42050,10 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) if (!braces.require_open (parser)) return; - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); add_stmt (substmt); - cp_parser_omp_section_scan (parser, "scan", false); cp_token *tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN) { @@ -42055,7 +42089,7 @@ cp_parser_omp_scan_loop_body (cp_parser *parser) error ("expected %<#pragma omp scan%>"); clauses = finish_omp_clauses (clauses, C_ORT_OMP); - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE); substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt, clauses); add_stmt (substmt); @@ -42924,7 +42958,8 @@ cp_parser_omp_sections_scope (cp_parser *parser) != PRAGMA_OMP_SECTION && !cp_parser_omp_section_scan (parser, "section", true)) { - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } @@ -42951,7 +42986,8 @@ cp_parser_omp_sections_scope (cp_parser *parser) error_suppress = true; } - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } diff --git a/gcc/testsuite/c-c++-common/gomp/sections1.c b/gcc/testsuite/c-c++-common/gomp/sections1.c index 8c8ab91f7f1..417d2056ed5 100644 --- a/gcc/testsuite/c-c++-common/gomp/sections1.c +++ b/gcc/testsuite/c-c++-common/gomp/sections1.c @@ -50,7 +50,7 @@ foo () #pragma omp sections { bar (12); - bar (13); /* { dg-error "pragma omp section" } */ + bar (13); #pragma omp section bar (14); } @@ -63,11 +63,29 @@ foo () bar (15); #pragma omp section bar (16); - bar (17); /* { dg-error "pragma omp section" } */ + bar (17); } #pragma omp sections { bar (18); #pragma omp section } /* { dg-error "expression before" } */ + #pragma omp sections + { + #pragma omp section + #pragma omp section /* { dg-error "may only be used in" } */ + bar (19); + } + #pragma omp sections + { + bar (20); + #pragma omp section + #pragma omp section /* { dg-error "may only be used in" } */ + bar (21); + } + #pragma omp sections + { + bar (22); + #pragma omp section + } /* { dg-error "expression before" } */ } diff --git a/gcc/testsuite/g++.dg/gomp/attrs-6.C b/gcc/testsuite/g++.dg/gomp/attrs-6.C index 30b47e1ac15..af8b9731da9 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-6.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-6.C @@ -26,6 +26,41 @@ foo () #pragma omp section { a[3]++; } } + #pragma omp parallel sections + { + #pragma omp section + a[0]++; + a[4]++; + l1: a[5]++; + if (a[5] == 42) goto l1; + [[omp::directive (section)]] { + a[1]++; + a[6]++; + } [[omp::directive (section)]] + a[2]++; + a[7]++; + #pragma omp section + { a[3]++; } + a[8]++; + } + [[omp::directive (parallel sections)]] + { + #pragma omp section + a[0]++; + a[4]++; + [[omp::directive (section)]] { + a[1]++; + a[5]++; + } [[omp::directive (section)]] + a[2]++; + l2: a[6]++; + if (a[6] == 42) + goto l2; + a[7]++; + #pragma omp section + a[8]++; + { a[3]++; } + } } int @@ -46,5 +81,23 @@ bar (int a, int *c, int *d, int *e, int *f) #pragma omp scan inclusive (a) d[i] = a; } + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + int t = a; + d[i] = t; + [[omp::directive (scan, exclusive (a))]] + int u = c[i]; + a += u; + } + [[omp::directive (simd reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + int t = c[i]; + a += t; + #pragma omp scan inclusive (a) + int u = a; + d[i] = u; + } return a; } diff --git a/gcc/testsuite/g++.dg/gomp/attrs-7.C b/gcc/testsuite/g++.dg/gomp/attrs-7.C index cf842814657..900ef664957 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-7.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-7.C @@ -29,29 +29,33 @@ bar (int a, int *c, int *d, int *e, int *f) { d[i] = a; [[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { a += c[i]; [[omp::sequence (directive (scan inclusive (a)), directive (critical))]] // { dg-error "must be the only specified attribute on a statement" } - d[i] = a; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + d[i] = a; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { d[i] = a; [[gnu::cold]] [[omp::directive (scan, exclusive (a))]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { d[i] = a; [[omp::directive (scan, exclusive (a)), gnu::cold]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { diff --git a/gcc/testsuite/g++.dg/gomp/sections-2.C b/gcc/testsuite/g++.dg/gomp/sections-2.C index aabdfaf8069..6d8305afc03 100644 --- a/gcc/testsuite/g++.dg/gomp/sections-2.C +++ b/gcc/testsuite/g++.dg/gomp/sections-2.C @@ -19,11 +19,11 @@ void foo(void) { #pragma omp section bar(2); - bar(3); // { dg-error "expected" } + bar(3); bar(4); #pragma omp section bar(5); - bar(6); // { dg-error "expected" } + bar(6); bar(7); } } diff --git a/gcc/testsuite/gcc.dg/gomp/sections-2.c b/gcc/testsuite/gcc.dg/gomp/sections-2.c index aabdfaf8069..6d8305afc03 100644 --- a/gcc/testsuite/gcc.dg/gomp/sections-2.c +++ b/gcc/testsuite/gcc.dg/gomp/sections-2.c @@ -19,11 +19,11 @@ void foo(void) { #pragma omp section bar(2); - bar(3); // { dg-error "expected" } + bar(3); bar(4); #pragma omp section bar(5); - bar(6); // { dg-error "expected" } + bar(6); bar(7); } } diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index 02160f81562..2f61a2231fe 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -291,7 +291,7 @@ The OpenMP 4.5 specification is fully supported. @item @code{strict} modifier in the @code{grainsize} and @code{num_tasks} clauses of the taskloop construct @tab Y @tab @item @code{align} clause/modifier in @code{allocate} directive/clause - and @code{allocator} directive @tab N @tab + and @code{allocator} directive @tab P @tab C/C++ on clause only @item @code{thread_limit} clause to @code{target} construct @tab N @tab @item @code{has_device_addr} clause to @code{target} construct @tab N @tab @item iterators in @code{target update} motion clauses and @code{map} @@ -301,7 +301,7 @@ The OpenMP 4.5 specification is fully supported. @item @code{interop} directive @tab N @tab @item @code{omp_interop_t} object support in runtime routines @tab N @tab @item @code{nowait} clause in @code{taskwait} directive @tab N @tab -@item Extensions to the @code{atomic} directive @tab N @tab +@item Extensions to the @code{atomic} directive @tab P @tab C/C++ only @item @code{seq_cst} clause on a @code{flush} construct @tab Y @tab @item @code{inoutset} argument to the @code{depend} clause @tab N @tab @item @code{private} and @code{firstprivate} argument to @code{default} @@ -337,7 +337,10 @@ The OpenMP 4.5 specification is fully supported. @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments -@item Suppport of strictly structured blocks in Fortran @tab N @tab +@item Support of strictly structured blocks in Fortran @tab N @tab +@item Support of structured block sequences in C/C++ @tab Y @tab +@item @code{unconstrained} and @code{reproducible} modifiers on @code{order} + clause @tab Y @tab @end multitable