This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp3] Support for OpenMP 3.0 omp for loops with C++ random access iterators


Hi!

OpenMP 3.0 standard allows to use C++ random access iterators as
#pragma omp for loop iterators, provided that random access to elements
is O(1).  It is just a syntactic sugar, before people had to use
an integral iterator variable and in the body of the loop set
use operator + or operator += to get the current iterator.

I started by parsing the expressions and trying to figure what operators
they actually called, but that turned up to be too ugly.  So with a minor
parser change (new argument to cp_parser_binary_expression) until it is
known that some iterator is integral the condition and increment expressions
are kept in placeholder expressions unfolded, built using build2 etc., so that
finish_omp_for can easily find out what arguments are used and it will take
care of calling build_x_modify_expr etc. on the arguments as needed to
needed the right operations.

The omp-low.c changes are needed, so that if the random access iterator
is privatized, its constructor needs to be invoked before OMP_FOR_PRE_BODY
statements that already use it and similarly when used in lastprivate,
the lastprivate assignment needs to be done before destructing it.

The tree-cfg.c changes were needed because tree-eh.c relies on
TRY_CATCH try { } catch { ~dtor(); } with empty first operand statement list
being optimized out, and remove_useless_stmts pass which does that wasn't
diving into OMP_* containers.

There is one testcase with my own written implementation of a random access
iterator, one to make sure integral iterators especially in templates
haven't been broken, one testcase with std::vector's const_iterator and
one with std::basic_string's iterator.

What I haven't managed to test is if tsubst_expr is called on one OMP_FOR
several times, each time doing some partial replacements.  I know that e.g.
on function decls that's possible to trigger, but haven't been able to
trigger it on function body (even in
template <int N> struct X {
template <typename T> static void foo () { ... }
}; ... X<1>::foo<int> ()
the body is tsubst_expr all template arguments at once).  Any ideas if
that's possible to trigger somehow?  Say default argument with ({ ... })
and #pragma omp for in the statement expression?

Regtested on x86_64-linux, will commit to gomp-3_0-branch on Monday unless
I hear objections.

2008-02-08  Jakub Jelinek  <jakub@redhat.com>

	* omp-low.c (lower_omp_for_lastprivate): Add lastprivate clauses
	to the beginning of dlist rather than end.
	(lower_omp_for): Add rec input clauses before OMP_FOR_PRE_BODY,
	not after it.
	* tree-cfg.c (remove_useless_stmts_1): Handle OMP_* containers.

	* parser.c (cp_parser_binary_expression): Add prec argument.
	(cp_parser_assignment_expression): Adjust caller.
	(cp_parser_omp_for_cond, cp_parser_omp_for_incr): New helper
	functions.
	(cp_parser_omp_for_loop): Add clauses argument.  Parse loops
	with random access iterators.  Set OMP_FOR_CLAUSES here.
	(cp_parser_omp_for, cp_parser_omp_parallel): Adjust caller.
	* semantics.c (finish_omp_for): Handle loops with random access
	iterators.
	* pt.c (tsubst_expr) <case OMP_FOR>: Handle loops with random
	access iterators.

	* g++.dg/gomp/for-16.C (foo): Add a new dg-error.

	* testsuite/libgomp.c++/c++.exp: Add libstdc++-v3 build includes
	to C++ testsuite default compiler options.
	* testsuite/libgomp.c++/for-1.C: New test.
	* testsuite/libgomp.c++/for-2.C: New test.
	* testsuite/libgomp.c++/for-3.C: New test.
	* testsuite/libgomp.c++/for-4.C: New test.

--- gcc/omp-low.c	(revision 132090)
+++ gcc/omp-low.c	(working copy)
@@ -5072,7 +5072,8 @@ lower_omp_for_lastprivate (struct omp_fo
   lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
   if (stmts != NULL)
     {
-      append_to_statement_list (stmts, dlist);
+      append_to_statement_list (*dlist, &stmts);
+      *dlist = stmts;
 
       /* Optimize: v = 0; is usually cheaper than v = some_other_constant.  */
       vinit = fd->loop.n1;
@@ -5117,8 +5118,8 @@ lower_omp_for (tree *stmt_p, omp_context
   /* The pre-body and input clauses go before the lowered OMP_FOR.  */
   ilist = NULL;
   dlist = NULL;
-  append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
   lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
+  append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
 
   /* Lower the header expressions.  At this point, we can assume that
      the header is of the form:
--- gcc/tree-cfg.c	(revision 131902)
+++ gcc/tree-cfg.c	(working copy)
@@ -1925,6 +1925,34 @@ remove_useless_stmts_1 (tree *tp, struct
       data->last_goto = NULL;
       break;
 
+    case OMP_PARALLEL:
+    case OMP_TASK:
+      /* Make sure the outermost BIND_EXPR in OMP_BODY isn't removed
+	 as useless.  */
+      remove_useless_stmts_1 (&BIND_EXPR_BODY (OMP_TASKREG_BODY (*tp)), data);
+      data->last_goto = NULL;
+      break;
+
+    case OMP_SECTIONS:
+    case OMP_SINGLE:
+    case OMP_SECTION:
+    case OMP_MASTER :
+    case OMP_ORDERED:
+    case OMP_CRITICAL:
+      remove_useless_stmts_1 (&OMP_BODY (*tp), data);
+      data->last_goto = NULL;
+      break;
+
+    case OMP_FOR:
+      remove_useless_stmts_1 (&OMP_FOR_BODY (*tp), data);
+      data->last_goto = NULL;
+      if (OMP_FOR_PRE_BODY (*tp))
+	{
+	  remove_useless_stmts_1 (&OMP_FOR_PRE_BODY (*tp), data);
+	  data->last_goto = NULL;
+	}
+      break;
+    
     default:
       data->last_goto = NULL;
       break;
--- gcc/cp/parser.c	(revision 132166)
+++ gcc/cp/parser.c	(working copy)
@@ -1613,7 +1613,7 @@ static tree cp_parser_delete_expression
 static tree cp_parser_cast_expression
   (cp_parser *, bool, bool);
 static tree cp_parser_binary_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, enum cp_parser_prec);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
@@ -5963,14 +5963,15 @@ cp_parser_cast_expression (cp_parser *pa
  : binops_by_token[token->type].prec)
 
 static tree
-cp_parser_binary_expression (cp_parser* parser, bool cast_p)
+cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+			     enum cp_parser_prec prec)
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
   tree lhs, rhs;
   cp_token *token;
   enum tree_code tree_type, lhs_type, rhs_type;
-  enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
+  enum cp_parser_prec new_prec, lookahead_prec;
   bool overloaded_p;
 
   /* Parse the first expression.  */
@@ -6146,7 +6147,7 @@ cp_parser_assignment_expression (cp_pars
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
-      expr = cp_parser_binary_expression (parser, cast_p);
+      expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR);
       /* If the next token is a `?' then we're actually looking at a
 	 conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
@@ -20094,12 +20095,145 @@ cp_parser_omp_flush (cp_parser *parser, 
   finish_omp_flush ();
 }
 
+/* Helper function, to parse omp for increment expression.  */
+
+static tree
+cp_parser_omp_for_cond (cp_parser *parser, tree decl)
+{
+  tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
+  enum tree_code op;
+  cp_token *token;
+
+  if (lhs != decl)
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  token = cp_lexer_peek_token (parser->lexer);
+  op = binops_by_token [token->type].tree_type;
+  switch (op)
+    {
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+      break;
+    default:
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  cp_lexer_consume_token (parser->lexer);
+  rhs = cp_parser_binary_expression (parser, false,
+				     PREC_RELATIONAL_EXPRESSION);
+  if (rhs == error_mark_node
+      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  return build2 (op, boolean_type_node, lhs, rhs);
+}
+
+/* Helper function, to parse omp for increment expression.  */
+
+static tree
+cp_parser_omp_for_incr (cp_parser *parser, tree decl)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  enum tree_code op;
+  tree lhs, rhs;
+  cp_id_kind idk;
+  bool decl_first;
+
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      op = (token->type == CPP_PLUS_PLUS
+	    ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
+      cp_lexer_consume_token (parser->lexer);
+      lhs = cp_parser_cast_expression (parser, false, false);
+      if (lhs != decl)
+	return error_mark_node;
+      return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+    }
+
+  lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+  if (lhs != decl)
+    return error_mark_node;
+
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      op = (token->type == CPP_PLUS_PLUS
+	    ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR);
+      cp_lexer_consume_token (parser->lexer);
+      return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+    }
+
+  op = cp_parser_assignment_operator_opt (parser);
+  if (op == ERROR_MARK)
+    return error_mark_node;
+
+  if (op != NOP_EXPR)
+    {
+      rhs = cp_parser_assignment_expression (parser, false);
+      rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
+      return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+    }
+
+  lhs = cp_parser_binary_expression (parser, false,
+				     PREC_ADDITIVE_EXPRESSION);
+  token = cp_lexer_peek_token (parser->lexer);
+  decl_first = lhs == decl;
+  if (decl_first)
+    lhs = NULL_TREE;
+  if (token->type != CPP_PLUS
+      && token->type != CPP_MINUS)
+    return error_mark_node;
+
+  do
+    {
+      op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
+      cp_lexer_consume_token (parser->lexer);
+      rhs = cp_parser_binary_expression (parser, false,
+					 PREC_ADDITIVE_EXPRESSION);
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
+	{
+	  if (lhs == NULL_TREE)
+	    {
+	      if (op == PLUS_EXPR)
+		lhs = rhs;
+	      else
+		lhs = build_x_unary_op (NEGATE_EXPR, rhs);
+	    }
+	  else
+	    lhs = build_x_binary_op (op, lhs, ERROR_MARK, rhs, ERROR_MARK,
+				     NULL);
+	}
+    }
+  while (token->type == CPP_PLUS || token->type == CPP_MINUS);
+
+  if (!decl_first)
+    {
+      if (rhs != decl || op == MINUS_EXPR)
+	return error_mark_node;
+      rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
+    }
+  else
+    rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs);
+
+  return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+}
+
 /* Parse the restricted form of the for statment allowed by OpenMP.  */
 
 static tree
-cp_parser_omp_for_loop (cp_parser *parser)
+cp_parser_omp_for_loop (cp_parser *parser, tree clauses)
 {
-  tree init, cond, incr, body, decl, pre_body;
+  tree init, cond, incr, body, decl, pre_body, ret, for_block = NULL_TREE;
   location_t loc;
 
   if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
@@ -20136,7 +20270,8 @@ cp_parser_omp_for_loop (cp_parser *parse
 	  attributes = cp_parser_attributes_opt (parser);
 	  asm_specification = cp_parser_asm_specification_opt (parser);
 
-	  cp_parser_require (parser, CPP_EQ, "`='");
+	  if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+	    cp_parser_require (parser, CPP_EQ, "`='");
 	  if (cp_parser_parse_definitely (parser))
 	    {
 	      tree pushed_scope;
@@ -20146,10 +20281,33 @@ cp_parser_omp_for_loop (cp_parser *parse
 				 /*prefix_attributes=*/NULL_TREE,
 				 &pushed_scope);
 
-	      init = cp_parser_assignment_expression (parser, false);
+	      if (CLASS_TYPE_P (TREE_TYPE (decl))
+		  || type_dependent_expression_p (decl))
+		{
+		  bool is_parenthesized_init, is_non_constant_init;
+
+		  init = cp_parser_initializer (parser, &is_parenthesized_init,
+						&is_non_constant_init);
+
+		  cp_finish_decl (decl, init, !is_non_constant_init,
+				  asm_specification, LOOKUP_ONLYCONVERTING);
+		  if (CLASS_TYPE_P (TREE_TYPE (decl)))
+		    {
+		      for_block = pre_body;
+		      init = NULL_TREE;
+		    }
+		  else
+		    init = pop_stmt_list (pre_body);
+		  pre_body = NULL_TREE;
+		}
+	      else
+		{
+		  cp_parser_require (parser, CPP_EQ, "`='");
+		  init = cp_parser_assignment_expression (parser, false);
 
-	      cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false,
-			      asm_specification, LOOKUP_ONLYCONVERTING);
+		  cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false,
+				  asm_specification, LOOKUP_ONLYCONVERTING);
+		}
 
 	      if (pushed_scope)
 		pop_scope (pushed_scope);
@@ -20161,19 +20319,81 @@ cp_parser_omp_for_loop (cp_parser *parse
       /* If parsing as an initialized declaration failed, try again as
 	 a simple expression.  */
       if (decl == NULL)
-	init = cp_parser_expression (parser, false);
+	{
+	  cp_id_kind idk;
+	  cp_parser_parse_tentatively (parser);
+	  decl = cp_parser_primary_expression (parser, false, false,
+					       false, &idk);
+	  if (!cp_parser_error_occurred (parser)
+	      && decl
+	      && DECL_P (decl)
+	      && CLASS_TYPE_P (TREE_TYPE (decl)))
+	    {
+	      tree rhs, c;
+
+	      cp_parser_parse_definitely (parser);
+	      cp_parser_require (parser, CPP_EQ, "`='");
+	      rhs = cp_parser_assignment_expression (parser, false);
+	      finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR, rhs));
+	      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 be firstprivate", decl);
+		  else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+			   && OMP_CLAUSE_DECL (c) == decl)
+		    error ("iteration variable %qD should be reduction", decl);
+		}
+	      if (c == NULL)
+		{
+		  c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+		  OMP_CLAUSE_DECL (c) = decl;
+		  OMP_CLAUSE_CHAIN (c) = clauses;
+		  clauses = c;
+		}
+	    }
+	  else
+	    {
+	      decl = NULL;
+	      cp_parser_abort_tentative_parse (parser);
+	      init = cp_parser_expression (parser, false);
+	    }
+	}
     }
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
-  pre_body = pop_stmt_list (pre_body);
+  if (pre_body)
+    pre_body = pop_stmt_list (pre_body);
 
   cond = NULL;
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    cond = cp_parser_condition (parser);
+    {
+      /* If decl is an iterator, preserve LHS and RHS of the relational
+	 expr until finish_omp_for.  */
+      if (decl
+	  && (type_dependent_expression_p (decl)
+	      || CLASS_TYPE_P (TREE_TYPE (decl))))
+	cond = cp_parser_omp_for_cond (parser, decl);
+      else
+	cond = cp_parser_condition (parser);
+    }
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 
   incr = NULL;
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
-    incr = cp_parser_expression (parser, false);
+    {
+      /* If decl is an iterator, preserve the operator on decl
+	 until finish_omp_for.  */
+      if (decl
+	  && (type_dependent_expression_p (decl)
+	      || CLASS_TYPE_P (TREE_TYPE (decl))))
+	incr = cp_parser_omp_for_incr (parser, decl);
+      else
+	incr = cp_parser_expression (parser, false);
+    }
 
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
@@ -20190,7 +20410,14 @@ cp_parser_omp_for_loop (cp_parser *parse
   cp_parser_statement (parser, NULL_TREE, false, NULL);
   body = pop_stmt_list (body);
 
-  return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
+  ret = finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
+  if (ret)
+    OMP_FOR_CLAUSES (ret) = clauses;
+
+  if (for_block)
+    add_stmt (pop_stmt_list (for_block));
+
+  return ret;
 }
 
 /* OpenMP 2.5:
@@ -20219,9 +20446,7 @@ cp_parser_omp_for (cp_parser *parser, cp
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
-  ret = cp_parser_omp_for_loop (parser);
-  if (ret)
-    OMP_FOR_CLAUSES (ret) = clauses;
+  ret = cp_parser_omp_for_loop (parser, clauses);
 
   cp_parser_end_omp_structured_block (parser, save);
   add_stmt (finish_omp_structured_block (sb));
@@ -20419,9 +20644,7 @@ cp_parser_omp_parallel (cp_parser *parse
 
     case PRAGMA_OMP_PARALLEL_FOR:
       c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      stmt = cp_parser_omp_for_loop (parser);
-      if (stmt)
-	OMP_FOR_CLAUSES (stmt) = ws_clause;
+      cp_parser_omp_for_loop (parser, ws_clause);
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
--- gcc/cp/semantics.c	(revision 132166)
+++ gcc/cp/semantics.c	(working copy)
@@ -3851,7 +3851,7 @@ tree
 finish_omp_for (location_t locus, tree decl, tree init, tree cond,
 		tree incr, tree body, tree pre_body)
 {
-  tree omp_for = NULL;
+  tree omp_for = NULL, orig_incr = incr;
 
   if (decl == NULL)
     {
@@ -3881,9 +3881,15 @@ finish_omp_for (location_t locus, tree d
     }
 
   if (type_dependent_expression_p (decl)
-      || type_dependent_expression_p (init)
+      || (init && type_dependent_expression_p (init))
       || (cond && type_dependent_expression_p (cond))
-      || (incr && type_dependent_expression_p (incr)))
+      || (incr
+	  && ((TREE_CODE (incr) != MODOP_EXPR
+	       && type_dependent_expression_p (incr))
+	      || (TREE_CODE (incr) == MODOP_EXPR
+		  && (type_dependent_expression_p (TREE_OPERAND (incr, 0))
+		      || type_dependent_expression_p (TREE_OPERAND (incr,
+								    2)))))))
     {
       tree stmt;
 
@@ -3926,14 +3932,183 @@ finish_omp_for (location_t locus, tree d
       return NULL;
     }
 
-  if (pre_body == NULL || IS_EMPTY_STMT (pre_body))
-    pre_body = NULL;
-  else if (! processing_template_decl)
+  if (incr && TREE_CODE (incr) == MODOP_EXPR)
     {
-      add_stmt (pre_body);
-      pre_body = NULL;
+      orig_incr = incr;
+      incr = build_modify_expr (TREE_OPERAND (incr, 0),
+				TREE_CODE (TREE_OPERAND (incr, 1)),
+				TREE_OPERAND (incr, 2));
     }
 
+  if (CLASS_TYPE_P (TREE_TYPE (decl)))
+    {
+      tree diff, iter = decl, iter_init, last;
+      tree orig_pre_body, orig_body;
+
+      if (cond == NULL)
+	{
+	  error ("missing controlling predicate");
+	  return NULL;
+	}
+      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);
+	      if (error_operand_p (tem))
+		return NULL;
+	    }
+	  break;
+	default:
+	  cond = error_mark_node;
+	  break;
+	}
+      if (cond == error_mark_node)
+	{
+	  error ("invalid controlling predicate");
+	  return NULL;
+	}
+      diff = build_x_binary_op (MINUS_EXPR, TREE_OPERAND (cond, 1),
+				ERROR_MARK, iter, ERROR_MARK, NULL);
+      if (error_operand_p (diff))
+	return NULL;
+      if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
+	{
+	  error ("difference between %qE and %qD does not have integer type",
+		 TREE_OPERAND (cond, 1), iter);
+	  return NULL;
+	}
+
+      if (incr == NULL)
+	{
+	  error ("missing increment expression");
+	  return NULL;
+	}
+      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;
+	  else if (error_operand_p (build_x_unary_op (TREE_CODE (incr), iter)))
+	    return NULL;
+	  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
+		    {
+		      tree tem = build_x_modify_expr (iter, TREE_CODE (rhs),
+						      TREE_OPERAND (rhs, 1));
+		      if (error_operand_p (tem))
+			return NULL;
+		      if (TREE_CODE (rhs) == MINUS_EXPR)
+			incr = fold_build1 (NEGATE_EXPR, TREE_TYPE (diff),
+					    fold_convert (TREE_TYPE (diff),
+							  TREE_OPERAND (rhs,
+									1)));
+		      else
+			incr = TREE_OPERAND (rhs, 1);
+		    }
+		}
+	      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
+		    {
+		      tree tem
+			= build_x_binary_op (PLUS_EXPR, TREE_OPERAND (rhs, 0),
+					     ERROR_MARK, iter, ERROR_MARK,
+					     NULL);
+		      if (error_operand_p (tem))
+			return NULL;
+		      tem = build_x_modify_expr (iter, NOP_EXPR, tem);
+		      if (error_operand_p (tem))
+			return NULL;
+		      incr = TREE_OPERAND (rhs, 0);
+		    }
+		}
+	      else
+		incr = error_mark_node;
+	    }
+	  else
+	    incr = error_mark_node;
+	  break;
+	default:
+	  incr = error_mark_node;
+	  break;
+	}
+
+      if (incr == error_mark_node)
+	{
+	  error ("invalid increment expression");
+	  return NULL;
+	}
+
+      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);
+      cond = cp_build_binary_op (TREE_CODE (cond), decl, diff);
+      incr = build_modify_expr (decl, PLUS_EXPR,
+				fold_convert (TREE_TYPE (diff), incr));
+      orig_incr = incr;
+
+      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));
+      init = build_int_cst (TREE_TYPE (diff), 0);
+      finish_expr_stmt (build_x_modify_expr (last, NOP_EXPR, init));
+      pre_body = pop_stmt_list (pre_body);
+
+      orig_body = body;
+      body = push_stmt_list ();
+      iter_init = fold_build2 (MINUS_EXPR, TREE_TYPE (diff), decl, last);
+      iter_init = build_x_modify_expr (iter, PLUS_EXPR, iter_init);
+      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));
+      add_stmt (orig_body);
+      body = pop_stmt_list (body);
+    }
+
+  if (IS_EMPTY_STMT (pre_body))
+    pre_body = NULL;
+
   if (!processing_template_decl)
     init = fold_build_cleanup_point_expr (TREE_TYPE (init), init);
   init = build_modify_expr (decl, NOP_EXPR, init);
@@ -3949,17 +4124,24 @@ finish_omp_for (location_t locus, tree d
   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 (TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0)) == MODIFY_EXPR
-      && TREE_SIDE_EFFECTS (TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0), 1))
-      && BINARY_CLASS_P (TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0), 1)))
+      && TREE_CODE (TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0)) == MODIFY_EXPR)
     {
-      tree t = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0), 1);
-      int n = TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)) != 0;
+      tree incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 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 (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 (processing_template_decl)
+	TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0) = orig_incr;
     }
   return omp_for;
 }
--- gcc/cp/pt.c	(revision 132166)
+++ gcc/cp/pt.c	(working copy)
@@ -10528,12 +10528,133 @@ tsubst_expr (tree t, tree args, tsubst_f
 	init = TREE_VEC_ELT (OMP_FOR_INIT (t), 0);
 	gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
 	decl = RECUR (TREE_OPERAND (init, 0));
-	init = RECUR (TREE_OPERAND (init, 1));
-	cond = RECUR (TREE_VEC_ELT (OMP_FOR_COND (t), 0));
-	incr = RECUR (TREE_VEC_ELT (OMP_FOR_INCR (t), 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), 0));
+	    incr = TREE_VEC_ELT (OMP_FOR_INCR (t), 0);
+	    if (TREE_CODE (incr) == MODIFY_EXPR)
+	      incr = build_x_modify_expr (RECUR (TREE_OPERAND (incr, 0)),
+					  NOP_EXPR,
+					  RECUR (TREE_OPERAND (incr, 1)));
+	    else
+	      incr = RECUR (incr);
+	  }
+	else
+	  {
+	    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 be firstprivate",
+			     decl);
+		    else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+			     && OMP_CLAUSE_DECL (c) == decl)
+		      error ("iteration variable %qD should be reduction",
+			     decl);
+		  }
+		if (c == NULL)
+		  {
+		    c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+		    OMP_CLAUSE_DECL (c) = decl;
+		    OMP_CLAUSE_CHAIN (c) = clauses;
+		    clauses = c;
+		  }
+	      }
+	    cond = TREE_VEC_ELT (OMP_FOR_COND (t), 0);
+	    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), 0);
+	    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;
+	      }
+	  }
 
 	stmt = begin_omp_structured_block ();
 
+	if (init && TREE_CODE (init) == DECL_EXPR)
+	  {
+	    if (CLASS_TYPE_P (TREE_TYPE (init)))
+	      {
+		init = RECUR (init);
+		gcc_assert (init == decl);
+		init = NULL_TREE;
+	      }
+	    else
+	      {
+		tree decl_expr = init, orig_init;
+		orig_init = DECL_INITIAL (DECL_EXPR_DECL (decl_expr));
+		gcc_assert (orig_init != NULL);
+		init = RECUR (orig_init);
+		DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = NULL;
+		RECUR (decl_expr);
+		DECL_INITIAL (DECL_EXPR_DECL (decl_expr)) = orig_init;
+	      }
+	  }
+	else
+	  init = RECUR (init);
+
 	pre_body = push_stmt_list ();
 	RECUR (OMP_FOR_PRE_BODY (t));
 	pre_body = pop_stmt_list (pre_body);
--- gcc/testsuite/g++.dg/gomp/for-16.C	(revision 131899)
+++ gcc/testsuite/g++.dg/gomp/for-16.C	(working copy)
@@ -12,8 +12,7 @@ void foo ()
 #pragma omp for
   for (int l = 0; l < 10; ); // { dg-error "missing increment expression" }
 #pragma omp for
-  for (int m = 0; m < 10; m *= 3); // Error here is emitted only during
-				   // instantiation
+  for (int m = 0; m < 10; m *= 3); // { dg-error "invalid increment expression" } 
 #pragma omp for
   for (T n = 0; ; n++); // { dg-error "missing controlling predicate" }
 #pragma omp for
--- libgomp/testsuite/libgomp.c++/c++.exp	(revision 131899)
+++ libgomp/testsuite/libgomp.c++/c++.exp	(working copy)
@@ -31,8 +31,15 @@ if { $lang_test_file_found } {
     set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}"
     set_ld_library_path_env_vars
 
+    set flags_file "${blddir}/../libstdc++-v3/scripts/testsuite_flags"
+    if { [file exists $flags_file] } {
+	set libstdcxx_includes [exec sh $flags_file --build-includes]
+    } else {
+	set libstdcxx_includes ""
+    }
+
     # Main loop.
-    gfortran-dg-runtest $tests ""
+    gfortran-dg-runtest $tests $libstdcxx_includes
 }
 
 # All done.
--- libgomp/testsuite/libgomp.c++/for-1.C	(revision 0)
+++ libgomp/testsuite/libgomp.c++/for-1.C	(revision 0)
@@ -0,0 +1,291 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+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> I<T>::I () : p (0) {}
+template <typename T> I<T>::~I () {}
+template <typename T> I<T>::I (T *x) : p (x) {}
+template <typename T> I<T>::I (const I &x) : p (x.p) {}
+template <typename T> T &I<T>::operator * () { return *p; }
+template <typename T> T *I<T>::operator -> () { return p; }
+template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; }
+template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; }
+template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; }
+template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); }
+template <typename T> I<T> &I<T>::operator -- () { --p; return *this; }
+template <typename T> I<T> I<T>::operator -- (int) { return I (p--); }
+template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; }
+template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; }
+template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); }
+template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); }
+template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; }
+template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); }
+template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); }
+template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; }
+template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; }
+template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; }
+template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; }
+template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; }
+template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; }
+template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; }
+template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); }
+
+template <typename T>
+class J
+{
+public:
+  J(const I<T> &x, const I<T> &y) : b (x), e (y) {}
+  const I<T> &begin ();
+  const I<T> &end ();
+private:
+  I<T> b, e;
+};
+
+template <typename T> const I<T> &J<T>::begin () { return b; }
+template <typename T> const I<T> &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (I<T> &i)
+{
+  if (*i < 0 || *i >= 2000)
+    abort ();
+  results[*i]++;
+}
+
+void
+f1 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (I<int> i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel for private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (I<int> i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const I<int> &x, const I<int> &y)
+{
+  I<int> i;
+#pragma omp parallel for lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (I<int> i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (I<int> i = x + 2000 - 64; i > y + 10; i = i - 12 + 2)
+    {
+      I<int> j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (I<int> i, const I<int> &x, const I<int> &y)
+{
+#pragma omp parallel for
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  I<int> i;
+#pragma omp parallel for
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const I<T> &x, const I<T> &y)
+{
+#pragma omp parallel for
+  for (I<T> i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const I<T> &x, const I<T> &y)
+{
+  I<T> i;
+#pragma omp parallel for
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+  {
+#pragma omp for nowait
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel for
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+#pragma omp parallel for
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  abort ();					\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      abort ()
+
+int
+main ()
+{
+  int a[2000];
+  long b[2000];
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  f1 (&a[10], &a[1990]);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (&a[0], &a[1999]);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (&a[20], &a[1837]);
+  check (i >= 20 && i <= 1837);
+  f4<int> (&a[0], &a[30]);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (&a[0], &a[100]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (&a[10], &a[110]);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (I<int> (), &a[12], &a[1800]);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (&a[14], &a[1803]));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (&a[33], &a[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (&a[1939], &a[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<int> > (&a[16], &a[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<int> > (&a[1761], &a[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<int> > (&a[1], &a[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  f9<long, 7> (&b[33], &b[1967]);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (&b[1939], &b[17]);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<I<long> > (&b[16], &b[1981]);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<I<long> > (&b[1761], &b[37]);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<I<long> > (&b[1], &b[1935]);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+}
--- libgomp/testsuite/libgomp.c++/for-2.C	(revision 0)
+++ libgomp/testsuite/libgomp.c++/for-2.C	(revision 0)
@@ -0,0 +1,182 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+template <typename T>
+class J
+{
+public:
+  J(T x, T y) : b (x), e (y) {}
+  T begin ();
+  T end ();
+private:
+  T b, e;
+};
+
+template <typename T> T J<T>::begin () { return b; }
+template <typename T> T J<T>::end () { return e; }
+
+int results[2000];
+
+void
+baz (int i)
+{
+  if (i < 0 || i >= 2000)
+    abort ();
+  results[i]++;
+}
+
+void
+f1 (int x, int y)
+{
+#pragma omp parallel for
+  for (int i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (int x, int y)
+{
+  int i;
+#pragma omp parallel for private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (int x, int y)
+{
+#pragma omp parallel for
+  for (int i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (int x, int y)
+{
+  int i;
+#pragma omp parallel for lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (int x, int y)
+{
+#pragma omp parallel for
+  for (int i = x + 2000 - 64; i > y + 10L; i -= 10L)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (int x, int y)
+{
+#pragma omp parallel for
+  for (int i = x + 2000 - 64; i > y + 10L; i = i - 12 + 2L)
+    baz (i + N);
+}
+
+template <long N>
+void
+f7 (int i, int x, int y)
+{
+#pragma omp parallel for
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <long N>
+void
+f8 (J<int> j)
+{
+  int i;
+#pragma omp parallel for
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, long N>
+void
+f9 (T x, T y)
+{
+#pragma omp parallel for
+  for (T i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, long N>
+void
+f10 (T x, T y)
+{
+  T i;
+#pragma omp parallel for
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (T x, long y)
+{
+#pragma omp parallel
+  {
+#pragma omp for nowait
+    for (T i = x; i <= y; i += 3L)
+      baz (i);
+#pragma omp single
+    baz (y + 3);
+  }
+}
+
+template <typename T>
+void
+f12 (T x, T y)
+{
+  T i;
+#pragma omp parallel for
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  abort ();					\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      abort ()
+
+int
+main ()
+{
+  f1 (10, 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (0, 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (20, 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (0, 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (0, 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (10, 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (0, 12, 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (14, 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (33, 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (1939, 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<int> (16, 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<int> (1761, 37);
+  check (i > 37 && i <= 1761);
+}
--- libgomp/testsuite/libgomp.c++/for-3.C	(revision 0)
+++ libgomp/testsuite/libgomp.c++/for-3.C	(revision 0)
@@ -0,0 +1,239 @@
+// { dg-do run }
+
+#include <vector>
+#include <cstdlib>
+
+template <typename T>
+class J
+{
+public:
+  typedef typename std::vector<T>::const_iterator const_iterator;
+  J(const const_iterator &x, const const_iterator &y) : b (x), e (y) {}
+  const const_iterator &begin ();
+  const const_iterator &end ();
+private:
+  const_iterator b, e;
+};
+
+template <typename T>
+const typename std::vector<T>::const_iterator &J<T>::begin () { return b; }
+template <typename T>
+const typename std::vector<T>::const_iterator &J<T>::end () { return e; }
+
+int results[2000];
+
+template <typename T>
+void
+baz (T &i)
+{
+  if (*i < 0 || *i >= 2000)
+    std::abort ();
+  results[*i]++;
+}
+
+void
+f1 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel for
+  for (std::vector<int>::const_iterator i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel for private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel for schedule (dynamic, 6)
+  for (std::vector<int>::const_iterator i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel for lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel for schedule (static, 10)
+  for (std::vector<int>::const_iterator i = x + 2000 - 64; i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel for schedule (runtime)
+  for (std::vector<int>::const_iterator i = x + 2000 - 64;
+       i > y + 10; i = i - 12 + 2)
+    {
+      std::vector<int>::const_iterator j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (std::vector<int>::const_iterator i,
+    const std::vector<int>::const_iterator &x,
+    const std::vector<int>::const_iterator &y)
+{
+#pragma omp parallel for schedule (dynamic, 6)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <int N>
+void
+f8 (J<int> j)
+{
+  std::vector<int>::const_iterator i;
+#pragma omp parallel for schedule (dynamic, 40)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const typename std::vector<T>::const_iterator &x,
+    const typename std::vector<T>::const_iterator &y)
+{
+#pragma omp parallel for schedule (static, 25)
+  for (typename std::vector<T>::const_iterator i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const typename std::vector<T>::const_iterator &x,
+     const typename std::vector<T>::const_iterator &y)
+{
+  typename std::vector<T>::const_iterator i;
+#pragma omp parallel for
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+  {
+#pragma omp for nowait schedule (static, 2)
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel for schedule (dynamic, 130)
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+#pragma omp parallel for schedule (runtime)
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  std::abort ();				\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      std::abort ()
+
+int
+main ()
+{
+  std::vector<int> a(2000);
+  std::vector<long> b(2000);
+  for (int i = 0; i < 2000; i++)
+    {
+      a[i] = i;
+      b[i] = i;
+    }
+  f1 (a.begin () + 10, a.begin () + 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (a.begin () + 0, a.begin () + 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (a.begin () + 20, a.begin () + 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (a.begin () + 0, a.begin () + 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (a.begin () + 0, a.begin () + 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (a.begin () + 10, a.begin () + 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (std::vector<int>::const_iterator (), a.begin () + 12,
+	 a.begin () + 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<int> (a.begin () + 14, a.begin () + 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<int, 7> (a.begin () + 33, a.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<int, -7> (a.begin () + 1939, a.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::vector<int>::const_iterator > (a.begin () + 16, a.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::vector<int>::const_iterator > (a.begin () + 1761, a.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::vector<int>::const_iterator > (a.begin () + 1,
+						a.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+  f9<long, 7> (b.begin () + 33, b.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<long, -7> (b.begin () + 1939, b.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::vector<long>::const_iterator > (b.begin () + 16, b.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::vector<long>::const_iterator > (b.begin () + 1761, b.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::vector<long>::const_iterator > (b.begin () + 1,
+						 b.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+}
--- libgomp/testsuite/libgomp.c++/for-4.C	(revision 0)
+++ libgomp/testsuite/libgomp.c++/for-4.C	(revision 0)
@@ -0,0 +1,225 @@
+// { dg-do run }
+
+#include <string>
+#include <cstdlib>
+
+template <typename T>
+class J
+{
+public:
+  typedef typename std::basic_string<T>::iterator iterator;
+  J(const iterator &x, const iterator &y) : b (x), e (y) {}
+  const iterator &begin ();
+  const iterator &end ();
+private:
+  iterator b, e;
+};
+
+template <typename T>
+const typename std::basic_string<T>::iterator &J<T>::begin () { return b; }
+template <typename T>
+const typename std::basic_string<T>::iterator &J<T>::end () { return e; }
+
+template <typename T>
+void
+baz (T &i)
+{
+  if (*i < L'a' || *i >= L'a' + 2000)
+    std::abort ();
+  (*i)++;
+}
+
+void
+f1 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel for
+  for (std::basic_string<wchar_t>::iterator i = x; i <= y; i += 6)
+    baz (i);
+}
+
+void
+f2 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel for private(i)
+  for (i = x; i < y - 1; i = 1 - 6 + 7 + i)
+    baz (i);
+}
+
+template <typename T>
+void
+f3 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel for schedule (dynamic, 6)
+  for (std::basic_string<wchar_t>::iterator i = x; i <= y; i = i + 9 - 8)
+    baz (i);
+}
+
+template <typename T>
+void
+f4 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel for lastprivate(i)
+  for (i = x + 2000 - 64; i > y + 10; --i)
+    baz (i);
+}
+
+void
+f5 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel for schedule (static, 10)
+  for (std::basic_string<wchar_t>::iterator i = x + 2000 - 64;
+       i > y + 10; i -= 10)
+    baz (i);
+}
+
+template <int N>
+void
+f6 (const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel for schedule (runtime)
+  for (std::basic_string<wchar_t>::iterator i = x + 2000 - 64;
+       i > y + 10; i = i - 12 + 2)
+    {
+      std::basic_string<wchar_t>::iterator j = i + N;
+      baz (j);
+    }
+}
+
+template <int N>
+void
+f7 (std::basic_string<wchar_t>::iterator i,
+    const std::basic_string<wchar_t>::iterator &x,
+    const std::basic_string<wchar_t>::iterator &y)
+{
+#pragma omp parallel for schedule (dynamic, 6)
+  for (i = x - 10; i <= y + 10; i += N)
+    baz (i);
+}
+
+template <wchar_t N>
+void
+f8 (J<wchar_t> j)
+{
+  std::basic_string<wchar_t>::iterator i;
+#pragma omp parallel for schedule (dynamic, 40)
+  for (i = j.begin (); i <= j.end () + N; i += 2)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f9 (const typename std::basic_string<T>::iterator &x,
+    const typename std::basic_string<T>::iterator &y)
+{
+#pragma omp parallel for schedule (static, 25)
+  for (typename std::basic_string<T>::iterator i = x; i <= y; i = i + N)
+    baz (i);
+}
+
+template <typename T, int N>
+void
+f10 (const typename std::basic_string<T>::iterator &x,
+     const typename std::basic_string<T>::iterator &y)
+{
+  typename std::basic_string<T>::iterator i;
+#pragma omp parallel for
+  for (i = x; i > y; i = i + N)
+    baz (i);
+}
+
+template <typename T>
+void
+f11 (const T &x, const T &y)
+{
+#pragma omp parallel
+  {
+#pragma omp for nowait schedule (static, 2)
+    for (T i = x; i <= y; i += 3)
+      baz (i);
+#pragma omp single
+    {
+      T j = y + 3;
+      baz (j);
+    }
+  }
+}
+
+template <typename T>
+void
+f12 (const T &x, const T &y)
+{
+  T i;
+#pragma omp parallel for schedule (dynamic, 130)
+  for (i = x; i > y; --i)
+    baz (i);
+}
+
+template <int N>
+struct K
+{
+  template <typename T>
+  static void
+  f13 (const T &x, const T &y)
+  {
+#pragma omp parallel for schedule (runtime)
+    for (T i = x; i <= y + N; i += N)
+      baz (i);
+  }
+};
+
+#define check(expr) \
+  for (int i = 0; i < 2000; i++)			\
+    if (expr)						\
+      {							\
+	if (a[i] != L'a' + i + 1)			\
+	  std::abort ();				\
+	a[i] = L'a' + i;				\
+      }							\
+    else if (a[i] != L'a' + i)				\
+      std::abort ()
+
+int
+main ()
+{
+  std::basic_string<wchar_t> a = L"";
+  for (int i = 0; i < 2000; i++)
+    a += L'a' + i;
+  f1 (a.begin () + 10, a.begin () + 1990);
+  check (i >= 10 && i <= 1990 && (i - 10) % 6 == 0);
+  f2 (a.begin () + 0, a.begin () + 1999);
+  check (i < 1998 && (i & 1) == 0);
+  f3<char> (a.begin () + 20, a.begin () + 1837);
+  check (i >= 20 && i <= 1837);
+  f4<int> (a.begin () + 0, a.begin () + 30);
+  check (i > 40 && i <= 2000 - 64);
+  f5 (a.begin () + 0, a.begin () + 100);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f6<-10> (a.begin () + 10, a.begin () + 110);
+  check (i >= 116 && i <= 2000 - 64 && (i - 116) % 10 == 0);
+  f7<6> (std::basic_string<wchar_t>::iterator (), a.begin () + 12,
+	 a.begin () + 1800);
+  check (i >= 2 && i <= 1808 && (i - 2) % 6 == 0);
+  f8<121> (J<wchar_t> (a.begin () + 14, a.begin () + 1803));
+  check (i >= 14 && i <= 1924 && (i & 1) == 0);
+  f9<wchar_t, 7> (a.begin () + 33, a.begin () + 1967);
+  check (i >= 33 && i <= 1967 && (i - 33) % 7 == 0);
+  f10<wchar_t, -7> (a.begin () + 1939, a.begin () + 17);
+  check (i >= 21 && i <= 1939 && (i - 21) % 7 == 0);
+  f11<std::basic_string<wchar_t>::iterator > (a.begin () + 16,
+					      a.begin () + 1981);
+  check (i >= 16 && i <= 1984 && (i - 16) % 3 == 0);
+  f12<std::basic_string<wchar_t>::iterator > (a.begin () + 1761,
+					      a.begin () + 37);
+  check (i > 37 && i <= 1761);
+  K<5>::f13<std::basic_string<wchar_t>::iterator > (a.begin () + 1,
+						    a.begin () + 1935);
+  check (i >= 1 && i <= 1936 && (i - 1) % 5 == 0);
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]