@@ -1245,7 +1245,7 @@ extern void c_finish_omp_flush (location_t);
extern void c_finish_omp_taskwait (location_t);
extern void c_finish_omp_taskyield (location_t);
extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
- tree, tree, tree);
+ tree, tree, tree, tree);
extern tree c_finish_oacc_wait (location_t, tree, tree);
extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
tree, tree *);
@@ -432,6 +432,10 @@ c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
/* Validate and generate OMP_FOR.
DECLV is a vector of iteration variables, for each collapsed loop.
+
+ ORIG_DECLV, if non-NULL, is a vector with the original iteration
+ variables (prior to any transformations, by say, C++ iterators).
+
INITV, CONDV and INCRV are vectors containing initialization
expressions, controlling predicates and increment expressions.
BODY is the body of the loop and PRE_BODY statements that go before
@@ -439,7 +443,8 @@ c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
tree
c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
- tree initv, tree condv, tree incrv, tree body, tree pre_body)
+ tree orig_declv, tree initv, tree condv, tree incrv,
+ tree body, tree pre_body)
{
location_t elocus;
bool fail = false;
@@ -678,6 +683,8 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
OMP_FOR_INCR (t) = incrv;
OMP_FOR_BODY (t) = body;
OMP_FOR_PRE_BODY (t) = pre_body;
+ if (code == OMP_FOR)
+ OMP_FOR_ORIG_DECLS (t) = orig_declv;
SET_EXPR_LOCATION (t, locus);
return add_stmt (t);
@@ -13696,7 +13696,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
an error from the initialization parsing. */
if (!fail)
{
- stmt = c_finish_omp_for (loc, code, declv, initv, condv,
+ stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv,
incrv, body, NULL);
if (stmt)
{
@@ -6027,7 +6027,7 @@ extern tree begin_omp_task (void);
extern tree finish_omp_task (tree, tree);
extern tree finish_omp_for (location_t, enum tree_code,
tree, tree, tree, tree, tree,
- tree, tree);
+ tree, tree, tree);
extern void finish_omp_atomic (enum tree_code, enum tree_code,
tree, tree, tree, tree, tree,
bool);
@@ -31328,8 +31328,8 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
if (declv == NULL_TREE)
ret = NULL_TREE;
else
- ret = finish_omp_for (loc_first, code, declv, initv, condv, incrv, body,
- pre_body, clauses);
+ ret = finish_omp_for (loc_first, code, declv, NULL, initv, condv, incrv,
+ body, pre_body, clauses);
while (nbraces)
{
@@ -13816,8 +13816,8 @@ static tree *omp_parallel_combined_clauses;
/* 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,
+tsubst_omp_for_iterator (tree t, int i, tree declv, tree orig_declv,
+ tree initv, tree condv, tree incrv, tree *clauses,
tree args, tsubst_flags_t complain, tree in_decl,
bool integral_constant_expression_p)
{
@@ -13828,6 +13828,16 @@ tsubst_omp_for_iterator (tree t, int i, tree declv, tree initv,
init = TREE_VEC_ELT (OMP_FOR_INIT (t), i);
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+
+ if (orig_declv && OMP_FOR_ORIG_DECLS (t))
+ {
+ tree o = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (t), i);
+ tree spec = retrieve_local_specialization (o);
+ if (spec)
+ o = spec;
+ TREE_VEC_ELT (orig_declv, i) = o;
+ }
+
decl = TREE_OPERAND (init, 0);
init = TREE_OPERAND (init, 1);
tree decl_expr = NULL_TREE;
@@ -14459,6 +14469,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
{
tree clauses, body, pre_body;
tree declv = NULL_TREE, initv = NULL_TREE, condv = NULL_TREE;
+ tree orig_declv = NULL_TREE;
tree incrv = NULL_TREE;
int i;
@@ -14468,6 +14479,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
if (OMP_FOR_INIT (t) != NULL_TREE)
{
declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
+ if (TREE_CODE (t) == OMP_FOR)
+ 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)));
incrv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
@@ -14481,8 +14494,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
if (OMP_FOR_INIT (t) != NULL_TREE)
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,
+ tsubst_omp_for_iterator (t, i, declv, orig_declv, initv, condv,
+ incrv, &clauses, args, complain, in_decl,
integral_constant_expression_p);
omp_parallel_combined_clauses = NULL;
@@ -14491,8 +14504,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
body = pop_stmt_list (body);
if (OMP_FOR_INIT (t) != NULL_TREE)
- t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv, initv,
- condv, incrv, body, pre_body, clauses);
+ t = finish_omp_for (EXPR_LOCATION (t), TREE_CODE (t), declv,
+ orig_declv, initv, condv, incrv, body, pre_body,
+ clauses);
else
{
t = make_node (TREE_CODE (t));
@@ -22151,7 +22165,7 @@ dependent_template_id_p (tree tmpl, tree args)
}
/* Returns TRUE if OMP_FOR with DECLV, INITV, CONDV and INCRV vectors
- is dependent. */
+ are dependent. */
bool
dependent_omp_for_p (tree declv, tree initv, tree condv, tree incrv)
@@ -7235,8 +7235,9 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
sk_omp scope. */
tree
-finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
- tree condv, tree incrv, tree body, tree pre_body, tree clauses)
+finish_omp_for (location_t locus, enum tree_code code, tree declv,
+ tree orig_declv, tree initv, tree condv, tree incrv,
+ tree body, tree pre_body, tree clauses)
{
tree omp_for = NULL, orig_incr = NULL;
tree decl = NULL, init, cond, incr, orig_decl = NULL_TREE, block = NULL_TREE;
@@ -7302,6 +7303,9 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
TREE_VEC_ELT (initv, i) = init;
}
+ if (!orig_declv || !TREE_VEC_LENGTH (orig_declv))
+ orig_declv = copy_node (declv);
+
if (dependent_omp_for_p (declv, initv, condv, incrv))
{
tree stmt;
@@ -7325,6 +7329,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
OMP_FOR_BODY (stmt) = body;
OMP_FOR_PRE_BODY (stmt) = pre_body;
OMP_FOR_CLAUSES (stmt) = clauses;
+ if (code == OMP_FOR)
+ OMP_FOR_ORIG_DECLS (stmt) = orig_declv;
SET_EXPR_LOCATION (stmt, locus);
return add_stmt (stmt);
@@ -7430,8 +7436,8 @@ finish_omp_for (location_t locus, enum tree_code code, tree declv, tree initv,
if (code == CILK_FOR && !processing_template_decl)
block = push_stmt_list ();
- omp_for = c_finish_omp_for (locus, code, declv, initv, condv, incrv,
- body, pre_body);
+ omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
+ incrv, body, pre_body);
if (omp_for == NULL)
{
@@ -7311,7 +7311,11 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
gcc_assert (DECL_P (decl));
gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
|| POINTER_TYPE_P (TREE_TYPE (decl)));
- gimplify_omp_ctxp->iter_vars.quick_push (decl);
+ if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
+ gimplify_omp_ctxp->iter_vars.quick_push
+ (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i));
+ else
+ gimplify_omp_ctxp->iter_vars.quick_push (decl);
/* Make sure the iteration variable is private. */
tree c = NULL_TREE;
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+void bar (int *);
+
+void
+foo ()
+{
+ int i,j;
+#pragma omp parallel for ordered(1)
+ for (i=0; i < 100; ++i)
+ {
+#pragma omp ordered depend(sink:i-1)
+ bar(&i);
+ }
+}
new file mode 100644
@@ -0,0 +1,64 @@
+/* { dg-do compile } */
+
+/* Tests iterators are allowed in ordered loops and that we keep track
+ of the original iterator DECL for diagnostic purposes. */
+
+#include <iostream>
+#include <vector>
+
+/* Test plain iterator. */
+void foo1 ()
+{
+ std::vector<int> v;
+ for (int i=1; i<=5; i++) v.push_back(i);
+
+ std::vector<int>::const_iterator it;
+
+#pragma omp parallel for ordered(1)
+ for (it = v.begin(); it < v.end(); ++it)
+ {
+#pragma omp ordered depend(sink:it-1)
+ std::cout << *it << '\n';
+#pragma omp ordered depend(source)
+ }
+}
+
+/* Test non-dependent iterator in a template. */
+template <int N>
+void foo2 ()
+{
+ std::vector<int> v;
+ for (int i=1; i<=5; i++) v.push_back(i);
+
+ std::vector<int>::const_iterator it;
+#pragma omp parallel for ordered(1)
+ for (it = v.begin(); it < v.end(); ++it)
+ {
+#pragma omp ordered depend(sink:it-1)
+ std::cout << *it << '\n';
+#pragma omp ordered depend(source)
+ }
+}
+
+/* Test dependent iterator in a template. */
+template <typename T>
+void foo3 ()
+{
+ std::vector<T> v;
+ for (int i=1; i<=5; i++) v.push_back(i);
+
+ typename std::vector<T>::const_iterator it;
+#pragma omp parallel for ordered(1)
+ for (it = v.begin(); it < v.end(); ++it)
+ {
+#pragma omp ordered depend(sink:it-1)
+ std::cout << *it << '\n';
+#pragma omp ordered depend(source)
+ }
+}
+
+int main ()
+{
+ foo2 <0> ();
+ foo3 <int> ();
+}
@@ -1087,36 +1087,41 @@ DEFTREECODE (OMP_TASK, "omp_task", tcc_statement, 2)
from INIT, COND, and INCR that are technically part of the
OMP_FOR structured block, but are evaluated before the loop
body begins.
+ Operand 6: OMP_FOR_ORIG_DECLS: If non-NULL, list of DECLs initialized
+ in OMP_FOR_INIT. In some cases, like C++ iterators, the original
+ DECL init has been lost in gimplification and now contains a
+ temporary (D.nnnn). This list contains the original DECLs in
+ the source.
VAR must be an integer or pointer variable, which is implicitly thread
private. N1, N2 and INCR are required to be loop invariant integer
expressions that are evaluated without any synchronization.
The evaluation order, frequency of evaluation and side-effects are
unspecified by the standards. */
-DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 6)
+DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 7)
/* OpenMP - #pragma omp simd [clause1 ... clauseN]
- Operands like for OMP_FOR. */
+ Operands like operands 1-6 of OMP_FOR. */
DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
/* Cilk Plus - #pragma simd [clause1 ... clauseN]
- Operands like for OMP_FOR. */
+ Operands like operands 1-6 of OMP_FOR. */
DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6)
/* Cilk Plus - _Cilk_for (..)
- Operands like for OMP_FOR. */
+ Operands like operands 1-6 of OMP_FOR. */
DEFTREECODE (CILK_FOR, "cilk_for", tcc_statement, 6)
/* OpenMP - #pragma omp distribute [clause1 ... clauseN]
- Operands like for OMP_FOR. */
+ Operands like operands 1-6 of OMP_FOR. */
DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)
/* OpenMP - #pragma omp taskloop [clause1 ... clauseN]
- Operands like for OMP_FOR. */
+ Operands like operands 1-6 of OMP_FOR. */
DEFTREECODE (OMP_TASKLOOP, "omp_taskloop", tcc_statement, 6)
/* OpenMP - #pragma acc loop [clause1 ... clauseN]
- Operands like for OMP_FOR. */
+ Operands like operands 1-6 of OMP_FOR. */
DEFTREECODE (OACC_LOOP, "oacc_loop", tcc_statement, 6)
/* OpenMP - #pragma omp teams [clause1 ... clauseN]
@@ -1260,6 +1260,8 @@ extern void protected_set_expr_location (tree, location_t);
#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 3)
#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 4)
#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOP_CHECK (NODE), 5)
+/* Note that this is only available for OMP_FOR, hence OMP_FOR_CHECK. */
+#define OMP_FOR_ORIG_DECLS(NODE) TREE_OPERAND (OMP_FOR_CHECK (NODE), 6)
#define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
#define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)