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:
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);
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);
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
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);
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);
}
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);
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:
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)
{
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);
!= 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);
}
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);
}
#pragma omp sections
{
bar (12);
- bar (13); /* { dg-error "pragma omp section" } */
+ bar (13);
#pragma omp section
bar (14);
}
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" } */
}
#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
#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;
}
{
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++)
{
{
#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);
}
}
{
#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);
}
}
@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}
@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}
@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