@@ -1469,6 +1469,10 @@ extern void protected_set_expr_location
#define OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV(NODE) \
TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE))
+/* True if a LASTPRIVATE clause has CONDITIONAL: modifier. */
+#define OMP_CLAUSE_LASTPRIVATE_CONDITIONAL(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE))
+
/* True on a SHARED clause if a FIRSTPRIVATE clause for the same
decl is present in the chain (this can happen only for taskloop
with FIRSTPRIVATE/LASTPRIVATE on it originally. */
@@ -389,7 +389,13 @@ dump_omp_clause (pretty_printer *pp, tre
goto print_remap;
case OMP_CLAUSE_LASTPRIVATE:
name = "lastprivate";
- goto print_remap;
+ if (!OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clause))
+ goto print_remap;
+ pp_string (pp, "lastprivate(conditional:");
+ dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
case OMP_CLAUSE_COPYIN:
name = "copyin";
goto print_remap;
@@ -7431,16 +7431,42 @@ gimplify_scan_omp_clauses (tree *list_p,
check_non_private = "firstprivate";
goto do_add;
case OMP_CLAUSE_LASTPRIVATE:
+ if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ switch (code)
+ {
+ case OMP_DISTRIBUTE:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "conditional %<lastprivate%> clause on "
+ "%<distribute%> construct");
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
+ break;
+ case OMP_TASKLOOP:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "conditional %<lastprivate%> clause on "
+ "%<taskloop%> construct");
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
+ break;
+ default:
+ break;
+ }
flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
check_non_private = "lastprivate";
decl = OMP_CLAUSE_DECL (c);
if (error_operand_p (decl))
goto do_add;
- else if (outer_ctx
- && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
- || outer_ctx->region_type == ORT_COMBINED_TEAMS)
- && splay_tree_lookup (outer_ctx->variables,
- (splay_tree_key) decl) == NULL)
+ if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+ && !lang_hooks.decls.omp_scalar_p (decl))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "non-scalar variable %qD in conditional "
+ "%<lastprivate%> clause", decl);
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
+ }
+ if (outer_ctx
+ && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
+ || outer_ctx->region_type == ORT_COMBINED_TEAMS)
+ && splay_tree_lookup (outer_ctx->variables,
+ (splay_tree_key) decl) == NULL)
{
omp_add_variable (outer_ctx, decl, GOVD_SHARED | GOVD_SEEN);
if (outer_ctx->outer_context)
@@ -1191,6 +1191,8 @@ c_omp_split_clauses (location_t loc, enu
OMP_CLAUSE_LASTPRIVATE);
OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+ = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
}
if (code == OMP_FOR || code == OMP_SECTIONS)
@@ -1208,6 +1210,8 @@ c_omp_split_clauses (location_t loc, enu
c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
OMP_CLAUSE_LASTPRIVATE);
OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+ = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
!= 0)
s = C_OMP_CLAUSE_SPLIT_PARALLEL;
@@ -11401,12 +11401,41 @@ c_parser_omp_clause_if (c_parser *parser
}
/* OpenMP 2.5:
- lastprivate ( variable-list ) */
+ lastprivate ( variable-list )
+
+ OpenMP 5.0:
+ lastprivate ( [ lastprivate-modifier : ] variable-list ) */
static tree
c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE, list);
+ /* The clauses location. */
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ bool conditional = false;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "conditional") == 0)
+ {
+ conditional = true;
+ c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
+ }
+ }
+ tree nlist = c_parser_omp_variable_list (parser, loc,
+ OMP_CLAUSE_LASTPRIVATE, list);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+ if (conditional)
+ for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
+ return nlist;
+ }
+ return list;
}
/* OpenMP 3.1:
@@ -17872,8 +17901,9 @@ c_parser_cilk_all_clauses (c_parser *par
clauses = c_parser_omp_clause_firstprivate (parser, clauses);
break;
case PRAGMA_CILK_CLAUSE_LASTPRIVATE:
- /* Use the OpenMP counterpart. */
- clauses = c_parser_omp_clause_lastprivate (parser, clauses);
+ clauses
+ = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LASTPRIVATE,
+ clauses);
break;
case PRAGMA_CILK_CLAUSE_REDUCTION:
/* Use the OpenMP counterpart. */
@@ -32459,6 +32459,43 @@ cp_parser_omp_clause_aligned (cp_parser
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, location_t loc)
+{
+ 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 )
@@ -33334,8 +33371,8 @@ cp_parser_omp_all_clauses (cp_parser *pa
c_name = "if";
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,
+ token->location);
c_name = "lastprivate";
break;
case PRAGMA_OMP_CLAUSE_MERGEABLE: