diff options
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 691 |
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 |