diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 255 |
1 files changed, 243 insertions, 12 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4bb43addb74..f141b74a6fd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10214,16 +10214,26 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain, switch (OMP_CLAUSE_CODE (nc)) { + case OMP_CLAUSE_LASTPRIVATE: + if (OMP_CLAUSE_LASTPRIVATE_STMT (oc)) + { + OMP_CLAUSE_LASTPRIVATE_STMT (nc) = push_stmt_list (); + tsubst_expr (OMP_CLAUSE_LASTPRIVATE_STMT (oc), args, complain, + in_decl, /*integral_constant_expression_p=*/false); + OMP_CLAUSE_LASTPRIVATE_STMT (nc) + = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (nc)); + } + /* FALLTHRU */ case OMP_CLAUSE_PRIVATE: case OMP_CLAUSE_SHARED: case OMP_CLAUSE_FIRSTPRIVATE: - case OMP_CLAUSE_LASTPRIVATE: case OMP_CLAUSE_REDUCTION: case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_COPYPRIVATE: case OMP_CLAUSE_IF: case OMP_CLAUSE_NUM_THREADS: case OMP_CLAUSE_SCHEDULE: + case OMP_CLAUSE_COLLAPSE: OMP_CLAUSE_OPERAND (nc, 0) = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl, /*integral_constant_expression_p=*/false); @@ -10231,6 +10241,7 @@ tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain, case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_DEFAULT: + case OMP_CLAUSE_UNTIED: break; default: gcc_unreachable (); @@ -10274,6 +10285,137 @@ tsubst_copy_asm_operands (tree t, tree args, tsubst_flags_t complain, #undef RECUR } +/* Substitute one OMP_FOR iterator. */ + +static void +tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv, + tree condv, tree incrv, tree *clauses, + tree args, tsubst_flags_t complain, tree in_decl, + bool integral_constant_expression_p) +{ +#define RECUR(NODE) \ + tsubst_expr ((NODE), args, complain, in_decl, \ + integral_constant_expression_p) + tree decl, init, cond, incr; + + init = TREE_VEC_ELT (OMP_FOR_INIT (t), i); + gcc_assert (TREE_CODE (init) == MODIFY_EXPR); + decl = RECUR (TREE_OPERAND (init, 0)); + init = TREE_OPERAND (init, 1); + gcc_assert (!type_dependent_expression_p (decl)); + + if (!CLASS_TYPE_P (TREE_TYPE (decl))) + { + cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), i)); + incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i); + if (TREE_CODE (incr) == MODIFY_EXPR) + incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)), NOP_EXPR, + RECUR (TREE_OPERAND (incr, 1)), + complain); + else + incr = RECUR (incr); + 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; + } + + if (init && TREE_CODE (init) != DECL_EXPR) + { + tree c; + for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c)) + { + if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) + && OMP_CLAUSE_DECL (c) == decl) + break; + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + && OMP_CLAUSE_DECL (c) == decl) + error ("iteration variable %qD should not be firstprivate", decl); + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_DECL (c) == decl) + error ("iteration variable %qD should not be reduction", decl); + } + if (c == NULL) + { + c = build_omp_clause (OMP_CLAUSE_PRIVATE); + OMP_CLAUSE_DECL (c) = decl; + c = finish_omp_clauses (c); + if (c) + { + OMP_CLAUSE_CHAIN (c) = *clauses; + *clauses = c; + } + } + } + cond = TREE_VEC_ELT (OMP_FOR_COND (t), i); + if (COMPARISON_CLASS_P (cond)) + cond = build2 (TREE_CODE (cond), boolean_type_node, + RECUR (TREE_OPERAND (cond, 0)), + RECUR (TREE_OPERAND (cond, 1))); + else + cond = RECUR (cond); + incr = TREE_VEC_ELT (OMP_FOR_INCR (t), i); + switch (TREE_CODE (incr)) + { + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + incr = build2 (TREE_CODE (incr), TREE_TYPE (decl), + RECUR (TREE_OPERAND (incr, 0)), NULL_TREE); + break; + case MODIFY_EXPR: + if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR + || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR) + { + tree rhs = TREE_OPERAND (incr, 1); + incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), + RECUR (TREE_OPERAND (incr, 0)), + build2 (TREE_CODE (rhs), TREE_TYPE (decl), + RECUR (TREE_OPERAND (rhs, 0)), + RECUR (TREE_OPERAND (rhs, 1)))); + } + else + incr = RECUR (incr); + break; + case MODOP_EXPR: + if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR + || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR) + { + tree lhs = RECUR (TREE_OPERAND (incr, 0)); + incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), lhs, + build2 (TREE_CODE (TREE_OPERAND (incr, 1)), + TREE_TYPE (decl), lhs, + RECUR (TREE_OPERAND (incr, 2)))); + } + else if (TREE_CODE (TREE_OPERAND (incr, 1)) == NOP_EXPR + && (TREE_CODE (TREE_OPERAND (incr, 2)) == PLUS_EXPR + || (TREE_CODE (TREE_OPERAND (incr, 2)) == MINUS_EXPR))) + { + tree rhs = TREE_OPERAND (incr, 2); + incr = build2 (MODIFY_EXPR, TREE_TYPE (decl), + RECUR (TREE_OPERAND (incr, 0)), + build2 (TREE_CODE (rhs), TREE_TYPE (decl), + RECUR (TREE_OPERAND (rhs, 0)), + RECUR (TREE_OPERAND (rhs, 1)))); + } + else + incr = RECUR (incr); + break; + default: + incr = RECUR (incr); + break; + } + + TREE_VEC_ELT (declv, i) = decl; + TREE_VEC_ELT (initv, i) = init; + TREE_VEC_ELT (condv, i) = cond; + TREE_VEC_ELT (incrv, i) = incr; +#undef RECUR +} + /* Like tsubst_copy for expressions, etc. but also does semantic processing. */ @@ -10597,21 +10739,55 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, = OMP_PARALLEL_COMBINED (t); break; + case OMP_TASK: + tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), + args, complain, in_decl); + stmt = begin_omp_task (); + RECUR (OMP_TASK_BODY (t)); + finish_omp_task (tmp, stmt); + break; + case OMP_FOR: { - tree clauses, decl, init, cond, incr, body, pre_body; + tree clauses, body, pre_body; + tree declv, initv, condv, incrv; + int i; clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), args, complain, in_decl); - init = OMP_FOR_INIT (t); - gcc_assert (TREE_CODE (init) == MODIFY_EXPR); - decl = RECUR (TREE_OPERAND (init, 0)); - init = RECUR (TREE_OPERAND (init, 1)); - cond = RECUR (OMP_FOR_COND (t)); - incr = RECUR (OMP_FOR_INCR (t)); + 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))); + incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t))); + + for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (t)); i++) + tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv, + &clauses, args, complain, in_decl, + integral_constant_expression_p); stmt = begin_omp_structured_block (); + for (i = 0; i < TREE_VEC_LENGTH (initv); i++) + if (TREE_VEC_ELT (initv, i) == NULL + || TREE_CODE (TREE_VEC_ELT (initv, i)) != DECL_EXPR) + TREE_VEC_ELT (initv, i) = RECUR (TREE_VEC_ELT (initv, i)); + else if (CLASS_TYPE_P (TREE_TYPE (TREE_VEC_ELT (initv, i)))) + { + tree init = RECUR (TREE_VEC_ELT (initv, i)); + gcc_assert (init == TREE_VEC_ELT (declv, i)); + TREE_VEC_ELT (initv, i) = NULL_TREE; + } + else + { + tree decl_expr = TREE_VEC_ELT (initv, i); + tree init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr)); + gcc_assert (init != NULL); + TREE_VEC_ELT (initv, i) = RECUR (init); + DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL; + RECUR (decl_expr); + DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = init; + } + pre_body = push_stmt_list (); RECUR (OMP_FOR_PRE_BODY (t)); pre_body = pop_stmt_list (pre_body); @@ -10620,10 +10796,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, RECUR (OMP_FOR_BODY (t)); body = pop_stmt_list (body); - t = finish_omp_for (EXPR_LOCATION (t), decl, init, cond, incr, body, - pre_body); - if (t) - OMP_FOR_CLAUSES (t) = clauses; + t = finish_omp_for (EXPR_LOCATION (t), declv, initv, condv, incrv, + body, pre_body, clauses); add_stmt (finish_omp_structured_block (stmt)); } @@ -16195,6 +16369,63 @@ dependent_template_id_p (tree tmpl, tree args) || any_dependent_template_arguments_p (args)); } +/* Returns TRUE if OMP_FOR with DECLV, INITV, CONDV and INCRV vectors + is dependent. */ + +bool +dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv) +{ + int i; + + if (!processing_template_decl) + return false; + + for (i = 0; i < TREE_VEC_LENGTH (declv); i++) + { + 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); + + if (type_dependent_expression_p (decl)) + return true; + + if (init && type_dependent_expression_p (init)) + return true; + + if (type_dependent_expression_p (cond)) + return true; + + if (COMPARISON_CLASS_P (cond) + && (type_dependent_expression_p (TREE_OPERAND (cond, 0)) + || type_dependent_expression_p (TREE_OPERAND (cond, 1)))) + return true; + + if (TREE_CODE (incr) == MODOP_EXPR) + { + if (type_dependent_expression_p (TREE_OPERAND (incr, 0)) + || type_dependent_expression_p (TREE_OPERAND (incr, 2))) + return true; + } + else if (type_dependent_expression_p (incr)) + return true; + else if (TREE_CODE (incr) == MODIFY_EXPR) + { + if (type_dependent_expression_p (TREE_OPERAND (incr, 0))) + return true; + else if (BINARY_CLASS_P (TREE_OPERAND (incr, 1))) + { + tree t = TREE_OPERAND (incr, 1); + if (type_dependent_expression_p (TREE_OPERAND (t, 0)) + || type_dependent_expression_p (TREE_OPERAND (t, 1))) + return true; + } + } + } + + return false; +} + /* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the TYPENAME_TYPE corresponds. Returns the original TYPENAME_TYPE if no such TYPE can be found. Note that this function peers inside |