[gomp4.5] Add checking that OpenMP loop iterators aren't referenced in the bounds/step expressions

Jakub Jelinek jakub@redhat.com
Mon Oct 19 15:54:00 GMT 2015


Hi!

In 4.0 and earlier, there has just been a restriction that the lb, b and
incr expressions in the syntax (low/high bounds and step) can't change their
values during the loop, but in OpenMP 4.5 we have even stronger restriction,
the iterators may not be referenced in there at all, so even if you ignore
the value, or multiply or and with 0, subtract it from itself etc., it is
still invalid.  That means the compiler can actually easily diagnose invalid
loops.

2015-10-19  Jakub Jelinek  <jakub@redhat.com>

gcc/
	* tree.h (OMP_FOR_ORIG_DECLS): Use OMP_LOOP_CHECK instead of
	OMP_FOR_CHECK.  Remove comment.
	* tree.def (OMP_SIMD, CILK_SIMD, CILK_FOR, OMP_DISTRIBUTE,
	OMP_TASKLOOP, OACC_LOOP): Add OMP_FOR_ORIG_DECLS argument.
gcc/c-family/
	* c-common.h (c_omp_check_loop_iv, c_omp_check_loop_iv_exprs): New
	prototypes.
	* c-omp.c (c_finish_omp_for): Store OMP_FOR_ORIG_DECLS always.
	Don't call add_stmt here.
	(struct c_omp_check_loop_iv_data): New type.
	(c_omp_check_loop_iv_r, c_omp_check_loop_iv,
	c_omp_check_loop_iv_exprs): New functions.
gcc/c/
	* c-parser.c (c_parser_omp_for_loop): Call c_omp_check_loop_iv.
	Call add_stmt here.
gcc/cp/
	* cp-tree.h (finish_omp_for): Add ORIG_INITS argument.
	* parser.c (cp_parser_omp_for_loop_init): Add ORIG_INIT argument,
	initialize it.
	(cp_parser_omp_for_loop): Compute orig_inits, pass it's address
	to finish_omp_for.
	* pt.c (tsubst_expr): Use OMP_FOR_ORIG_DECLS for all
	OpenMP/OpenACC/Cilk+ looping constructs.  Adjust finish_omp_for
	caller.
	* semantics.c (handle_omp_for_class_iterator): Add ORIG_DECLS
	argument.  Call c_omp_check_loop_iv_exprs on cond.
	(finish_omp_for): Add ORIG_INITS argument.  Call
	c_omp_check_loop_iv_exprs on ORIG_INITS elements.  Adjust
	handle_omp_for_class_iterator caller.  Call c_omp_check_loop_iv.
	Call add_stmt.
gcc/testsuite/
	* c-c++-common/gomp/pr67521.c: Add dg-error directives.
	* gcc.dg/gomp/loop-1.c: New test.
	* g++.dg/gomp/pr38639.C (foo): Adjust dg-error.
	(bar): Remove dg-message.
	* g++.dg/gomp/loop-1.C: New test.
	* g++.dg/gomp/loop-2.C: New test.
	* g++.dg/gomp/loop-3.C: New test.

--- gcc/tree.h.jj	2015-10-14 10:24:55.000000000 +0200
+++ gcc/tree.h	2015-10-19 12:01:11.390680056 +0200
@@ -1264,8 +1264,7 @@ extern void protected_set_expr_location
 #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_FOR_ORIG_DECLS(NODE)   TREE_OPERAND (OMP_LOOP_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)
--- gcc/tree.def.jj	2015-10-14 10:25:43.000000000 +0200
+++ gcc/tree.def	2015-10-19 12:00:50.282982246 +0200
@@ -1101,28 +1101,28 @@ DEFTREECODE (OMP_TASK, "omp_task", tcc_s
 DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 7)
 
 /* OpenMP - #pragma omp simd [clause1 ... clauseN]
-   Operands like operands 1-6 of OMP_FOR.  */
-DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 6)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 7)
 
 /* Cilk Plus - #pragma simd [clause1 ... clauseN]
-   Operands like operands 1-6 of OMP_FOR.  */
-DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 6)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (CILK_SIMD, "cilk_simd", tcc_statement, 7)
 
 /* Cilk Plus - _Cilk_for (..)
-   Operands like operands 1-6 of OMP_FOR.  */
-DEFTREECODE (CILK_FOR, "cilk_for", tcc_statement, 6)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (CILK_FOR, "cilk_for", tcc_statement, 7)
 
 /* OpenMP - #pragma omp distribute [clause1 ... clauseN]
-   Operands like operands 1-6 of OMP_FOR.  */
-DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 6)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 7)
 
 /* OpenMP - #pragma omp taskloop [clause1 ... clauseN]
-   Operands like operands 1-6 of OMP_FOR.  */
-DEFTREECODE (OMP_TASKLOOP, "omp_taskloop", tcc_statement, 6)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (OMP_TASKLOOP, "omp_taskloop", tcc_statement, 7)
 
 /* OpenMP - #pragma acc loop [clause1 ... clauseN]
-   Operands like operands 1-6 of OMP_FOR.  */
-DEFTREECODE (OACC_LOOP, "oacc_loop", tcc_statement, 6)
+   Operands like for OMP_FOR.  */
+DEFTREECODE (OACC_LOOP, "oacc_loop", tcc_statement, 7)
 
 /* OpenMP - #pragma omp teams [clause1 ... clauseN]
    Operand 0: OMP_TEAMS_BODY: Teams body.
--- gcc/c-family/c-common.h.jj	2015-10-14 10:24:54.000000000 +0200
+++ gcc/c-family/c-common.h	2015-10-19 15:04:58.740284268 +0200
@@ -1268,6 +1268,9 @@ extern void c_finish_omp_taskwait (locat
 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);
+extern bool c_omp_check_loop_iv (tree, tree, walk_tree_lh);
+extern bool c_omp_check_loop_iv_exprs (location_t, tree, tree, tree, tree,
+				       walk_tree_lh);
 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 *);
--- gcc/c-family/c-omp.c.jj	2015-10-14 10:24:54.000000000 +0200
+++ gcc/c-family/c-omp.c	2015-10-19 17:12:42.211884644 +0200
@@ -683,14 +683,173 @@ c_finish_omp_for (location_t locus, enum
       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;
+      OMP_FOR_ORIG_DECLS (t) = orig_declv;
 
       SET_EXPR_LOCATION (t, locus);
-      return add_stmt (t);
+      return t;
     }
 }
 
+/* Type for passing data in between c_omp_check_loop_iv and
+   c_omp_check_loop_iv_r.  */
+
+struct c_omp_check_loop_iv_data
+{
+  tree declv;
+  bool fail;
+  location_t stmt_loc;
+  location_t expr_loc;
+  int kind;
+  walk_tree_lh lh;
+  hash_set<tree> *ppset;
+};
+
+/* Helper function called via walk_tree, to diagnose uses
+   of associated loop IVs inside of lb, b and incr expressions
+   of OpenMP loops.  */
+   
+static tree
+c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
+{
+  struct c_omp_check_loop_iv_data *d
+    = (struct c_omp_check_loop_iv_data *) data;
+  if (DECL_P (*tp))
+    {
+      int i;
+      for (i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
+	if (*tp == TREE_VEC_ELT (d->declv, i))
+	  {
+	    location_t loc = d->expr_loc;
+	    if (loc == UNKNOWN_LOCATION)
+	      loc = d->stmt_loc;
+	    switch (d->kind)
+	      {
+	      case 0:
+		error_at (loc, "initializer expression refers to "
+			       "iteration variable %qD", *tp);
+		break;
+	      case 1:
+		error_at (loc, "condition expression refers to "
+			       "iteration variable %qD", *tp);
+		break;
+	      case 2:
+		error_at (loc, "increment expression refers to "
+			       "iteration variable %qD", *tp);
+		break;
+	      }
+	    d->fail = true;
+	  }
+    }
+  /* Don't walk dtors added by C++ wrap_cleanups_r.  */
+  else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
+	   && TRY_CATCH_IS_CLEANUP (*tp))
+    {
+      *walk_subtrees = 0;
+      return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
+			  d->ppset, d->lh);
+    }
+
+  return NULL_TREE;
+}
+
+/* Diagnose invalid references to loop iterators in lb, b and incr
+   expressions.  */
+
+bool
+c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
+{
+  hash_set<tree> pset;
+  struct c_omp_check_loop_iv_data data;
+  int i;
+
+  data.declv = declv;
+  data.fail = false;
+  data.stmt_loc = EXPR_LOCATION (stmt);
+  data.lh = lh;
+  data.ppset = &pset;
+  for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
+    {
+      tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
+      gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
+      tree decl = TREE_OPERAND (init, 0);
+      tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
+      gcc_assert (COMPARISON_CLASS_P (cond));
+      gcc_assert (TREE_OPERAND (cond, 0) == decl);
+      tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
+      data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
+      data.kind = 0;
+      walk_tree_1 (&TREE_OPERAND (init, 1),
+		   c_omp_check_loop_iv_r, &data, &pset, lh);
+      /* Don't warn for C++ random access iterators here, the
+	 expression then involves the subtraction and always refers
+	 to the original value.  The C++ FE needs to warn on those
+	 earlier.  */
+      if (decl == TREE_VEC_ELT (declv, i))
+	{
+	  data.expr_loc = EXPR_LOCATION (cond);
+	  data.kind = 1;
+	  walk_tree_1 (&TREE_OPERAND (cond, 1),
+		       c_omp_check_loop_iv_r, &data, &pset, lh);
+	}
+      if (TREE_CODE (incr) == MODIFY_EXPR)
+	{
+	  gcc_assert (TREE_OPERAND (incr, 0) == decl);
+	  incr = TREE_OPERAND (incr, 1);
+	  data.kind = 2;
+	  if (TREE_CODE (incr) == PLUS_EXPR
+	      && TREE_OPERAND (incr, 1) == decl)
+	    {
+	      data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
+	      walk_tree_1 (&TREE_OPERAND (incr, 0),
+			   c_omp_check_loop_iv_r, &data, &pset, lh);
+	    }
+	  else
+	    {
+	      data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
+	      walk_tree_1 (&TREE_OPERAND (incr, 1),
+			   c_omp_check_loop_iv_r, &data, &pset, lh);
+	    }
+	}
+    }
+  return !data.fail;
+}
+
+/* Similar, but allows to check the init or cond expressions individually.  */
+
+bool
+c_omp_check_loop_iv_exprs (location_t stmt_loc, tree declv, tree decl,
+			   tree init, tree cond, walk_tree_lh lh)
+{
+  hash_set<tree> pset;
+  struct c_omp_check_loop_iv_data data;
+
+  data.declv = declv;
+  data.fail = false;
+  data.stmt_loc = stmt_loc;
+  data.lh = lh;
+  data.ppset = &pset;
+  if (init)
+    {
+      data.expr_loc = EXPR_LOCATION (init);
+      data.kind = 0;
+      walk_tree_1 (&init,
+		   c_omp_check_loop_iv_r, &data, &pset, lh);
+    }
+  if (cond)
+    {
+      gcc_assert (COMPARISON_CLASS_P (cond));
+      data.expr_loc = EXPR_LOCATION (init);
+      data.kind = 1;
+      if (TREE_OPERAND (cond, 0) == decl)
+	walk_tree_1 (&TREE_OPERAND (cond, 1),
+		     c_omp_check_loop_iv_r, &data, &pset, lh);
+      else
+	walk_tree_1 (&TREE_OPERAND (cond, 0),
+		     c_omp_check_loop_iv_r, &data, &pset, lh);
+    }
+  return !data.fail;
+}
+
 /* Right now we have 21 different combined/composite constructs, this
    function attempts to split or duplicate clauses for combined
    constructs.  CODE is the innermost construct in the combined construct,
--- gcc/c/c-parser.c.jj	2015-10-19 12:39:22.000000000 +0200
+++ gcc/c/c-parser.c	2015-10-19 15:18:40.928501691 +0200
@@ -13991,8 +13991,15 @@ c_parser_omp_for_loop (location_t loc, c
     {
       stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv,
 			       incrv, body, pre_body);
+
+      /* Check for iterators appearing in lb, b or incr expressions.  */
+      if (stmt && !c_omp_check_loop_iv (stmt, declv, NULL))
+	stmt = NULL_TREE;
+
       if (stmt)
 	{
+	  add_stmt (stmt);
+
 	  if (cclauses != NULL
 	      && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
 	    {
--- gcc/cp/cp-tree.h.jj	2015-10-14 10:25:31.000000000 +0200
+++ gcc/cp/cp-tree.h	2015-10-19 14:43:41.571508885 +0200
@@ -6326,7 +6326,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, vec<tree> *, tree);
 extern void finish_omp_atomic			(enum tree_code, enum tree_code,
 						 tree, tree, tree, tree, tree,
 						 bool);
--- gcc/cp/parser.c.jj	2015-10-15 17:36:30.000000000 +0200
+++ gcc/cp/parser.c	2015-10-19 14:43:21.592793906 +0200
@@ -32447,6 +32447,7 @@ cp_parser_omp_for_loop_init (cp_parser *
 			     tree &this_pre_body,
 			     vec<tree, va_gc> *for_block,
 			     tree &init,
+			     tree &orig_init,
 			     tree &decl,
 			     tree &real_decl)
 {
@@ -32544,6 +32545,7 @@ cp_parser_omp_for_loop_init (cp_parser *
 	      cp_finish_decl (decl, init, !is_non_constant_init,
 			      asm_specification,
 			      LOOKUP_ONLYCONVERTING);
+	      orig_init = init;
 	      if (CLASS_TYPE_P (TREE_TYPE (decl)))
 		{
 		  vec_safe_push (for_block, this_pre_body);
@@ -32621,6 +32623,7 @@ cp_parser_omp_for_loop_init (cp_parser *
 	  cp_parser_parse_definitely (parser);
 	  cp_parser_require (parser, CPP_EQ, RT_EQ);
 	  rhs = cp_parser_assignment_expression (parser);
+	  orig_init = rhs;
 	  finish_expr_stmt (build_x_modify_expr (EXPR_LOCATION (rhs),
 						 decl, NOP_EXPR,
 						 rhs,
@@ -32650,13 +32653,14 @@ static tree
 cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
 			tree *cclauses)
 {
-  tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
+  tree init, orig_init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
   tree real_decl, initv, condv, incrv, declv;
   tree this_pre_body, cl, ordered_cl = NULL_TREE;
   location_t loc_first;
   bool collapse_err = false;
   int i, collapse = 1, ordered = 0, count, nbraces = 0;
   vec<tree, va_gc> *for_block = make_tree_vector ();
+  auto_vec<tree, 4> orig_inits;
 
   for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
     if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -32723,13 +32727,13 @@ cp_parser_omp_for_loop (cp_parser *parse
       if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
 	return NULL;
 
-      init = decl = real_decl = NULL;
+      init = orig_init = decl = real_decl = NULL;
       this_pre_body = push_stmt_list ();
 
       add_private_clause
 	= cp_parser_omp_for_loop_init (parser, code,
 				       this_pre_body, for_block,
-				       init, decl, real_decl);
+				       init, orig_init, decl, real_decl);
 
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       if (this_pre_body)
@@ -32861,6 +32865,11 @@ cp_parser_omp_for_loop (cp_parser *parse
       TREE_VEC_ELT (initv, i) = init;
       TREE_VEC_ELT (condv, i) = cond;
       TREE_VEC_ELT (incrv, i) = incr;
+      if (orig_init)
+	{
+	  orig_inits.safe_grow_cleared (i + 1);
+	  orig_inits[i] = orig_init;
+	}
 
       if (i == count - 1)
 	break;
@@ -32918,7 +32927,7 @@ cp_parser_omp_for_loop (cp_parser *parse
     ret = NULL_TREE;
   else
     ret = finish_omp_for (loc_first, code, declv, NULL, initv, condv, incrv,
-			  body, pre_body, clauses);
+			  body, pre_body, &orig_inits, clauses);
 
   while (nbraces)
     {
--- gcc/cp/pt.c.jj	2015-10-14 10:25:31.000000000 +0200
+++ gcc/cp/pt.c	2015-10-19 14:44:36.485725467 +0200
@@ -15237,7 +15237,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 	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)));
@@ -15264,7 +15264,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 	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));
--- gcc/cp/semantics.c.jj	2015-10-16 17:08:35.000000000 +0200
+++ gcc/cp/semantics.c	2015-10-19 15:58:13.386683491 +0200
@@ -7286,9 +7286,10 @@ finish_omp_task (tree clauses, tree body
 
 static bool
 handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
-			       tree declv, tree initv, tree condv, tree incrv,
-			       tree *body, tree *pre_body, tree &clauses,
-			       tree *lastp, int collapse, int ordered)
+			       tree declv, tree orig_declv, tree initv,
+			       tree condv, tree incrv, tree *body,
+			       tree *pre_body, tree &clauses, tree *lastp,
+			       int collapse, int ordered)
 {
   tree diff, iter_init, iter_incr = NULL, last;
   tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -7345,6 +7346,10 @@ handle_omp_for_class_iterator (int i, lo
 		TREE_OPERAND (cond, 1), iter);
       return true;
     }
+  if (!c_omp_check_loop_iv_exprs (locus, orig_declv,
+				  TREE_VEC_ELT (declv, i), NULL_TREE,
+				  cond, cp_walk_subtrees))
+    return true;
 
   switch (TREE_CODE (incr))
     {
@@ -7600,7 +7605,7 @@ handle_omp_for_class_iterator (int i, lo
 tree
 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 body, tree pre_body, vec<tree> *orig_inits, tree clauses)
 {
   tree omp_for = NULL, orig_incr = NULL;
   tree decl = NULL, init, cond, incr, orig_decl = NULL_TREE, block = NULL_TREE;
@@ -7676,6 +7681,20 @@ finish_omp_for (location_t locus, enum t
       TREE_VEC_ELT (initv, i) = init;
     }
 
+  if (orig_inits)
+    {
+      bool fail = false;
+      tree orig_init;
+      FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
+	if (orig_init
+	    && !c_omp_check_loop_iv_exprs (locus, declv,
+					   TREE_VEC_ELT (declv, i), orig_init,
+					   NULL_TREE, cp_walk_subtrees))
+	  fail = true;
+      if (fail)
+	return NULL;
+    }
+
   if (dependent_omp_for_p (declv, initv, condv, incrv))
     {
       tree stmt;
@@ -7749,10 +7768,10 @@ finish_omp_for (location_t locus, enum t
 	    }
 	  if (code == CILK_FOR && i == 0)
 	    orig_decl = decl;
-	  if (handle_omp_for_class_iterator (i, locus, code, declv, initv,
-					     condv, incrv, &body, &pre_body,
-					     clauses, &last, collapse,
-					     ordered))
+	  if (handle_omp_for_class_iterator (i, locus, code, declv, orig_declv,
+					     initv, condv, incrv, &body,
+					     &pre_body, clauses, &last,
+					     collapse, ordered))
 	    return NULL;
 	  continue;
 	}
@@ -7811,6 +7830,10 @@ finish_omp_for (location_t locus, enum t
   omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv,
 			      incrv, body, pre_body);
 
+  /* Check for iterators appearing in lb, b or incr expressions.  */
+  if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees))
+    omp_for = NULL_TREE;
+
   if (omp_for == NULL)
     {
       if (block)
@@ -7818,6 +7841,8 @@ finish_omp_for (location_t locus, enum t
       return NULL;
     }
 
+  add_stmt (omp_for);
+
   for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++)
     {
       decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i), 0);
--- gcc/testsuite/c-c++-common/gomp/pr67521.c.jj	2015-10-19 11:07:17.631880902 +0200
+++ gcc/testsuite/c-c++-common/gomp/pr67521.c	2015-10-19 11:07:55.249342590 +0200
@@ -7,14 +7,14 @@ foo (int x)
 {
   int i = 0;
   #pragma omp parallel for simd
-  for (i = (i & x); i < 10; i = i + 2)
+  for (i = (i & x); i < 10; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
     ;
   i = 0;
   #pragma omp parallel for simd
-  for (i = 0; i < (i & x) + 10; i = i + 2)
+  for (i = 0; i < (i & x) + 10; i = i + 2) /* { dg-error "condition expression refers to iteration variable" } */
     ;
   i = 0;
   #pragma omp parallel for simd
-  for (i = 0; i < 10; i = i + ((i & x) + 2))
+  for (i = 0; i < 10; i = i + ((i & x) + 2)) /* { dg-error "increment expression refers to iteration variable" } */
     ;
 }
--- gcc/testsuite/gcc.dg/gomp/loop-1.c.jj	2015-10-19 10:20:03.442502890 +0200
+++ gcc/testsuite/gcc.dg/gomp/loop-1.c	2015-10-19 11:56:25.848768035 +0200
@@ -0,0 +1,283 @@
+int bar (int);
+int baz (int *);
+
+void
+f1 (int x)
+{
+  int i = 0, j = 0;
+  #pragma omp for
+  for (i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  for (i = 0; 16 > i; i++)
+    ;
+  #pragma omp for
+  for (i = 0; i < 16; i = i + 2)
+    ;
+  #pragma omp for
+  for (i = 0; i < 16; i = 2 + i)
+    ;
+  #pragma omp for /* { dg-error "initializer expression refers to iteration variable" } */
+  for (i = i; i < 16; i++)
+    ;
+  #pragma omp for
+  for (i = 2 * (i & x); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = bar (i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = baz (&i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 2 * i + 17; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; 2 * i + 17 > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for /* { dg-error "increment expression refers to iteration variable" } */
+  for (i = 5; i < 16; i += i)
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment expression|increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for /* { dg-error "increment expression refers to iteration variable" } */
+  for (i = 5; i < 16; i = i + i)
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2)
+    for (j = 0; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "initializer expression refers to iteration variable" } */
+  for (i = j; i < 16; i = i + 2)
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "initializer expression refers to iteration variable" } */
+  for (i = 0; i < 16; i = i + 2)
+    for (j = i; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2)
+    for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 16; j > (i & x); j--) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < j; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < bar (j); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < baz (&i); j++) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2) /* { dg-error "increment expression refers to iteration variable" } */
+  for (i = 0; i < 16; i += j)
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "increment expression refers to iteration variable" } */
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < 16; j += i)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "increment expression refers to iteration variable" } */
+  for (i = 0; i < 16; i = j + i)
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "increment expression refers to iteration variable" } */
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < 16; j = j + i)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = bar (j) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < 16; j = j + baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+void
+f2 (int x)
+{
+  #pragma omp for
+  for (int i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  for (int i = 0; 16 > i; i++)
+    ;
+  #pragma omp for
+  for (int i = 0; i < 16; i = i + 2)
+    ;
+  #pragma omp for
+  for (int i = 0; i < 16; i = 2 + i)
+    ;
+  #pragma omp for /* { dg-error "initializer expression refers to iteration variable" } */
+  for (int i = i; i < 16; i++)
+    ;
+  #pragma omp for
+  for (int i = 2 * (i & x); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = bar (i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = baz (&i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 2 * i + 17; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; 2 * i + 17 > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for /* { dg-error "increment expression refers to iteration variable" } */
+  for (int i = 5; i < 16; i += i)
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment expression|increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for /* { dg-error "increment expression refers to iteration variable" } */
+  for (int i = 5; i < 16; i = i + i)
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = 0; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "initializer expression refers to iteration variable" } */
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = i; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 16; j > (i & x); j--) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < i; j++) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < i + 4; j++) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < baz (&i); j++) /* { dg-error "condition expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2) /* { dg-error "increment expression refers to iteration variable" } */
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < 16; j += i)
+      ;
+  #pragma omp for collapse(2) /* { dg-error "increment expression refers to iteration variable" } */
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < 16; j = j + i)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < 16; j = j + baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+void
+f3 (void)
+{
+  int j = 0;
+  #pragma omp for collapse(2)
+  for (int i = j; i < 16; i = i + 2)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < j + 4; i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < j; i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < bar (j); i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i += j)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = j + i)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = bar (j) + i)
+    for (int j = 0; j < 16; j++)
+      ;
+}
--- gcc/testsuite/g++.dg/gomp/pr38639.C.jj	2015-10-14 10:25:28.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr38639.C	2015-10-19 15:09:38.005272514 +0200
@@ -6,12 +6,12 @@ template<int> void
 foo ()
 {
 #pragma omp parallel for
-  for (auto i = i = 0; i<4; ++i)	// { dg-error "incomplete|unable|invalid|auto" }
+  for (auto i = i = 0; i<4; ++i)	// { dg-error "initializer expression refers to iteration variable" }
     ;
 }
 
 void
 bar ()
 {
-  foo<0> ();				// { dg-message "required from here" }
+  foo<0> ();
 }
--- gcc/testsuite/g++.dg/gomp/loop-1.C.jj	2015-10-19 13:07:38.469657173 +0200
+++ gcc/testsuite/g++.dg/gomp/loop-1.C	2015-10-19 13:18:05.659683587 +0200
@@ -0,0 +1,283 @@
+int bar (int);
+int baz (int *);
+
+void
+f1 (int x)
+{
+  int i = 0, j = 0;
+  #pragma omp for
+  for (i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  for (i = 0; 16 > i; i++)
+    ;
+  #pragma omp for
+  for (i = 0; i < 16; i = i + 2)
+    ;
+  #pragma omp for
+  for (i = 0; i < 16; i = 2 + i)
+    ;
+  #pragma omp for
+  for (i = i; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 2 * (i & x); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = bar (i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = baz (&i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 2 * i + 17; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; 2 * i + 17 > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment expression|increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2)
+    for (j = 0; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = j; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = i; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2)
+    for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = baz (&i); j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 16; j > (i & x); j--)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < i; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < i + 4; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < j; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < bar (j); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < baz (&i); j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i += j) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j += i)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = j + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j = j + i)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = bar (j) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < 16; j = j + baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+void
+f2 (int x)
+{
+  #pragma omp for
+  for (int i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  for (int i = 0; 16 > i; i++)
+    ;
+  #pragma omp for
+  for (int i = 0; i < 16; i = i + 2)
+    ;
+  #pragma omp for
+  for (int i = 0; i < 16; i = 2 + i)
+    ;
+  #pragma omp for
+  for (int i = i; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 2 * (i & x); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = bar (i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = baz (&i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 2 * i + 17; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; 2 * i + 17 > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment expression|increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = 0; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (int j = i; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (int j = baz (&i); j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 16; j > (i & x); j--)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 0; j < i; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 0; j < i + 4; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 0; j < baz (&i); j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (int j = 0; j < 16; j += i)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (int j = 0; j < 16; j = j + i)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < 16; j = j + baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+void
+f3 (void)
+{
+  int j = 0;
+  #pragma omp for collapse(2)
+  for (int i = j; i < 16; i = i + 2)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < j + 4; i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < j; i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < bar (j); i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i += j)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = j + i)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = bar (j) + i)
+    for (int j = 0; j < 16; j++)
+      ;
+}
--- gcc/testsuite/g++.dg/gomp/loop-2.C.jj	2015-10-19 15:10:38.145407819 +0200
+++ gcc/testsuite/g++.dg/gomp/loop-2.C	2015-10-19 15:12:42.936613569 +0200
@@ -0,0 +1,294 @@
+int bar (int);
+int baz (int *);
+
+template <int N>
+void
+f1 (int x)
+{
+  int i = 0, j = 0;
+  #pragma omp for
+  for (i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  for (i = 0; 16 > i; i++)
+    ;
+  #pragma omp for
+  for (i = 0; i < 16; i = i + 2)
+    ;
+  #pragma omp for
+  for (i = 0; i < 16; i = 2 + i)
+    ;
+  #pragma omp for
+  for (i = i; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 2 * (i & x); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = bar (i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = baz (&i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 2 * i + 17; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; 2 * i + 17 > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment expression|increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = 5; i < 16; i += baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2)
+    for (j = 0; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = j; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = i; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = i + 2)
+    for (j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 16; j > (i & x); j--)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < i; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < i + 4; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < j; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < bar (j); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = 0; j < baz (&i); j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i += j) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j += i)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = j + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j = j + i)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i = bar (j) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = 0; i < 16; i++)
+    for (j = 0; j < 16; j = j + baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+template <int N>
+void
+f2 (int x)
+{
+  #pragma omp for
+  for (int i = 0; i < 16; i++)
+    ;
+  #pragma omp for
+  for (int i = 0; 16 > i; i++)
+    ;
+  #pragma omp for
+  for (int i = 0; i < 16; i = i + 2)
+    ;
+  #pragma omp for
+  for (int i = 0; i < 16; i = 2 + i)
+    ;
+  #pragma omp for
+  for (int i = i; i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 2 * (i & x); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = bar (i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = baz (&i); i < 16; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 2 * i + 17; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; 2 * i + 17 > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; bar (i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + 2 * i) /* { dg-error "invalid increment expression|increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = i + bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i = baz (&i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += bar (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (int i = 5; i < 16; i += baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = 0; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (int j = i; j < 16; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = i + 2)
+    for (int j = i + 3; j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = baz (&i); j < 16; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 16; j > (i & x); j--)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 0; j < i; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 0; j < i + 4; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (int j = 0; j < baz (&i); j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (int j = 0; j < 16; j += i)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++) /* { dg-error "increment expression refers to iteration variable" } */
+    for (int j = 0; j < 16; j = j + i)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i++)
+    for (int j = 0; j < 16; j = j + baz (&i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+template <int N>
+void
+f3 ()
+{
+  int j = 0;
+  #pragma omp for collapse(2)
+  for (int i = j; i < 16; i = i + 2)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < j + 4; i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < j; i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < bar (j); i++)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i += j)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = j + i)
+    for (int j = 0; j < 16; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 16; i = bar (j) + i)
+    for (int j = 0; j < 16; j++)
+      ;
+}
+
+void
+foo ()
+{
+  f1 <0> (0);
+  f2 <0> (0);
+  f3 <0> ();
+}
--- gcc/testsuite/g++.dg/gomp/loop-3.C.jj	2015-10-19 15:20:12.909189004 +0200
+++ gcc/testsuite/g++.dg/gomp/loop-3.C	2015-10-19 16:19:30.119481730 +0200
@@ -0,0 +1,306 @@
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+
+template <typename T>
+class I
+{
+public:
+  typedef ptrdiff_t difference_type;
+  I ();
+  ~I ();
+  I (T *);
+  I (const I &);
+  T &operator * ();
+  T *operator -> ();
+  T &operator [] (const difference_type &) const;
+  I &operator = (const I &);
+  I &operator ++ ();
+  I operator ++ (int);
+  I &operator -- ();
+  I operator -- (int);
+  I &operator += (const difference_type &);
+  I &operator -= (const difference_type &);
+  I operator + (const difference_type &) const;
+  I operator - (const difference_type &) const;
+  template <typename S> friend bool operator == (I<S> &, I<S> &);
+  template <typename S> friend bool operator == (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator < (I<S> &, I<S> &);
+  template <typename S> friend bool operator < (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator <= (I<S> &, I<S> &);
+  template <typename S> friend bool operator <= (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator > (I<S> &, I<S> &);
+  template <typename S> friend bool operator > (const I<S> &, const I<S> &);
+  template <typename S> friend bool operator >= (I<S> &, I<S> &);
+  template <typename S> friend bool operator >= (const I<S> &, const I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &);
+  template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &);
+  template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &);
+private:
+  T *p;
+};
+
+template <typename T> bool operator == (I<T> &, I<T> &);
+template <typename T> bool operator == (const I<T> &, const I<T> &);
+template <typename T> bool operator != (I<T> &, I<T> &);
+template <typename T> bool operator != (const I<T> &, const I<T> &);
+template <typename T> bool operator < (I<T> &, I<T> &);
+template <typename T> bool operator < (const I<T> &, const I<T> &);
+template <typename T> bool operator <= (I<T> &, I<T> &);
+template <typename T> bool operator <= (const I<T> &, const I<T> &);
+template <typename T> bool operator > (I<T> &, I<T> &);
+template <typename T> bool operator > (const I<T> &, const I<T> &);
+template <typename T> bool operator >= (I<T> &, I<T> &);
+template <typename T> bool operator >= (const I<T> &, const I<T> &);
+template <typename T> typename I<T>::difference_type operator - (I<T> &, I<T> &);
+template <typename T> typename I<T>::difference_type operator - (const I<T> &, const I<T> &);
+template <typename T> I<T> operator + (typename I<T>::difference_type, const I<T> &);
+
+ptrdiff_t foo (I<int> &);
+I<int> &bar (I<int> &);
+I<int> &baz (I<int> *);
+
+void
+f1 (I<int> &x, I<int> &y, I<int> &u, I<int> &v)
+{
+  I<int> i, j;
+  #pragma omp for
+  for (i = x; i < y; i++)
+    ;
+  #pragma omp for
+  for (i = x; y > i; i++)
+    ;
+  #pragma omp for
+  for (i = x; i < y; i = i + 2)
+    ;
+  #pragma omp for
+  for (i = x; i < y; i = 2 + i)
+    ;
+  #pragma omp for
+  for (i = i; i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = i + 3; i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = bar (i); i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = baz (&i); i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; i <= i + 5; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; baz (&i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; i < y; i += foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; i < y; i = i + foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (i = x; i < y; i = foo (i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i = i + 2)
+    for (j = u; j < y; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = j; i < y; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = x; j < y; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (j = i; j < v; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i = i + 2)
+    for (j = i + 3; j < v; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++)
+    for (j = baz (&i); j < v; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = v; j > i; j--)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = x; j < i; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = u; j < i + 4; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < j + 4; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < j; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < bar (j); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (j = u; j < baz (&i); j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i += foo (j)) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++)
+    for (j = u; j < v; j += foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i = foo (j) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++)
+    for (j = u; j < y; j = j + (i - v)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i = foo (j) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    for (j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (i = x; i < y; i++)
+    for (j = u; j < v; j = j + foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+void
+f2 (I<int> &x, I<int> &y, I<int> &u, I<int> &v)
+{
+  #pragma omp for
+  for (I<int> i = x; i < y; i++)
+    ;
+  #pragma omp for
+  for (I<int> i = x; y > i; i++)
+    ;
+  #pragma omp for
+  for (I<int> i = x; i < y; i = i + 2)
+    ;
+  #pragma omp for
+  for (I<int> i = x; i < y; i = 2 + i)
+    ;
+  #pragma omp for
+  for (I<int> i = i; i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = i + 3; i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = bar (i); i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = baz (&i); i < y; i++) /* { dg-error "initializer expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; i <= i + 5; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; i <= baz (&i); i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; baz (&i) > i; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; i <= i; i++) /* { dg-error "invalid controlling predicate|condition expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; i < y; i += foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; i < y; i = i + foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for
+  for (I<int> i = x; i < y; i = foo (i) + i) /* { dg-error "increment expression refers to iteration variable" } */
+    ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i = i + 2)
+    for (I<int> j = u; j < y; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+    for (I<int> j = i; j < v; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i = i + 2)
+    for (I<int> j = i + 3; j < v; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++)
+    for (I<int> j = baz (&i); j < v; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (I<int> j = v; j > i; j--)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (I<int> j = x; j < i; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (I<int> j = u; j < i + 4; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+    for (I<int> j = u; j < baz (&i); j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++)
+    for (I<int> j = u; j < v; j += foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++)
+    for (I<int> j = u; j < y; j = j + (i - v)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i++)
+    for (I<int> j = u; j < v; j = j + foo (i)) /* { dg-error "increment expression refers to iteration variable" } */
+      ;
+}
+
+void
+f3 (I<int> &x, I<int> &y, I<int> &u, I<int> &v)
+{
+  I<int> j;
+  #pragma omp for collapse(2)
+  for (I<int> i = j; i < y; i = i + 2)
+    for (I<int> j = x; j < y; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < j + 4; i++)
+    for (I<int> j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < j; i++)
+    for (I<int> j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < bar (j); i++)
+    for (I<int> j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i += foo (j))
+    for (I<int> j = u; j < v; j++)
+      ;
+  #pragma omp for collapse(2)
+  for (I<int> i = x; i < y; i = foo (j) + i)
+    for (I<int> j = u; j < v; j++)
+      ;
+}

	Jakub



More information about the Gcc-patches mailing list