summaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c691
1 files changed, 504 insertions, 187 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 96999bf7e89..83d23394cb5 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3359,6 +3359,94 @@ omp_clause_info_fndecl (tree t, tree type)
return NULL_TREE;
}
+/* Create CP_OMP_CLAUSE_INFO for clause C. Returns true if it is invalid. */
+
+bool
+cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
+ bool need_copy_ctor, bool need_copy_assignment)
+{
+ int save_errorcount = errorcount;
+ tree info, t;
+
+ /* Always allocate 3 elements for simplicity. These are the
+ function decls for the ctor, dtor, and assignment op.
+ This layout is known to the three lang hooks,
+ cxx_omp_clause_default_init, cxx_omp_clause_copy_init,
+ and cxx_omp_clause_assign_op. */
+ info = make_tree_vec (3);
+ CP_OMP_CLAUSE_INFO (c) = info;
+
+ if (need_default_ctor
+ || (need_copy_ctor && !TYPE_HAS_TRIVIAL_INIT_REF (type)))
+ {
+ if (need_default_ctor)
+ t = NULL;
+ else
+ {
+ t = build_int_cst (build_pointer_type (type), 0);
+ t = build1 (INDIRECT_REF, type, t);
+ t = build_tree_list (NULL, t);
+ }
+ t = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ t, type, LOOKUP_NORMAL,
+ tf_warning_or_error);
+
+ if (targetm.cxx.cdtor_returns_this () || errorcount)
+ /* Because constructors and destructors return this,
+ the call will have been cast to "void". Remove the
+ cast here. We would like to use STRIP_NOPS, but it
+ wouldn't work here because TYPE_MODE (t) and
+ TYPE_MODE (TREE_OPERAND (t, 0)) are different.
+ They are VOIDmode and Pmode, respectively. */
+ if (TREE_CODE (t) == NOP_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ TREE_VEC_ELT (info, 0) = get_callee_fndecl (t);
+ }
+
+ if ((need_default_ctor || need_copy_ctor)
+ && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ {
+ t = build_int_cst (build_pointer_type (type), 0);
+ t = build1 (INDIRECT_REF, type, t);
+ t = build_special_member_call (t, complete_dtor_identifier,
+ NULL, type, LOOKUP_NORMAL,
+ tf_warning_or_error);
+
+ if (targetm.cxx.cdtor_returns_this () || errorcount)
+ /* Because constructors and destructors return this,
+ the call will have been cast to "void". Remove the
+ cast here. We would like to use STRIP_NOPS, but it
+ wouldn't work here because TYPE_MODE (t) and
+ TYPE_MODE (TREE_OPERAND (t, 0)) are different.
+ They are VOIDmode and Pmode, respectively. */
+ if (TREE_CODE (t) == NOP_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ TREE_VEC_ELT (info, 1) = omp_clause_info_fndecl (t, type);
+ }
+
+ if (need_copy_assignment && !TYPE_HAS_TRIVIAL_ASSIGN_REF (type))
+ {
+ t = build_int_cst (build_pointer_type (type), 0);
+ t = build1 (INDIRECT_REF, type, t);
+ t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
+ build_tree_list (NULL, t),
+ type, LOOKUP_NORMAL,
+ tf_warning_or_error);
+
+ /* We'll have called convert_from_reference on the call, which
+ may well have added an indirect_ref. It's unneeded here,
+ and in the way, so kill it. */
+ if (TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+
+ TREE_VEC_ELT (info, 2) = omp_clause_info_fndecl (t, type);
+ }
+
+ return errorcount != save_errorcount;
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
@@ -3499,6 +3587,8 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_COLLAPSE:
break;
default:
@@ -3662,93 +3752,10 @@ finish_omp_clauses (tree clauses)
for making these queries. */
if (CLASS_TYPE_P (inner_type)
&& (need_default_ctor || need_copy_ctor || need_copy_assignment)
- && !type_dependent_expression_p (t))
- {
- int save_errorcount = errorcount;
- tree info;
-
- /* Always allocate 3 elements for simplicity. These are the
- function decls for the ctor, dtor, and assignment op.
- This layout is known to the three lang hooks,
- cxx_omp_clause_default_init, cxx_omp_clause_copy_init,
- and cxx_omp_clause_assign_op. */
- info = make_tree_vec (3);
- CP_OMP_CLAUSE_INFO (c) = info;
-
- if (need_default_ctor
- || (need_copy_ctor
- && !TYPE_HAS_TRIVIAL_INIT_REF (inner_type)))
- {
- if (need_default_ctor)
- t = NULL;
- else
- {
- t = build_int_cst (build_pointer_type (inner_type), 0);
- t = build1 (INDIRECT_REF, inner_type, t);
- t = build_tree_list (NULL, t);
- }
- t = build_special_member_call (NULL_TREE,
- complete_ctor_identifier,
- t, inner_type, LOOKUP_NORMAL,
- tf_warning_or_error);
-
- if (targetm.cxx.cdtor_returns_this () || errorcount)
- /* Because constructors and destructors return this,
- the call will have been cast to "void". Remove the
- cast here. We would like to use STRIP_NOPS, but it
- wouldn't work here because TYPE_MODE (t) and
- TYPE_MODE (TREE_OPERAND (t, 0)) are different.
- They are VOIDmode and Pmode, respectively. */
- if (TREE_CODE (t) == NOP_EXPR)
- t = TREE_OPERAND (t, 0);
-
- TREE_VEC_ELT (info, 0) = get_callee_fndecl (t);
- }
-
- if ((need_default_ctor || need_copy_ctor)
- && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_type))
- {
- t = build_int_cst (build_pointer_type (inner_type), 0);
- t = build1 (INDIRECT_REF, inner_type, t);
- t = build_special_member_call (t, complete_dtor_identifier,
- NULL, inner_type, LOOKUP_NORMAL,
- tf_warning_or_error);
-
- if (targetm.cxx.cdtor_returns_this () || errorcount)
- /* Because constructors and destructors return this,
- the call will have been cast to "void". Remove the
- cast here. We would like to use STRIP_NOPS, but it
- wouldn't work here because TYPE_MODE (t) and
- TYPE_MODE (TREE_OPERAND (t, 0)) are different.
- They are VOIDmode and Pmode, respectively. */
- if (TREE_CODE (t) == NOP_EXPR)
- t = TREE_OPERAND (t, 0);
-
- TREE_VEC_ELT (info, 1) = omp_clause_info_fndecl (t, inner_type);
- }
-
- if (need_copy_assignment
- && !TYPE_HAS_TRIVIAL_ASSIGN_REF (inner_type))
- {
- t = build_int_cst (build_pointer_type (inner_type), 0);
- t = build1 (INDIRECT_REF, inner_type, t);
- t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
- build_tree_list (NULL, t),
- inner_type, LOOKUP_NORMAL,
- tf_warning_or_error);
-
- /* We'll have called convert_from_reference on the call, which
- may well have added an indirect_ref. It's unneeded here,
- and in the way, so kill it. */
- if (TREE_CODE (t) == INDIRECT_REF)
- t = TREE_OPERAND (t, 0);
-
- TREE_VEC_ELT (info, 2) = omp_clause_info_fndecl (t, inner_type);
- }
-
- if (errorcount != save_errorcount)
- remove = true;
- }
+ && !type_dependent_expression_p (t)
+ && cxx_omp_create_clause_info (c, inner_type, need_default_ctor,
+ need_copy_ctor, need_copy_assignment))
+ remove = true;
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
@@ -3787,9 +3794,10 @@ finish_omp_threadprivate (tree vars)
error ("automatic variable %qE cannot be %<threadprivate%>", v);
else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
error ("%<threadprivate%> %qE has incomplete type", v);
- else if (TREE_STATIC (v) && TYPE_P (CP_DECL_CONTEXT (v)))
- error ("%<threadprivate%> %qE is not file, namespace "
- "or block scope variable", v);
+ else if (TREE_STATIC (v) && TYPE_P (CP_DECL_CONTEXT (v))
+ && CP_DECL_CONTEXT (v) != current_class_type)
+ error ("%<threadprivate%> %qE directive not "
+ "in %qT definition", v, CP_DECL_CONTEXT (v));
else
{
/* Allocate a LANG_SPECIFIC structure for V, if needed. */
@@ -3855,6 +3863,252 @@ finish_omp_parallel (tree clauses, tree body)
return add_stmt (stmt);
}
+tree
+begin_omp_task (void)
+{
+ keep_next_level (true);
+ return begin_omp_structured_block ();
+}
+
+tree
+finish_omp_task (tree clauses, tree body)
+{
+ tree stmt;
+
+ body = finish_omp_structured_block (body);
+
+ stmt = make_node (OMP_TASK);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TASK_CLAUSES (stmt) = clauses;
+ OMP_TASK_BODY (stmt) = body;
+
+ return add_stmt (stmt);
+}
+
+/* Helper function for finish_omp_for. Convert Ith random access iterator
+ into integral iterator. Return FALSE if successful. */
+
+static bool
+handle_omp_for_class_iterator (int i, location_t locus, tree declv, tree initv,
+ tree condv, tree incrv, tree *body,
+ tree *pre_body, tree clauses)
+{
+ tree diff, iter_init, iter_incr = NULL, last;
+ tree incr_var = NULL, orig_pre_body, orig_body, c;
+ tree decl = TREE_VEC_ELT (declv, i);
+ tree init = TREE_VEC_ELT (initv, i);
+ tree cond = TREE_VEC_ELT (condv, i);
+ tree incr = TREE_VEC_ELT (incrv, i);
+ tree iter = decl;
+ location_t elocus = locus;
+
+ if (init && EXPR_HAS_LOCATION (init))
+ elocus = EXPR_LOCATION (init);
+
+ switch (TREE_CODE (cond))
+ {
+ case GT_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ if (TREE_OPERAND (cond, 0) != iter)
+ cond = error_mark_node;
+ else
+ {
+ tree tem = build_x_binary_op (TREE_CODE (cond), iter, ERROR_MARK,
+ TREE_OPERAND (cond, 1), ERROR_MARK,
+ NULL, tf_warning_or_error);
+ if (error_operand_p (tem))
+ return true;
+ }
+ break;
+ default:
+ cond = error_mark_node;
+ break;
+ }
+ if (cond == error_mark_node)
+ {
+ error ("%Hinvalid controlling predicate", &elocus);
+ return true;
+ }
+ diff = build_x_binary_op (MINUS_EXPR, TREE_OPERAND (cond, 1),
+ ERROR_MARK, iter, ERROR_MARK, NULL,
+ tf_warning_or_error);
+ if (error_operand_p (diff))
+ return true;
+ if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
+ {
+ error ("%Hdifference between %qE and %qD does not have integer type",
+ &elocus, TREE_OPERAND (cond, 1), iter);
+ return true;
+ }
+
+ switch (TREE_CODE (incr))
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ if (TREE_OPERAND (incr, 0) != iter)
+ {
+ incr = error_mark_node;
+ break;
+ }
+ iter_incr = build_x_unary_op (TREE_CODE (incr), iter,
+ tf_warning_or_error);
+ if (error_operand_p (iter_incr))
+ return true;
+ else if (TREE_CODE (incr) == PREINCREMENT_EXPR
+ || TREE_CODE (incr) == POSTINCREMENT_EXPR)
+ incr = integer_one_node;
+ else
+ incr = integer_minus_one_node;
+ break;
+ case MODIFY_EXPR:
+ if (TREE_OPERAND (incr, 0) != iter)
+ incr = error_mark_node;
+ else if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
+ || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR)
+ {
+ tree rhs = TREE_OPERAND (incr, 1);
+ if (TREE_OPERAND (rhs, 0) == iter)
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 1)))
+ != INTEGER_TYPE)
+ incr = error_mark_node;
+ else
+ {
+ iter_incr = build_x_modify_expr (iter, TREE_CODE (rhs),
+ TREE_OPERAND (rhs, 1),
+ tf_warning_or_error);
+ if (error_operand_p (iter_incr))
+ return true;
+ incr = TREE_OPERAND (rhs, 1);
+ incr = cp_convert (TREE_TYPE (diff), incr);
+ if (TREE_CODE (rhs) == MINUS_EXPR)
+ {
+ incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr);
+ incr = fold_if_not_in_template (incr);
+ }
+ if (TREE_CODE (incr) != INTEGER_CST
+ && (TREE_CODE (incr) != NOP_EXPR
+ || (TREE_CODE (TREE_OPERAND (incr, 0))
+ != INTEGER_CST)))
+ iter_incr = NULL;
+ }
+ }
+ else if (TREE_OPERAND (rhs, 1) == iter)
+ {
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) != INTEGER_TYPE
+ || TREE_CODE (rhs) != PLUS_EXPR)
+ incr = error_mark_node;
+ else
+ {
+ iter_incr = build_x_binary_op (PLUS_EXPR,
+ TREE_OPERAND (rhs, 0),
+ ERROR_MARK, iter,
+ ERROR_MARK, NULL,
+ tf_warning_or_error);
+ if (error_operand_p (iter_incr))
+ return true;
+ iter_incr = build_x_modify_expr (iter, NOP_EXPR,
+ iter_incr,
+ tf_warning_or_error);
+ if (error_operand_p (iter_incr))
+ return true;
+ incr = TREE_OPERAND (rhs, 0);
+ iter_incr = NULL;
+ }
+ }
+ else
+ incr = error_mark_node;
+ }
+ else
+ incr = error_mark_node;
+ break;
+ default:
+ incr = error_mark_node;
+ break;
+ }
+
+ if (incr == error_mark_node)
+ {
+ error ("%Hinvalid increment expression", &elocus);
+ return true;
+ }
+
+ incr = cp_convert (TREE_TYPE (diff), incr);
+ for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_DECL (c) == iter)
+ break;
+
+ decl = create_temporary_var (TREE_TYPE (diff));
+ pushdecl (decl);
+ add_decl_expr (decl);
+ last = create_temporary_var (TREE_TYPE (diff));
+ pushdecl (last);
+ add_decl_expr (last);
+ if (c && iter_incr == NULL)
+ {
+ incr_var = create_temporary_var (TREE_TYPE (diff));
+ pushdecl (incr_var);
+ add_decl_expr (incr_var);
+ }
+ gcc_assert (stmts_are_full_exprs_p ());
+
+ orig_pre_body = *pre_body;
+ *pre_body = push_stmt_list ();
+ if (orig_pre_body)
+ add_stmt (orig_pre_body);
+ if (init != NULL)
+ finish_expr_stmt (build_x_modify_expr (iter, NOP_EXPR, init,
+ tf_warning_or_error));
+ init = build_int_cst (TREE_TYPE (diff), 0);
+ if (c && iter_incr == NULL)
+ {
+ finish_expr_stmt (build_x_modify_expr (incr_var, NOP_EXPR,
+ incr, tf_warning_or_error));
+ incr = incr_var;
+ iter_incr = build_x_modify_expr (iter, PLUS_EXPR, incr,
+ tf_warning_or_error);
+ }
+ finish_expr_stmt (build_x_modify_expr (last, NOP_EXPR, init,
+ tf_warning_or_error));
+ *pre_body = pop_stmt_list (*pre_body);
+
+ cond = cp_build_binary_op (TREE_CODE (cond), decl, diff,
+ tf_warning_or_error);
+ incr = build_modify_expr (decl, PLUS_EXPR, incr);
+
+ orig_body = *body;
+ *body = push_stmt_list ();
+ iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), decl, last);
+ iter_init = build_x_modify_expr (iter, PLUS_EXPR, iter_init,
+ tf_warning_or_error);
+ iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
+ finish_expr_stmt (iter_init);
+ finish_expr_stmt (build_x_modify_expr (last, NOP_EXPR, decl,
+ tf_warning_or_error));
+ add_stmt (orig_body);
+ *body = pop_stmt_list (*body);
+
+ if (c)
+ {
+ OMP_CLAUSE_LASTPRIVATE_STMT (c) = push_stmt_list ();
+ finish_expr_stmt (iter_incr);
+ OMP_CLAUSE_LASTPRIVATE_STMT (c)
+ = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c));
+ }
+
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+
+ return false;
+}
+
/* Build and validate an OMP_FOR statement. CLAUSES, BODY, COND, INCR
are directly for their associated operands in the statement. DECL
and INIT are a combo; if DECL is NULL then INIT ought to be a
@@ -3863,126 +4117,203 @@ finish_omp_parallel (tree clauses, tree body)
sk_omp scope. */
tree
-finish_omp_for (location_t locus, tree decl, tree init, tree cond,
- tree incr, tree body, tree pre_body)
+finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
+ tree incrv, tree body, tree pre_body, tree clauses)
{
- tree omp_for = NULL;
+ tree omp_for = NULL, orig_incr = NULL;
+ tree decl, init, cond, incr;
+ location_t elocus;
+ int i;
- if (decl == NULL)
+ gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
+ gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
+ gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
+ for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
{
- if (init != NULL)
- switch (TREE_CODE (init))
- {
- case MODIFY_EXPR:
- decl = TREE_OPERAND (init, 0);
- init = TREE_OPERAND (init, 1);
- break;
- case MODOP_EXPR:
- if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
+ decl = TREE_VEC_ELT (declv, i);
+ init = TREE_VEC_ELT (initv, i);
+ cond = TREE_VEC_ELT (condv, i);
+ incr = TREE_VEC_ELT (incrv, i);
+ elocus = locus;
+
+ if (decl == NULL)
+ {
+ if (init != NULL)
+ switch (TREE_CODE (init))
{
+ case MODIFY_EXPR:
decl = TREE_OPERAND (init, 0);
- init = TREE_OPERAND (init, 2);
+ init = TREE_OPERAND (init, 1);
+ break;
+ case MODOP_EXPR:
+ if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR)
+ {
+ decl = TREE_OPERAND (init, 0);
+ init = TREE_OPERAND (init, 2);
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
- }
- if (decl == NULL)
- {
- error ("expected iteration declaration or initialization");
- return NULL;
+ if (decl == NULL)
+ {
+ error ("%Hexpected iteration declaration or initialization",
+ &locus);
+ return NULL;
+ }
}
- }
- if (type_dependent_expression_p (decl)
- || type_dependent_expression_p (init)
- || (cond && type_dependent_expression_p (cond))
- || (incr && type_dependent_expression_p (incr)))
- {
- tree stmt;
+ if (init && EXPR_HAS_LOCATION (init))
+ elocus = EXPR_LOCATION (init);
if (cond == NULL)
{
- error ("%Hmissing controlling predicate", &locus);
+ error ("%Hmissing controlling predicate", &elocus);
return NULL;
}
if (incr == NULL)
{
- error ("%Hmissing increment expression", &locus);
+ error ("%Hmissing increment expression", &elocus);
return NULL;
}
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ }
+
+ if (dependent_omp_for_p (declv, initv, condv, incrv))
+ {
+ tree stmt;
+
stmt = make_node (OMP_FOR);
- /* This is really just a place-holder. We'll be decomposing this
- again and going through the build_modify_expr path below when
- we instantiate the thing. */
- init = build2 (MODIFY_EXPR, void_type_node, decl, init);
+ for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
+ {
+ /* This is really just a place-holder. We'll be decomposing this
+ again and going through the cp_build_modify_expr path below when
+ we instantiate the thing. */
+ TREE_VEC_ELT (initv, i)
+ = build2 (MODIFY_EXPR, void_type_node, TREE_VEC_ELT (declv, i),
+ TREE_VEC_ELT (initv, i));
+ }
TREE_TYPE (stmt) = void_type_node;
- OMP_FOR_INIT (stmt) = init;
- OMP_FOR_COND (stmt) = cond;
- OMP_FOR_INCR (stmt) = incr;
+ OMP_FOR_INIT (stmt) = initv;
+ OMP_FOR_COND (stmt) = condv;
+ OMP_FOR_INCR (stmt) = incrv;
OMP_FOR_BODY (stmt) = body;
OMP_FOR_PRE_BODY (stmt) = pre_body;
+ OMP_FOR_CLAUSES (stmt) = clauses;
SET_EXPR_LOCATION (stmt, locus);
return add_stmt (stmt);
}
- if (!DECL_P (decl))
- {
- error ("expected iteration declaration or initialization");
- return NULL;
- }
+ if (processing_template_decl)
+ orig_incr = make_tree_vec (TREE_VEC_LENGTH (incrv));
- if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
+ for (i = 0; i < TREE_VEC_LENGTH (declv); )
{
- location_t elocus = locus;
-
- if (EXPR_HAS_LOCATION (init))
+ decl = TREE_VEC_ELT (declv, i);
+ init = TREE_VEC_ELT (initv, i);
+ cond = TREE_VEC_ELT (condv, i);
+ incr = TREE_VEC_ELT (incrv, i);
+ if (orig_incr)
+ TREE_VEC_ELT (orig_incr, i) = incr;
+ elocus = locus;
+
+ if (init && EXPR_HAS_LOCATION (init))
elocus = EXPR_LOCATION (init);
- error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
- return NULL;
- }
- if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
- pre_body = NULL;
- else if (! processing_template_decl)
- {
- add_stmt (pre_body);
- pre_body = NULL;
- }
+ if (!DECL_P (decl))
+ {
+ error ("%Hexpected iteration declaration or initialization",
+ &elocus);
+ return NULL;
+ }
- if (!processing_template_decl)
- init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
- init = cp_build_modify_expr (decl, NOP_EXPR, init, tf_warning_or_error);
- if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond))
- {
- int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0;
- tree t = TREE_OPERAND (cond, n);
+ if (incr && TREE_CODE (incr) == MODOP_EXPR)
+ {
+ if (orig_incr)
+ TREE_VEC_ELT (orig_incr, i) = incr;
+ incr = cp_build_modify_expr (TREE_OPERAND (incr, 0),
+ TREE_CODE (TREE_OPERAND (incr, 1)),
+ TREE_OPERAND (incr, 2),
+ tf_warning_or_error);
+ }
+
+ if (CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ if (handle_omp_for_class_iterator (i, locus, declv, initv, condv,
+ incrv, &body, &pre_body, clauses))
+ return NULL;
+ continue;
+ }
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
+ && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
+ {
+ error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
+ return NULL;
+ }
if (!processing_template_decl)
- TREE_OPERAND (cond, n)
- = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
+ init = cp_build_modify_expr (decl, NOP_EXPR, init, tf_warning_or_error);
+ if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond))
+ {
+ int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0;
+ tree t = TREE_OPERAND (cond, n);
+
+ if (!processing_template_decl)
+ TREE_OPERAND (cond, n)
+ = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ if (decl == error_mark_node || init == error_mark_node)
+ return NULL;
+
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+ i++;
}
- if (decl != error_mark_node && init != error_mark_node)
- omp_for = c_finish_omp_for (locus, decl, init, cond, incr, body, pre_body);
- if (omp_for != NULL
- && TREE_CODE (OMP_FOR_INCR (omp_for)) == MODIFY_EXPR
- && TREE_SIDE_EFFECTS (TREE_OPERAND (OMP_FOR_INCR (omp_for), 1))
- && BINARY_CLASS_P (TREE_OPERAND (OMP_FOR_INCR (omp_for), 1)))
+
+ if (IS_EMPTY_STMT (pre_body))
+ pre_body = NULL;
+
+ omp_for = c_finish_omp_for (locus, declv, initv, condv, incrv,
+ body, pre_body);
+
+ if (omp_for == NULL)
+ return NULL;
+
+ for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++)
{
- tree t = TREE_OPERAND (OMP_FOR_INCR (omp_for), 1);
- int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0;
+ tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i);
- if (!processing_template_decl)
- TREE_OPERAND (t, n)
- = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)),
- TREE_OPERAND (t, n));
+ if (TREE_CODE (incr) != MODIFY_EXPR)
+ continue;
+
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (incr, 1))
+ && BINARY_CLASS_P (TREE_OPERAND (incr, 1)))
+ {
+ tree t = TREE_OPERAND (incr, 1);
+ int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0;
+
+ if (!processing_template_decl)
+ TREE_OPERAND (t, n)
+ = fold_build_cleanup_point_expr (TREE_TYPE (TREE_OPERAND (t, n)),
+ TREE_OPERAND (t, n));
+ }
+
+ if (orig_incr)
+ TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i) = TREE_VEC_ELT (orig_incr, i);
}
+ if (omp_for != NULL)
+ OMP_FOR_CLAUSES (omp_for) = clauses;
return omp_for;
}
@@ -4039,26 +4370,12 @@ finish_omp_flush (void)
finish_expr_stmt (stmt);
}
-/* True if OpenMP sharing attribute of DECL is predetermined. */
-
-enum omp_clause_default_kind
-cxx_omp_predetermined_sharing (tree decl)
+void
+finish_omp_taskwait (void)
{
- enum omp_clause_default_kind kind;
-
- kind = c_omp_predetermined_sharing (decl);
- if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
- return kind;
-
- /* Static data members are predetermined as shared. */
- if (TREE_STATIC (decl))
- {
- tree ctx = CP_DECL_CONTEXT (decl);
- if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
- return OMP_CLAUSE_DEFAULT_SHARED;
- }
-
- return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+ tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
+ tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+ finish_expr_stmt (stmt);
}
void