= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
in_decl);
break;
- case OMP_CLAUSE_LINEAR:
case OMP_CLAUSE_ALIGNED:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
- if (OMP_CLAUSE_CODE (oc) == OMP_CLAUSE_LINEAR
- && OMP_CLAUSE_LINEAR_STEP (oc) == NULL_TREE)
+ break;
+ case OMP_CLAUSE_LINEAR:
+ OMP_CLAUSE_DECL (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
+ in_decl);
+ if (OMP_CLAUSE_LINEAR_STEP (oc) == NULL_TREE)
{
gcc_assert (!linear_no_step);
linear_no_step = nc;
}
+ else if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (oc))
+ OMP_CLAUSE_LINEAR_STEP (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_LINEAR_STEP (oc), args,
+ complain, in_decl);
+ else
+ OMP_CLAUSE_LINEAR_STEP (nc)
+ = tsubst_expr (OMP_CLAUSE_LINEAR_STEP (oc), args, complain,
+ in_decl,
+ /*integral_constant_expression_p=*/false);
break;
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_DEFAULT:
if (allow_fields)
switch (OMP_CLAUSE_CODE (nc))
{
+ case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
&& DECL_NAME (v) == this_identifier)
{
decl = TREE_OPERAND (decl, 1);
- decl = omp_privatize_field (decl);
+ decl = omp_privatize_field (decl, false);
}
/* FALLTHRU */
default:
#undef RECUR
}
+/* Helper function of tsubst_expr, find OMP_TEAMS inside
+ of OMP_TARGET's body. */
+
+static tree
+tsubst_find_omp_teams (tree *tp, int *walk_subtrees, void *)
+{
+ *walk_subtrees = 0;
+ switch (TREE_CODE (*tp))
+ {
+ case OMP_TEAMS:
+ return *tp;
+ case BIND_EXPR:
+ case STATEMENT_LIST:
+ *walk_subtrees = 1;
+ break;
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
if (OMP_FOR_INIT (t) != NULL_TREE)
{
declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
- if (TREE_CODE (t) == OMP_FOR && OMP_FOR_ORIG_DECLS (t))
+ if (OMP_FOR_ORIG_DECLS (t))
orig_declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
condv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
if (OMP_FOR_INIT (t) != NULL_TREE)
t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv,
orig_declv, initv, condv, incrv, body, pre_body,
- clauses);
+ NULL, clauses);
else
{
t = make_node (TREE_CODE (t));
t = copy_node (t);
OMP_BODY (t) = stmt;
OMP_CLAUSES (t) = tmp;
+ if (TREE_CODE (t) == OMP_TARGET && OMP_TARGET_COMBINED (t))
+ {
+ tree teams = cp_walk_tree (&stmt, tsubst_find_omp_teams, NULL, NULL);
+ if (teams)
+ {
+ /* For combined target teams, ensure the num_teams and
+ thread_limit clause expressions are evaluated on the host,
+ before entering the target construct. */
+ tree c;
+ for (c = OMP_TEAMS_CLAUSES (teams);
+ c; c = OMP_CLAUSE_CHAIN (c))
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
+ && TREE_CODE (OMP_CLAUSE_OPERAND (c, 0)) != INTEGER_CST)
+ {
+ tree expr = OMP_CLAUSE_OPERAND (c, 0);
+ expr = force_target_expr (TREE_TYPE (expr), expr, tf_none);
+ if (expr == error_mark_node)
+ continue;
+ tmp = TARGET_EXPR_SLOT (expr);
+ add_stmt (expr);
+ OMP_CLAUSE_OPERAND (c, 0) = expr;
+ tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (tc) = tmp;
+ OMP_CLAUSE_CHAIN (tc) = OMP_TARGET_CLAUSES (t);
+ OMP_TARGET_CLAUSES (t) = tc;
+ }
+ }
+ }
add_stmt (t);
break;