aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c1475
1 files changed, 1347 insertions, 128 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 30a4766..deaca5c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "gcc-rich-location.h"
#include "tree-iterator.h"
#include "cp-name-hint.h"
+#include "memmodel.h"
/* The lexer. */
@@ -2110,7 +2111,7 @@ static tree cp_parser_for
static tree cp_parser_c_for
(cp_parser *, tree, tree, bool, unsigned short);
static tree cp_parser_range_for
- (cp_parser *, tree, tree, tree, bool, unsigned short);
+ (cp_parser *, tree, tree, tree, bool, unsigned short, bool);
static void do_range_for_auto_deduction
(tree, tree);
static tree cp_parser_perform_range_for_lookup
@@ -11843,7 +11844,8 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll)
is_range_for = cp_parser_init_statement (parser, &decl);
if (is_range_for)
- return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll);
+ return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll,
+ false);
else
return cp_parser_c_for (parser, scope, init, ivdep, unroll);
}
@@ -11901,7 +11903,7 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep,
static tree
cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
- bool ivdep, unsigned short unroll)
+ bool ivdep, unsigned short unroll, bool is_omp)
{
tree stmt, range_expr;
auto_vec <cxx_binding *, 16> bindings;
@@ -11961,6 +11963,11 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
IDENTIFIER_BINDING (names[i]) = binding;
}
+ /* finish_omp_for has its own code for the following, so just
+ return the range_expr instead. */
+ if (is_omp)
+ return range_expr;
+
/* If in template, STMT is converted to a normal for-statement
at instantiation. If not, it is done just ahead. */
if (processing_template_decl)
@@ -31490,7 +31497,7 @@ cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
}
-/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 parsing routines. */
+/* OpenMP 2.5 / 3.0 / 3.1 / 4.0 / 4.5 / 5.0 parsing routines. */
/* Returns name of the next clause.
If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
@@ -31580,6 +31587,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
case 'i':
if (!strcmp ("if_present", p))
result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
+ else if (!strcmp ("in_reduction", p))
+ result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
else if (!strcmp ("inbranch", p))
result = PRAGMA_OMP_CLAUSE_INBRANCH;
else if (!strcmp ("independent", p))
@@ -31604,6 +31613,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
case 'n':
if (!strcmp ("nogroup", p))
result = PRAGMA_OMP_CLAUSE_NOGROUP;
+ else if (!strcmp ("nontemporal", p))
+ result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
else if (!strcmp ("notinbranch", p))
result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
else if (!strcmp ("nowait", p))
@@ -31668,7 +31679,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
result = PRAGMA_OMP_CLAUSE_SIMDLEN;
break;
case 't':
- if (!strcmp ("taskgroup", p))
+ if (!strcmp ("task_reduction", p))
+ result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
+ else if (!strcmp ("taskgroup", p))
result = PRAGMA_OMP_CLAUSE_TASKGROUP;
else if (!strcmp ("thread_limit", p))
result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
@@ -31759,6 +31772,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
{
tree name, decl;
+ if (kind == OMP_CLAUSE_DEPEND)
+ cp_parser_parse_tentatively (parser);
token = cp_lexer_peek_token (parser->lexer);
if (kind != 0
&& current_class_ptr
@@ -31778,15 +31793,25 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
/*declarator_p=*/false,
/*optional_p=*/false);
if (name == error_mark_node)
- goto skip_comma;
+ {
+ if (kind == OMP_CLAUSE_DEPEND
+ && cp_parser_simulate_error (parser))
+ goto depend_lvalue;
+ goto skip_comma;
+ }
if (identifier_p (name))
decl = cp_parser_lookup_name_simple (parser, name, token->location);
else
decl = name;
if (decl == error_mark_node)
- cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
- token->location);
+ {
+ if (kind == OMP_CLAUSE_DEPEND
+ && cp_parser_simulate_error (parser))
+ goto depend_lvalue;
+ cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
+ token->location);
+ }
}
if (decl == error_mark_node)
;
@@ -31822,6 +31847,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
/* FALLTHROUGH. */
case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
tree low_bound = NULL_TREE, length = NULL_TREE;
@@ -31839,7 +31866,14 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
{
/* Look for `:'. */
if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
- goto skip_comma;
+ {
+ if (kind == OMP_CLAUSE_DEPEND
+ && cp_parser_simulate_error (parser))
+ goto depend_lvalue;
+ goto skip_comma;
+ }
+ if (kind == OMP_CLAUSE_DEPEND)
+ cp_parser_commit_to_tentative_parse (parser);
if (!cp_lexer_next_token_is (parser->lexer,
CPP_CLOSE_SQUARE))
length = cp_parser_expression (parser);
@@ -31847,7 +31881,12 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
/* Look for the closing `]'. */
if (!cp_parser_require (parser, CPP_CLOSE_SQUARE,
RT_CLOSE_SQUARE))
- goto skip_comma;
+ {
+ if (kind == OMP_CLAUSE_DEPEND
+ && cp_parser_simulate_error (parser))
+ goto depend_lvalue;
+ goto skip_comma;
+ }
decl = tree_cons (low_bound, length, decl);
}
@@ -31856,6 +31895,21 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
break;
}
+ if (kind == OMP_CLAUSE_DEPEND)
+ {
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+ && cp_parser_simulate_error (parser))
+ {
+ depend_lvalue:
+ cp_parser_abort_tentative_parse (parser);
+ decl = cp_parser_assignment_expression (parser, NULL,
+ false, false);
+ }
+ else
+ cp_parser_parse_definitely (parser);
+ }
+
tree u = build_omp_clause (token->location, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
@@ -32440,7 +32494,11 @@ cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location)
directive-name-modifier:
parallel | task | taskloop | target data | target | target update
- | target enter data | target exit data */
+ | target enter data | target exit data
+
+ OpenMP 5.0:
+ directive-name-modifier:
+ ... | simd | cancel */
static tree
cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
@@ -32459,8 +32517,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
const char *p = IDENTIFIER_POINTER (id);
int n = 2;
- if (strcmp ("parallel", p) == 0)
+ if (strcmp ("cancel", p) == 0)
+ if_modifier = VOID_CST;
+ else if (strcmp ("parallel", p) == 0)
if_modifier = OMP_PARALLEL;
+ else if (strcmp ("simd", p) == 0)
+ if_modifier = OMP_SIMD;
else if (strcmp ("task", p) == 0)
if_modifier = OMP_TASK;
else if (strcmp ("taskloop", p) == 0)
@@ -32547,7 +32609,9 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location,
const char *p = NULL;
switch (if_modifier)
{
+ case VOID_CST: p = "cancel"; break;
case OMP_PARALLEL: p = "parallel"; break;
+ case OMP_SIMD: p = "simd"; break;
case OMP_TASK: p = "task"; break;
case OMP_TASKLOOP: p = "taskloop"; break;
case OMP_TARGET_DATA: p = "target data"; break;
@@ -32774,7 +32838,10 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list,
}
/* OpenMP 4.5:
- defaultmap ( tofrom : scalar ) */
+ defaultmap ( tofrom : scalar )
+
+ OpenMP 5.0:
+ defaultmap ( implicit-behavior [ : variable-category ] ) */
static tree
cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
@@ -32782,47 +32849,163 @@ cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
{
tree c, id;
const char *p;
+ enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
+ enum omp_clause_defaultmap_kind category
+ = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
matching_parens parens;
if (!parens.require_open (parser))
return list;
- if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT))
+ p = "default";
+ else if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
- cp_parser_error (parser, "expected %<tofrom%>");
+ invalid_behavior:
+ cp_parser_error (parser, "expected %<alloc%>, %<to%>, %<from%>, "
+ "%<tofrom%>, %<firstprivate%>, %<none%> "
+ "or %<default%>");
goto out_err;
}
- id = cp_lexer_peek_token (parser->lexer)->u.value;
- p = IDENTIFIER_POINTER (id);
- if (strcmp (p, "tofrom") != 0)
+ else
{
- cp_parser_error (parser, "expected %<tofrom%>");
- goto out_err;
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
}
- cp_lexer_consume_token (parser->lexer);
- if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
- goto out_err;
- if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ switch (p[0])
{
- cp_parser_error (parser, "expected %<scalar%>");
- goto out_err;
+ case 'a':
+ if (strcmp ("alloc", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
+ else
+ goto invalid_behavior;
+ break;
+
+ case 'd':
+ if (strcmp ("default", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
+ else
+ goto invalid_behavior;
+ break;
+
+ case 'f':
+ if (strcmp ("firstprivate", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
+ else if (strcmp ("from", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
+ else
+ goto invalid_behavior;
+ break;
+
+ case 'n':
+ if (strcmp ("none", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
+ else
+ goto invalid_behavior;
+ break;
+
+ case 't':
+ if (strcmp ("tofrom", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
+ else if (strcmp ("to", p) == 0)
+ behavior = OMP_CLAUSE_DEFAULTMAP_TO;
+ else
+ goto invalid_behavior;
+ break;
+
+ default:
+ goto invalid_behavior;
}
- id = cp_lexer_peek_token (parser->lexer)->u.value;
- p = IDENTIFIER_POINTER (id);
- if (strcmp (p, "scalar") != 0)
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
{
- cp_parser_error (parser, "expected %<scalar%>");
- goto out_err;
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ goto out_err;
+
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ invalid_category:
+ cp_parser_error (parser, "expected %<scalar%>, %<aggregate%> or "
+ "%<pointer%>");
+ goto out_err;
+ }
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+
+ switch (p[0])
+ {
+ case 'a':
+ if (strcmp ("aggregate", p) == 0)
+ category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
+ else
+ goto invalid_category;
+ break;
+
+ case 'p':
+ if (strcmp ("pointer", p) == 0)
+ category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
+ else
+ goto invalid_category;
+ break;
+
+ case 's':
+ if (strcmp ("scalar", p) == 0)
+ category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
+ else
+ goto invalid_category;
+ break;
+
+ default:
+ goto invalid_category;
+ }
+
+ cp_lexer_consume_token (parser->lexer);
}
- cp_lexer_consume_token (parser->lexer);
if (!parens.require_close (parser))
goto out_err;
- check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULTMAP, "defaultmap",
- location);
+ for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
+ && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
+ || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
+ || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
+ == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
+ {
+ enum omp_clause_defaultmap_kind cat = category;
+ location_t loc = OMP_CLAUSE_LOCATION (c);
+ if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
+ cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
+ p = NULL;
+ switch (cat)
+ {
+ case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
+ p = NULL;
+ break;
+ case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
+ p = "aggregate";
+ break;
+ case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
+ p = "pointer";
+ break;
+ case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
+ p = "scalar";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (p)
+ error_at (loc, "too many %<defaultmap%> clauses with %qs category",
+ p);
+ else
+ error_at (loc, "too many %<defaultmap%> clauses with unspecified "
+ "category");
+ break;
+ }
c = build_omp_clause (location, OMP_CLAUSE_DEFAULTMAP);
+ OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
OMP_CLAUSE_CHAIN (c) = list;
return c;
@@ -32897,17 +33080,50 @@ cp_parser_omp_clause_ordered (cp_parser *parser,
reduction-operator:
One of: + * - & ^ | && ||
- id-expression */
+ id-expression
+
+ OpenMP 5.0:
+ reduction ( reduction-modifier, reduction-operator : variable-list )
+ in_reduction ( reduction-operator : variable-list )
+ task_reduction ( reduction-operator : variable-list ) */
static tree
-cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
+cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
+ bool is_omp, tree list)
{
enum tree_code code = ERROR_MARK;
tree nlist, c, id = NULL_TREE;
+ bool task = false;
+ bool inscan = false;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
+ if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+ {
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "task") == 0)
+ task = true;
+ else if (strcmp (p, "inscan") == 0)
+ inscan = true;
+ if (task || inscan)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
+ }
+
switch (cp_lexer_peek_token (parser->lexer)->type)
{
case CPP_PLUS: code = PLUS_EXPR; break;
@@ -32980,11 +33196,15 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
goto resync_fail;
- nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list,
+ nlist = cp_parser_omp_var_list_no_open (parser, kind, list,
NULL);
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
{
OMP_CLAUSE_REDUCTION_CODE (c) = code;
+ if (task)
+ OMP_CLAUSE_REDUCTION_TASK (c) = 1;
+ else if (inscan)
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id;
}
@@ -33303,6 +33523,43 @@ cp_parser_omp_clause_aligned (cp_parser *parser, tree list)
return nlist;
}
+/* OpenMP 2.5:
+ lastprivate ( variable-list )
+
+ OpenMP 5.0:
+ lastprivate ( [ lastprivate-modifier : ] variable-list ) */
+
+static tree
+cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list)
+{
+ bool conditional = false;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp ("conditional", p) == 0)
+ {
+ conditional = true;
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
+
+ tree nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_LASTPRIVATE,
+ list, NULL);
+
+ if (conditional)
+ for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
+ return nlist;
+}
+
/* OpenMP 4.0:
linear ( variable-list )
linear ( variable-list : expression )
@@ -33545,6 +33802,118 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc,
return list;
}
+/* OpenMP 5.0:
+ iterators ( iterators-definition )
+
+ iterators-definition:
+ iterator-specifier
+ iterator-specifier , iterators-definition
+
+ iterator-specifier:
+ identifier = range-specification
+ iterator-type identifier = range-specification
+
+ range-specification:
+ begin : end
+ begin : end : step */
+
+static tree
+cp_parser_omp_iterators (cp_parser *parser)
+{
+ tree ret = NULL_TREE, *last = &ret;
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return error_mark_node;
+
+ bool saved_colon_corrects_to_scope_p
+ = parser->colon_corrects_to_scope_p;
+ bool saved_colon_doesnt_start_class_def_p
+ = parser->colon_doesnt_start_class_def_p;
+
+ do
+ {
+ tree iter_type;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_EQ))
+ iter_type = integer_type_node;
+ else
+ {
+ const char *saved_message
+ = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message
+ = G_("types may not be defined in iterator type");
+
+ iter_type = cp_parser_type_id (parser);
+
+ parser->type_definition_forbidden_message = saved_message;
+ }
+
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ cp_parser_error (parser, "expected identifier");
+ break;
+ }
+
+ tree id = cp_parser_identifier (parser);
+ if (id == error_mark_node)
+ break;
+
+ if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
+ break;
+
+ parser->colon_corrects_to_scope_p = false;
+ parser->colon_doesnt_start_class_def_p = true;
+ tree begin = cp_parser_assignment_expression (parser);
+
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ break;
+
+ tree end = cp_parser_assignment_expression (parser);
+
+ tree step = integer_one_node;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ step = cp_parser_assignment_expression (parser);
+ }
+
+ tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
+ DECL_ARTIFICIAL (iter_var) = 1;
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ pushdecl (iter_var);
+
+ *last = make_tree_vec (6);
+ TREE_VEC_ELT (*last, 0) = iter_var;
+ TREE_VEC_ELT (*last, 1) = begin;
+ TREE_VEC_ELT (*last, 2) = end;
+ TREE_VEC_ELT (*last, 3) = step;
+ last = &TREE_CHAIN (*last);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
+ break;
+ }
+ while (1);
+
+ parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+ parser->colon_doesnt_start_class_def_p
+ = saved_colon_doesnt_start_class_def_p;
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ return ret ? ret : error_mark_node;
+}
+
/* OpenMP 4.0:
depend ( depend-kind : variable-list )
@@ -33554,41 +33923,73 @@ cp_parser_omp_clause_depend_sink (cp_parser *parser, location_t clause_loc,
OpenMP 4.5:
depend ( source )
- depend ( sink : vec ) */
+ depend ( sink : vec )
+
+ OpenMP 5.0:
+ depend ( depend-modifier , depend-kind: variable-list )
+
+ depend-kind:
+ in | out | inout | mutexinoutset | depobj
+
+ depend-modifier:
+ iterator ( iterators-definition ) */
static tree
cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
{
- tree nlist, c;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_INOUT;
+ tree nlist, c, iterators = NULL_TREE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
matching_parens parens;
if (!parens.require_open (parser))
return list;
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ do
{
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ goto invalid_kind;
+
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
+ {
+ begin_scope (sk_omp, NULL);
+ iterators = cp_parser_omp_iterators (parser);
+ cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+ continue;
+ }
if (strcmp ("in", p) == 0)
kind = OMP_CLAUSE_DEPEND_IN;
else if (strcmp ("inout", p) == 0)
kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (strcmp ("mutexinoutset", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
else if (strcmp ("out", p) == 0)
kind = OMP_CLAUSE_DEPEND_OUT;
- else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
+ else if (strcmp ("depobj", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_DEPOBJ;
else if (strcmp ("sink", p) == 0)
kind = OMP_CLAUSE_DEPEND_SINK;
+ else if (strcmp ("source", p) == 0)
+ kind = OMP_CLAUSE_DEPEND_SOURCE;
else
goto invalid_kind;
+ break;
}
- else
- goto invalid_kind;
+ while (1);
cp_lexer_consume_token (parser->lexer);
+ if (iterators
+ && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
+ {
+ poplevel (0, 1, 0);
+ error_at (loc, "%<iterator%> modifier incompatible with %qs",
+ kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
+ iterators = NULL_TREE;
+ }
+
if (kind == OMP_CLAUSE_DEPEND_SOURCE)
{
c = build_omp_clause (loc, OMP_CLAUSE_DEPEND);
@@ -33612,14 +34013,30 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_DEPEND,
list, NULL);
+ if (iterators)
+ {
+ tree block = poplevel (1, 1, 0);
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ {
+ OMP_CLAUSE_DEPEND_KIND (c) = kind;
+ if (iterators)
+ OMP_CLAUSE_DECL (c)
+ = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
+ }
}
return nlist;
invalid_kind:
cp_parser_error (parser, "invalid depend kind");
resync_fail:
+ if (iterators)
+ poplevel (0, 1, 0);
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
@@ -34022,7 +34439,9 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
c_name = "private";
break;
case PRAGMA_OACC_CLAUSE_REDUCTION:
- clauses = cp_parser_omp_clause_reduction (parser, clauses);
+ clauses
+ = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+ false, clauses);
c_name = "reduction";
break;
case PRAGMA_OACC_CLAUSE_SEQ:
@@ -34169,9 +34588,14 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
true);
c_name = "if";
break;
+ case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
+ clauses
+ = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
+ true, clauses);
+ c_name = "in_reduction";
+ break;
case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
- clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
- clauses);
+ clauses = cp_parser_omp_clause_lastprivate (parser, clauses);
c_name = "lastprivate";
break;
case PRAGMA_OMP_CLAUSE_MERGEABLE:
@@ -34209,7 +34633,9 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
c_name = "private";
break;
case PRAGMA_OMP_CLAUSE_REDUCTION:
- clauses = cp_parser_omp_clause_reduction (parser, clauses);
+ clauses
+ = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
+ true, clauses);
c_name = "reduction";
break;
case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -34222,6 +34648,13 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses);
c_name = "shared";
break;
+ case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
+ clauses
+ = cp_parser_omp_clause_reduction (parser,
+ OMP_CLAUSE_TASK_REDUCTION,
+ true, clauses);
+ c_name = "task_reduction";
+ break;
case PRAGMA_OMP_CLAUSE_UNTIED:
clauses = cp_parser_omp_clause_untied (parser, clauses,
token->location);
@@ -34232,6 +34665,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses, token->location);
c_name = "inbranch";
break;
+ case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
+ clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_NONTEMPORAL,
+ clauses);
+ c_name = "nontemporal";
+ break;
case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
clauses = cp_parser_omp_clause_branch (parser,
OMP_CLAUSE_NOTINBRANCH,
@@ -34494,62 +34932,154 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE;
tree rhs1 = NULL_TREE, orig_lhs;
- enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR;
+ location_t loc = pragma_tok->location;
+ enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
+ enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
bool structured_block = false;
- bool seq_cst = false;
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
- {
- tree id = cp_lexer_peek_token (parser->lexer)->u.value;
- const char *p = IDENTIFIER_POINTER (id);
-
- if (!strcmp (p, "seq_cst"))
- {
- seq_cst = true;
- cp_lexer_consume_token (parser->lexer);
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
- cp_lexer_consume_token (parser->lexer);
- }
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
- {
- tree id = cp_lexer_peek_token (parser->lexer)->u.value;
- const char *p = IDENTIFIER_POINTER (id);
+ bool first = true;
+ tree clauses = NULL_TREE;
- if (!strcmp (p, "read"))
- code = OMP_ATOMIC_READ;
- else if (!strcmp (p, "write"))
- code = NOP_EXPR;
- else if (!strcmp (p, "update"))
- code = OMP_ATOMIC;
- else if (!strcmp (p, "capture"))
- code = OMP_ATOMIC_CAPTURE_NEW;
- else
- p = NULL;
- if (p)
- cp_lexer_consume_token (parser->lexer);
- }
- if (!seq_cst)
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
{
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+ if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
+ first = false;
+
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
const char *p = IDENTIFIER_POINTER (id);
-
- if (!strcmp (p, "seq_cst"))
+ enum tree_code new_code = ERROR_MARK;
+ enum omp_memory_order new_memory_order
+ = OMP_MEMORY_ORDER_UNSPECIFIED;
+
+ if (!strcmp (p, "read"))
+ new_code = OMP_ATOMIC_READ;
+ else if (!strcmp (p, "write"))
+ new_code = NOP_EXPR;
+ else if (!strcmp (p, "update"))
+ new_code = OMP_ATOMIC;
+ else if (!strcmp (p, "capture"))
+ new_code = OMP_ATOMIC_CAPTURE_NEW;
+ else if (!strcmp (p, "seq_cst"))
+ new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ else if (!strcmp (p, "acq_rel"))
+ new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+ else if (!strcmp (p, "release"))
+ new_memory_order = OMP_MEMORY_ORDER_RELEASE;
+ else if (!strcmp (p, "acquire"))
+ new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+ else if (!strcmp (p, "relaxed"))
+ new_memory_order = OMP_MEMORY_ORDER_RELAXED;
+ else if (!strcmp (p, "hint"))
{
- seq_cst = true;
cp_lexer_consume_token (parser->lexer);
+ clauses = cp_parser_omp_clause_hint (parser, clauses, cloc);
+ continue;
+ }
+ else
+ {
+ p = NULL;
+ error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+ "%<capture%>, %<seq_cst%>, %<acq_rel%>, "
+ "%<release%>, %<relaxed%> or %<hint%> clause");
+ }
+ if (p)
+ {
+ if (new_code != ERROR_MARK)
+ {
+ if (code != ERROR_MARK)
+ error_at (cloc, "too many atomic clauses");
+ else
+ code = new_code;
+ }
+ else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+ {
+ if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
+ error_at (cloc, "too many memory order clauses");
+ else
+ memory_order = new_memory_order;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ continue;
}
}
+ break;
}
cp_parser_require_pragma_eol (parser, pragma_tok);
+ if (code == ERROR_MARK)
+ code = OMP_ATOMIC;
+ if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
+ switch ((enum omp_memory_order)
+ (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
+ {
+ case OMP_MEMORY_ORDER_UNSPECIFIED:
+ case OMP_MEMORY_ORDER_RELAXED:
+ memory_order = OMP_MEMORY_ORDER_RELAXED;
+ break;
+ case OMP_MEMORY_ORDER_SEQ_CST:
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ break;
+ case OMP_MEMORY_ORDER_ACQ_REL:
+ switch (code)
+ {
+ case OMP_ATOMIC_READ:
+ memory_order = OMP_MEMORY_ORDER_ACQUIRE;
+ break;
+ case NOP_EXPR: /* atomic write */
+ case OMP_ATOMIC:
+ memory_order = OMP_MEMORY_ORDER_RELEASE;
+ break;
+ default:
+ memory_order = OMP_MEMORY_ORDER_ACQ_REL;
+ break;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ switch (code)
+ {
+ case OMP_ATOMIC_READ:
+ if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+ || memory_order == OMP_MEMORY_ORDER_RELEASE)
+ {
+ error_at (loc, "%<#pragma omp atomic read%> incompatible with "
+ "%<acq_rel%> or %<release%> clauses");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ break;
+ case NOP_EXPR: /* atomic write */
+ if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+ || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+ {
+ error_at (loc, "%<#pragma omp atomic write%> incompatible with "
+ "%<acq_rel%> or %<acquire%> clauses");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ break;
+ case OMP_ATOMIC:
+ if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
+ || memory_order == OMP_MEMORY_ORDER_ACQUIRE)
+ {
+ error_at (loc, "%<#pragma omp atomic update%> incompatible with "
+ "%<acq_rel%> or %<acquire%> clauses");
+ memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+ }
+ break;
+ default:
+ break;
+ }
+
switch (code)
{
case OMP_ATOMIC_READ:
@@ -34849,7 +35379,9 @@ stmt_done:
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
}
done:
- finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1, seq_cst);
+ clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+ finish_omp_atomic (pragma_tok->location, code, opcode, lhs, rhs, v, lhs1,
+ rhs1, clauses, memory_order);
if (!structured_block)
cp_parser_consume_semicolon_at_end_of_statement (parser);
return;
@@ -34911,6 +35443,10 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
if (name == error_mark_node)
name = NULL;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
+ cp_lexer_consume_token (parser->lexer);
+
clauses = cp_parser_omp_all_clauses (parser,
OMP_CRITICAL_CLAUSE_MASK,
"#pragma omp critical", pragma_tok);
@@ -34922,26 +35458,151 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
return c_finish_omp_critical (input_location, stmt, name, clauses);
}
+/* OpenMP 5.0:
+ # pragma omp depobj ( depobj ) depobj-clause new-line
+
+ depobj-clause:
+ depend (dependence-type : locator)
+ destroy
+ update (dependence-type)
+
+ dependence-type:
+ in
+ out
+ inout
+ mutexinout */
+
+static void
+cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
+{
+ location_t loc = pragma_tok->location;
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return;
+ }
+
+ tree depobj = cp_parser_assignment_expression (parser);
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ tree clause = NULL_TREE;
+ enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
+ location_t c_loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!strcmp ("depend", p))
+ {
+ clause = cp_parser_omp_clause_depend (parser, NULL_TREE, c_loc);
+ if (clause)
+ clause = finish_omp_clauses (clause, C_ORT_OMP);
+ if (!clause)
+ clause = error_mark_node;
+ }
+ else if (!strcmp ("destroy", p))
+ kind = OMP_CLAUSE_DEPEND_LAST;
+ else if (!strcmp ("update", p))
+ {
+ matching_parens c_parens;
+ if (c_parens.require_open (parser))
+ {
+ location_t c2_loc
+ = cp_lexer_peek_token (parser->lexer)->location;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id2 = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p2 = IDENTIFIER_POINTER (id2);
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!strcmp ("in", p2))
+ kind = OMP_CLAUSE_DEPEND_IN;
+ else if (!strcmp ("out", p2))
+ kind = OMP_CLAUSE_DEPEND_OUT;
+ else if (!strcmp ("inout", p2))
+ kind = OMP_CLAUSE_DEPEND_INOUT;
+ else if (!strcmp ("mutexinoutset", p2))
+ kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+ }
+ if (kind == OMP_CLAUSE_DEPEND_SOURCE)
+ {
+ clause = error_mark_node;
+ error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
+ "%<mutexinoutset%>");
+ }
+ if (!c_parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ }
+ else
+ clause = error_mark_node;
+ }
+ }
+ if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
+ {
+ clause = error_mark_node;
+ error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
+ }
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+
+ finish_omp_depobj (loc, depobj, kind, clause);
+}
+
+
/* OpenMP 2.5:
# pragma omp flush flush-vars[opt] new-line
flush-vars:
- ( variable-list ) */
+ ( variable-list )
+
+ OpenMP 5.0:
+ # pragma omp flush memory-order-clause new-line */
static void
cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
{
+ enum memmodel mo = MEMMODEL_LAST;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (!strcmp (p, "acq_rel"))
+ mo = MEMMODEL_ACQ_REL;
+ else if (!strcmp (p, "release"))
+ mo = MEMMODEL_RELEASE;
+ else if (!strcmp (p, "acquire"))
+ mo = MEMMODEL_ACQUIRE;
+ else
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "expected %<acq_rel%>, %<release%> or %<acquire%>");
+ cp_lexer_consume_token (parser->lexer);
+ }
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
- (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+ {
+ if (mo != MEMMODEL_LAST)
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "%<flush%> list specified together with memory order "
+ "clause");
+ (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
+ }
cp_parser_require_pragma_eol (parser, pragma_tok);
- finish_omp_flush ();
+ finish_omp_flush (mo);
}
/* Helper function, to parse omp for increment expression. */
static tree
-cp_parser_omp_for_cond (cp_parser *parser, tree decl)
+cp_parser_omp_for_cond (cp_parser *parser, tree decl, enum tree_code code)
{
tree cond = cp_parser_binary_expression (parser, false, true,
PREC_NOT_OPERATOR, NULL);
@@ -34960,7 +35621,8 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
case LE_EXPR:
break;
case NE_EXPR:
- /* Fall through: OpenMP disallows NE_EXPR. */
+ if (code != OACC_LOOP)
+ break;
gcc_fallthrough ();
default:
return error_mark_node;
@@ -35304,6 +35966,192 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
return add_private_clause;
}
+/* Helper for cp_parser_omp_for_loop, handle one range-for loop. */
+
+void
+cp_convert_omp_range_for (tree &this_pre_body, vec<tree, va_gc> *for_block,
+ tree &decl, tree &orig_decl, tree &init,
+ tree &orig_init, tree &cond, tree &incr)
+{
+ tree begin, end, range_temp_decl = NULL_TREE;
+ tree iter_type, begin_expr, end_expr;
+
+ if (processing_template_decl)
+ {
+ if (check_for_bare_parameter_packs (init))
+ init = error_mark_node;
+ if (!type_dependent_expression_p (init)
+ /* do_auto_deduction doesn't mess with template init-lists. */
+ && !BRACE_ENCLOSED_INITIALIZER_P (init))
+ {
+ tree d = decl;
+ if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl))
+ {
+ tree v = DECL_VALUE_EXPR (decl);
+ if (TREE_CODE (v) == ARRAY_REF
+ && VAR_P (TREE_OPERAND (v, 0))
+ && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+ d = TREE_OPERAND (v, 0);
+ }
+ do_range_for_auto_deduction (d, init);
+ }
+ cond = global_namespace;
+ incr = NULL_TREE;
+ orig_init = init;
+ if (this_pre_body)
+ this_pre_body = pop_stmt_list (this_pre_body);
+ return;
+ }
+
+ init = mark_lvalue_use (init);
+
+ if (decl == error_mark_node || init == error_mark_node)
+ /* If an error happened previously do nothing or else a lot of
+ unhelpful errors would be issued. */
+ begin_expr = end_expr = iter_type = error_mark_node;
+ else
+ {
+ tree range_temp;
+
+ if (VAR_P (init)
+ && array_of_runtime_bound_p (TREE_TYPE (init)))
+ /* Can't bind a reference to an array of runtime bound. */
+ range_temp = init;
+ else
+ {
+ range_temp = build_range_temp (init);
+ DECL_NAME (range_temp) = NULL_TREE;
+ pushdecl (range_temp);
+ cp_finish_decl (range_temp, init,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+ range_temp_decl = range_temp;
+ range_temp = convert_from_reference (range_temp);
+ }
+ iter_type = cp_parser_perform_range_for_lookup (range_temp,
+ &begin_expr, &end_expr);
+ }
+
+ tree end_iter_type = iter_type;
+ if (cxx_dialect >= cxx17)
+ end_iter_type = cv_unqualified (TREE_TYPE (end_expr));
+ end = build_decl (input_location, VAR_DECL, NULL_TREE, end_iter_type);
+ TREE_USED (end) = 1;
+ DECL_ARTIFICIAL (end) = 1;
+ pushdecl (end);
+ cp_finish_decl (end, end_expr,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+
+ /* The new for initialization statement. */
+ begin = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type);
+ TREE_USED (begin) = 1;
+ DECL_ARTIFICIAL (begin) = 1;
+ pushdecl (begin);
+ orig_init = init;
+ if (CLASS_TYPE_P (iter_type))
+ init = NULL_TREE;
+ else
+ {
+ init = begin_expr;
+ begin_expr = NULL_TREE;
+ }
+ cp_finish_decl (begin, begin_expr,
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+
+ /* The new for condition. */
+ if (CLASS_TYPE_P (iter_type))
+ cond = build2 (NE_EXPR, boolean_type_node, begin, end);
+ else
+ cond = build_x_binary_op (input_location, NE_EXPR,
+ begin, ERROR_MARK,
+ end, ERROR_MARK,
+ NULL, tf_warning_or_error);
+
+ /* The new increment expression. */
+ if (CLASS_TYPE_P (iter_type))
+ incr = build2 (PREINCREMENT_EXPR, iter_type, begin, NULL_TREE);
+ else
+ incr = finish_unary_op_expr (input_location,
+ PREINCREMENT_EXPR, begin,
+ tf_warning_or_error);
+
+ orig_decl = decl;
+ decl = begin;
+ if (for_block)
+ {
+ vec_safe_push (for_block, this_pre_body);
+ this_pre_body = NULL_TREE;
+ }
+
+ tree decomp_first_name = NULL_TREE;
+ unsigned decomp_cnt = 0;
+ if (orig_decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (orig_decl))
+ {
+ tree v = DECL_VALUE_EXPR (orig_decl);
+ if (TREE_CODE (v) == ARRAY_REF
+ && VAR_P (TREE_OPERAND (v, 0))
+ && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0)))
+ {
+ tree d = orig_decl;
+ orig_decl = TREE_OPERAND (v, 0);
+ decomp_cnt = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1;
+ decomp_first_name = d;
+ }
+ }
+
+ tree auto_node = type_uses_auto (TREE_TYPE (orig_decl));
+ if (auto_node)
+ {
+ tree t = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
+ tf_none);
+ if (!error_operand_p (t))
+ TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl),
+ t, auto_node);
+ }
+
+ tree v = make_tree_vec (decomp_cnt + 3);
+ TREE_VEC_ELT (v, 0) = range_temp_decl;
+ TREE_VEC_ELT (v, 1) = end;
+ TREE_VEC_ELT (v, 2) = orig_decl;
+ for (unsigned i = 0; i < decomp_cnt; i++)
+ {
+ TREE_VEC_ELT (v, i + 3) = decomp_first_name;
+ decomp_first_name = DECL_CHAIN (decomp_first_name);
+ }
+ orig_decl = tree_cons (NULL_TREE, NULL_TREE, v);
+}
+
+/* Helper for cp_parser_omp_for_loop, finalize part of range for
+ inside of the collapsed body. */
+
+void
+cp_finish_omp_range_for (tree orig, tree begin)
+{
+ gcc_assert (TREE_CODE (orig) == TREE_LIST
+ && TREE_CODE (TREE_CHAIN (orig)) == TREE_VEC);
+ tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2);
+ tree decomp_first_name = NULL_TREE;
+ unsigned int decomp_cnt = 0;
+
+ if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+ {
+ decomp_first_name = TREE_VEC_ELT (TREE_CHAIN (orig), 3);
+ decomp_cnt = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3;
+ cp_maybe_mangle_decomp (decl, decomp_first_name, decomp_cnt);
+ }
+
+ /* The declaration is initialized with *__begin inside the loop body. */
+ cp_finish_decl (decl,
+ build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
+ tf_warning_or_error),
+ /*is_constant_init*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+ if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+ cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
+}
+
/* Parse the restricted form of the for statement allowed by OpenMP. */
static tree
@@ -35311,7 +36159,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
tree *cclauses, bool *if_p)
{
tree init, orig_init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
- tree real_decl, initv, condv, incrv, declv;
+ tree orig_decl;
+ tree real_decl, initv, condv, incrv, declv, orig_declv;
tree this_pre_body, cl, ordered_cl = NULL_TREE;
location_t loc_first;
bool collapse_err = false;
@@ -35364,6 +36213,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
initv = make_tree_vec (count);
condv = make_tree_vec (count);
incrv = make_tree_vec (count);
+ orig_declv = NULL_TREE;
loc_first = cp_lexer_peek_token (parser->lexer)->location;
@@ -35385,9 +36235,71 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
if (!parens.require_open (parser))
return NULL;
- init = orig_init = decl = real_decl = NULL;
+ init = orig_init = decl = real_decl = orig_decl = NULL_TREE;
this_pre_body = push_stmt_list ();
+ if (code != OACC_LOOP && cxx_dialect >= cxx11)
+ {
+ /* Save tokens so that we can put them back. */
+ cp_lexer_save_tokens (parser->lexer);
+
+ /* Look for ':' that is not nested in () or {}. */
+ bool is_range_for
+ = (cp_parser_skip_to_closing_parenthesis_1 (parser,
+ /*recovering=*/false,
+ CPP_COLON,
+ /*consume_paren=*/
+ false) == -1);
+
+ /* Roll back the tokens we skipped. */
+ cp_lexer_rollback_tokens (parser->lexer);
+
+ if (is_range_for)
+ {
+ bool saved_colon_corrects_to_scope_p
+ = parser->colon_corrects_to_scope_p;
+
+ /* A colon is used in range-based for. */
+ parser->colon_corrects_to_scope_p = false;
+
+ /* Parse the declaration. */
+ cp_parser_simple_declaration (parser,
+ /*function_definition_allowed_p=*/
+ false, &decl);
+ parser->colon_corrects_to_scope_p
+ = saved_colon_corrects_to_scope_p;
+
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+
+ init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, decl,
+ false, 0, true);
+
+ cp_convert_omp_range_for (this_pre_body, for_block, decl,
+ orig_decl, init, orig_init,
+ cond, incr);
+ if (this_pre_body)
+ {
+ if (pre_body)
+ {
+ tree t = pre_body;
+ pre_body = push_stmt_list ();
+ add_stmt (t);
+ add_stmt (this_pre_body);
+ pre_body = pop_stmt_list (pre_body);
+ }
+ else
+ pre_body = this_pre_body;
+ }
+
+ if (ordered_cl)
+ error_at (OMP_CLAUSE_LOCATION (ordered_cl),
+ "%<ordered%> clause with parameter on "
+ "range-based %<for%> loop");
+
+ goto parse_close_paren;
+ }
+ }
+
add_private_clause
= cp_parser_omp_for_loop_init (parser, this_pre_body, for_block,
init, orig_init, decl, real_decl);
@@ -35464,7 +36376,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
error_at (loc, "iteration variable %qD "
"should not be firstprivate",
decl);
- else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
&& OMP_CLAUSE_DECL (c) == decl)
error_at (loc, "iteration variable %qD should not be reduction",
decl);
@@ -35493,7 +36406,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
cond = NULL;
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- cond = cp_parser_omp_for_cond (parser, decl);
+ cond = cp_parser_omp_for_cond (parser, decl, code);
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
incr = NULL;
@@ -35513,6 +36426,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
protected_set_expr_location (incr, input_location);
}
+ parse_close_paren:
if (!parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
@@ -35527,6 +36441,14 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
orig_inits.safe_grow_cleared (i + 1);
orig_inits[i] = orig_init;
}
+ if (orig_decl)
+ {
+ if (!orig_declv)
+ orig_declv = copy_node (declv);
+ TREE_VEC_ELT (orig_declv, i) = orig_decl;
+ }
+ else if (orig_declv)
+ TREE_VEC_ELT (orig_declv, i) = decl;
if (i == count - 1)
break;
@@ -35575,15 +36497,27 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
/* Note that the grammar doesn't call for a structured block here,
though the loop as a whole is a structured block. */
- body = push_stmt_list ();
+ if (orig_declv)
+ {
+ body = begin_omp_structured_block ();
+ for (i = 0; i < count; i++)
+ if (TREE_VEC_ELT (orig_declv, i) != TREE_VEC_ELT (declv, i))
+ cp_finish_omp_range_for (TREE_VEC_ELT (orig_declv, i),
+ TREE_VEC_ELT (declv, i));
+ }
+ else
+ body = push_stmt_list ();
cp_parser_statement (parser, NULL_TREE, false, if_p);
- body = pop_stmt_list (body);
+ if (orig_declv)
+ body = finish_omp_structured_block (body);
+ else
+ body = pop_stmt_list (body);
if (declv == NULL_TREE)
ret = NULL_TREE;
else
- ret = finish_omp_for (loc_first, code, declv, NULL, initv, condv, incrv,
- body, pre_body, &orig_inits, clauses);
+ ret = finish_omp_for (loc_first, code, declv, orig_declv, initv, condv,
+ incrv, body, pre_body, &orig_inits, clauses);
while (nbraces)
{
@@ -35647,7 +36581,9 @@ cp_omp_split_clauses (location_t loc, enum tree_code code,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL))
static tree
cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
@@ -35678,13 +36614,14 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
}
}
+ keep_next_level (true);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
- add_stmt (finish_omp_structured_block (sb));
+ add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
return ret;
}
@@ -35777,26 +36714,78 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
}
+ keep_next_level (true);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
- add_stmt (finish_omp_structured_block (sb));
+ add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
return ret;
}
+static tree cp_parser_omp_taskloop (cp_parser *, cp_token *, char *,
+ omp_clause_mask, tree *, bool *);
+
/* OpenMP 2.5:
# pragma omp master new-line
structured-block */
static tree
-cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
+cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
- cp_parser_require_pragma_eol (parser, pragma_tok);
- return c_finish_omp_master (input_location,
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " master");
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "taskloop") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ if (cclauses == NULL)
+ cclauses = cclauses_buf;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask,
+ cclauses, if_p);
+ sb = begin_omp_structured_block ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask,
+ cclauses, if_p);
+ cp_parser_end_omp_structured_block (parser, save);
+ tree body = finish_omp_structured_block (sb);
+ if (ret == NULL)
+ return ret;
+ return c_finish_omp_master (loc, body);
+ }
+ }
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+
+ if (cclauses)
+ {
+ clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
+ false);
+ cp_omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
+ }
+ else
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+
+ return c_finish_omp_master (loc,
cp_parser_omp_structured_block (parser, if_p));
}
@@ -36038,16 +37027,34 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
return NULL_TREE;
}
- else if (!flag_openmp) /* flag_openmp_simd */
- {
- cp_parser_skip_to_pragma_eol (parser, pragma_tok);
- return NULL_TREE;
- }
else if (cclauses == NULL && cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
- if (strcmp (p, "sections") == 0)
+ if (strcmp (p, "master") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ cclauses = cclauses_buf;
+
+ cp_lexer_consume_token (parser->lexer);
+ block = begin_omp_parallel ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask,
+ cclauses, if_p);
+ cp_parser_end_omp_structured_block (parser, save);
+ stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ if (ret == NULL_TREE)
+ return ret;
+ return stmt;
+ }
+ else if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
+ else if (strcmp (p, "sections") == 0)
{
tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
cclauses = cclauses_buf;
@@ -36063,6 +37070,11 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
return stmt;
}
}
+ else if (!flag_openmp) /* flag_openmp_simd */
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return NULL_TREE;
+ }
clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok,
cclauses == NULL);
@@ -36095,6 +37107,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt = make_node (OMP_SINGLE);
TREE_TYPE (stmt) = void_type_node;
+ SET_EXPR_LOCATION (stmt, pragma_tok->location);
OMP_SINGLE_CLAUSES (stmt)
= cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
@@ -36118,7 +37131,8 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
static tree
cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
@@ -36136,13 +37150,32 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
}
/* OpenMP 3.0:
- # pragma omp taskwait new-line */
+ # pragma omp taskwait new-line
+
+ OpenMP 5.0:
+ # pragma omp taskwait taskwait-clause[opt] new-line */
+
+#define OMP_TASKWAIT_CLAUSE_MASK \
+ (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
static void
cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
{
- cp_parser_require_pragma_eol (parser, pragma_tok);
- finish_omp_taskwait ();
+ tree clauses
+ = cp_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
+ "#pragma omp taskwait", pragma_tok);
+
+ if (clauses)
+ {
+ tree stmt = make_node (OMP_TASK);
+ TREE_TYPE (stmt) = void_node;
+ OMP_TASK_CLAUSES (stmt) = clauses;
+ OMP_TASK_BODY (stmt) = NULL_TREE;
+ SET_EXPR_LOCATION (stmt, pragma_tok->location);
+ add_stmt (stmt);
+ }
+ else
+ finish_omp_taskwait ();
}
/* OpenMP 3.1:
@@ -36157,15 +37190,24 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
/* OpenMP 4.0:
# pragma omp taskgroup new-line
- structured-block */
+ structured-block
+
+ OpenMP 5.0:
+ # pragma omp taskgroup taskgroup-clause[optseq] new-line */
+
+#define OMP_TASKGROUP_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
static tree
cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
- cp_parser_require_pragma_eol (parser, pragma_tok);
+ tree clauses
+ = cp_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
+ "#pragma omp taskgroup", pragma_tok);
return c_finish_omp_taskgroup (input_location,
cp_parser_omp_structured_block (parser,
- if_p));
+ if_p),
+ clauses);
}
@@ -36338,13 +37380,14 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
}
+ keep_next_level (true);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL, if_p);
cp_parser_end_omp_structured_block (parser, save);
- add_stmt (finish_omp_structured_block (sb));
+ add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
return ret;
}
@@ -36388,6 +37431,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
cclauses, if_p);
+ keep_next_level (true);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
@@ -36423,6 +37467,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
tree stmt = make_node (OMP_TEAMS);
TREE_TYPE (stmt) = void_type_node;
OMP_TEAMS_CLAUSES (stmt) = clauses;
+ keep_next_level (true);
OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
SET_EXPR_LOCATION (stmt, loc);
@@ -36473,6 +37518,8 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
*pc = OMP_CLAUSE_CHAIN (*pc);
continue;
}
+ else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR)
+ map_seen = 3;
pc = &OMP_CLAUSE_CHAIN (*pc);
}
@@ -36481,7 +37528,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
if (map_seen == 0)
error_at (pragma_tok->location,
"%<#pragma omp target data%> must contain at least "
- "one %<map%> clause");
+ "one %<map%> or %<use_device_ptr%> clause");
return NULL_TREE;
}
@@ -36739,6 +37786,10 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
{
tree *pc = NULL, stmt;
+ if (flag_openmp)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
@@ -38092,6 +39143,147 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
return false;
}
+/* OpenMP 5.0
+ #pragma omp requires clauses[optseq] new-line */
+
+static bool
+cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok)
+{
+ bool first = true;
+ enum omp_requires new_req = (enum omp_requires) 0;
+
+ location_t loc = pragma_tok->location;
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+ {
+ if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+
+ first = false;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ location_t cloc = cp_lexer_peek_token (parser->lexer)->location;
+ enum omp_requires this_req = (enum omp_requires) 0;
+
+ if (!strcmp (p, "unified_address"))
+ this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
+ else if (!strcmp (p, "unified_shared_memory"))
+ this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
+ else if (!strcmp (p, "dynamic_allocators"))
+ this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
+ else if (!strcmp (p, "reverse_offload"))
+ this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
+ else if (!strcmp (p, "atomic_default_mem_order"))
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+
+ if (!strcmp (p, "seq_cst"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
+ else if (!strcmp (p, "relaxed"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
+ else if (!strcmp (p, "acq_rel"))
+ this_req
+ = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
+ }
+ if (this_req == 0)
+ {
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "expected %<seq_cst%>, %<relaxed%> or "
+ "%<acq_rel%>");
+ if (cp_lexer_nth_token_is (parser->lexer, 2,
+ CPP_CLOSE_PAREN))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ cp_lexer_consume_token (parser->lexer);
+
+ if (!parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/
+ true);
+
+ if (this_req == 0)
+ {
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ return false;
+ }
+ }
+ p = NULL;
+ }
+ else
+ {
+ error_at (cloc, "expected %<unified_address%>, "
+ "%<unified_shared_memory%>, "
+ "%<dynamic_allocators%>, "
+ "%<reverse_offload%> "
+ "or %<atomic_default_mem_order%> clause");
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return false;
+ }
+ if (p)
+ cp_lexer_consume_token (parser->lexer);
+ if (this_req)
+ {
+ if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+ {
+ if ((this_req & new_req) != 0)
+ error_at (cloc, "too many %qs clauses", p);
+ if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
+ && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
+ error_at (cloc, "%qs clause used lexically after first "
+ "target construct or offloading API", p);
+ }
+ else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+ {
+ error_at (cloc, "too many %qs clauses",
+ "atomic_default_mem_order");
+ this_req = (enum omp_requires) 0;
+ }
+ else if ((omp_requires_mask
+ & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
+ {
+ error_at (cloc, "more than one %<atomic_default_mem_order%>"
+ " clause in a single compilation unit");
+ this_req
+ = (enum omp_requires)
+ (omp_requires_mask
+ & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
+ }
+ else if ((omp_requires_mask
+ & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
+ error_at (cloc, "%<atomic_default_mem_order%> clause used "
+ "lexically after first %<atomic%> construct "
+ "without memory order clause");
+ new_req = (enum omp_requires) (new_req | this_req);
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | this_req);
+ continue;
+ }
+ }
+ break;
+ }
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+
+ if (new_req == 0)
+ error_at (loc, "%<pragma omp requires%> requires at least one clause");
+ return false;
+}
+
+
/* OpenMP 4.5:
#pragma omp taskloop taskloop-clause[optseq] new-line
for-loop
@@ -38113,7 +39305,9 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
static tree
cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
@@ -38126,6 +39320,10 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
strcat (p_name, " taskloop");
mask |= OMP_TASKLOOP_CLAUSE_MASK;
+ /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
+ clause. */
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
+ mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
@@ -38173,6 +39371,7 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
}
+ keep_next_level (true);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
@@ -38180,7 +39379,7 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
if_p);
cp_parser_end_omp_structured_block (parser, save);
- add_stmt (finish_omp_structured_block (sb));
+ add_stmt (finish_omp_for_block (finish_omp_structured_block (sb), ret));
return ret;
}
@@ -38487,7 +39686,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
if_p);
break;
case PRAGMA_OMP_MASTER:
- stmt = cp_parser_omp_master (parser, pragma_tok, if_p);
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_PARALLEL:
strcpy (p_name, "#pragma omp");
@@ -38947,6 +40148,21 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
}
break;
+ case PRAGMA_OMP_DEPOBJ:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_depobj (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error_at (pragma_tok->location, "%<#pragma %s%> may only be "
+ "used in compound statements", "omp depobj");
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
case PRAGMA_OMP_FLUSH:
switch (context)
{
@@ -39114,6 +40330,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
pop_omp_privatization_clauses (stmt);
return true;
+ case PRAGMA_OMP_REQUIRES:
+ return cp_parser_omp_requires (parser, pragma_tok);
+
case PRAGMA_OMP_ORDERED:
if (context != pragma_stmt && context != pragma_compound)
goto bad_stmt;