[gomp4.1] Add support for non-static data member iterators

Jakub Jelinek jakub@redhat.com
Fri Jun 26 13:38:00 GMT 2015


Hi!

As private/lastprivate/linear clauses now allow non-static data members
in C++, it (unfortunately) means that also the iterator variables
of distribute/for/simd/taskloop loops can be non-static data members.

This patch implements it; tested on x86_64-linux, committed to
gomp-4_1-branch.

2015-06-26  Jakub Jelinek  <jakub@redhat.com>

	* gimplify.c (enum omp_region_type): Add ORT_NONE.
	(gimplify_bind_expr, omp_firstprivatize_variable,
	omp_add_variable, omp_notice_variable): Handle ORT_NONE.
	(gimplify_omp_for): For OMP_FOR_PRE_BODY of taskloop,
	temporarily switch on ORT_NONE gimplify_omp_ctxp
	if it is NULL.
gcc/cp/
	* cp-tree.h (push_omp_privatization_clauses): Add bool
	argument.
	(omp_privatize_field): New prototype.
	* parser.c (cp_parser_omp_for_incr): For processing_template_decl
	use cp_tree_equals.
	(cp_parser_omp_for_loop_init): Change return type to tree,
	handle non-static data member iterators, return decl to
	add to private clause if one should be added.
	(cp_parser_omp_for_loop): Adjust caller.  For OMP_SIMD,
	add OMP_CLAUSE_LINEAR or OMP_CLAUSE_LASTPRIVATE instead of
	OMP_CLAUSE_PRIVATE.  Handle NULL TREE_TYPE as non-pointer.
	(cp_parser_pragma): Adjust push_omp_privatization_clauses callers.
	* pt.c (tsubst_omp_clauses): If there is a single OMP_CLAUSE_LINEAR
	with NULL OMP_CLAUSE_LINEAR_STEP, make sure it is NULL even after
	finish_omp_clauses.
	(omp_parallel_combined_clauses): New variable.
	(tsubst_omp_for_iterator): Handle non-static data members,
	for combined parallel for move lastprivate clause from parallel
	to for and avoid making already private iterator private again.
	(tsubst_expr): Adjust push_omp_privatization_clauses callers.
	For OMP_PARALLEL with OMP_PARALLEL_COMBINED temporarily set
	omp_parallel_combined_clauses and clear it in OMP_FOR
	and OMP_SECTIONS.
	(instantiate_decl): Call save_omp_privatization_clauses
	and restore_omp_privatization_clauses if nested.
	(dependent_omp_for_p): Return true even if the iterator
	is non-type dependent SCOPE_REF.
	* semantics.c (omp_private_member_ignore_next): New variable.
	(omp_privatize_field): No longer static.
	(push_omp_privatization_clauses): Add ignore_next argument.
	Set omp_private_member_ignore_next to it, return NULL early
	if omp_private_member_ignore_next was set before.
	(pop_omp_privatization_clauses): Do nothing if stmt is NULL.
	(save_omp_privatization_clauses): Save also
	omp_private_member_ignore_next flag in the vector.
	(restore_omp_privatization_clauses): And restore it.
	(finish_omp_for): For OMP_SIMD, fill in OMP_CLAUSE_LINEAR_STEP
	for the iterator if NULL.
libgomp/
	* testsuite/libgomp.c++/member-1.C: Remove dg-options.
	* testsuite/libgomp.c++/member-2.C: Remove dg-options.
	* testsuite/libgomp.c++/member-3.C: New test.
	* testsuite/libgomp.c++/member-4.C: New test.
	* testsuite/libgomp.c++/member-5.C: New test.

--- gcc/gimplify.c.jj	2015-06-24 12:04:02.000000000 +0200
+++ gcc/gimplify.c	2015-06-25 19:14:25.994242855 +0200
@@ -121,7 +121,10 @@ enum omp_region_type
   /* Data region.  */
   ORT_TARGET_DATA = 16,
   /* Data region with offloading.  */
-  ORT_TARGET = 32
+  ORT_TARGET = 32,
+  /* Dummy OpenMP region, used to disable expansion of
+     DECL_VALUE_EXPRs in taskloop pre body.  */
+  ORT_NONE = 64
 };
 
 /* Gimplify hashtable helper.  */
@@ -1083,7 +1086,7 @@ gimplify_bind_expr (tree *expr_p, gimple
 	  struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
 
 	  /* Mark variable as local.  */
-	  if (ctx && !DECL_EXTERNAL (t)
+	  if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t)
 	      && (! DECL_SEEN_IN_BIND_EXPR_P (t)
 		  || splay_tree_lookup (ctx->variables,
 					(splay_tree_key) t) == NULL))
@@ -5554,7 +5557,7 @@ omp_firstprivatize_variable (struct gimp
 {
   splay_tree_node n;
 
-  if (decl == NULL || !DECL_P (decl))
+  if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
     return;
 
   do
@@ -5646,7 +5649,7 @@ omp_add_variable (struct gimplify_omp_ct
   unsigned int nflags;
   tree t;
 
-  if (error_operand_p (decl))
+  if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
     return;
 
   /* Never elide decls whose type has TREE_ADDRESSABLE set.  This means
@@ -5799,6 +5802,9 @@ omp_notice_variable (struct gimplify_omp
   if (error_operand_p (decl))
     return false;
 
+  if (ctx->region_type == ORT_NONE)
+    return lang_hooks.decls.omp_disregard_value_expr (decl, false);
+
   /* Threadprivate variables are predetermined.  */
   if (is_global_var (decl))
     {
@@ -7195,7 +7201,20 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	    }
 	}
     }
-  gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
+  if (OMP_FOR_PRE_BODY (for_stmt))
+    {
+      if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
+	gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
+      else
+	{
+	  struct gimplify_omp_ctx ctx;
+	  memset (&ctx, 0, sizeof (ctx));
+	  ctx.region_type = ORT_NONE;
+	  gimplify_omp_ctxp = &ctx;
+	  gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
+	  gimplify_omp_ctxp = NULL;
+	}
+    }
   OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
 
   if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
--- gcc/cp/cp-tree.h.jj	2015-06-17 21:21:16.000000000 +0200
+++ gcc/cp/cp-tree.h	2015-06-25 17:31:50.677516397 +0200
@@ -5999,7 +5999,7 @@ extern tree omp_reduction_id			(enum tre
 extern tree cp_remove_omp_priv_cleanup_stmt	(tree *, int *, void *);
 extern void cp_check_omp_declare_reduction	(tree);
 extern tree finish_omp_clauses			(tree, bool);
-extern tree push_omp_privatization_clauses	(void);
+extern tree push_omp_privatization_clauses	(bool);
 extern void pop_omp_privatization_clauses	(tree);
 extern void save_omp_privatization_clauses	(vec<tree> &);
 extern void restore_omp_privatization_clauses	(vec<tree> &);
@@ -6025,6 +6025,7 @@ extern void finish_omp_taskwait			(void)
 extern void finish_omp_taskyield		(void);
 extern void finish_omp_cancel			(tree);
 extern void finish_omp_cancellation_point	(tree);
+extern tree omp_privatize_field			(tree);
 extern tree begin_transaction_stmt		(location_t, tree *, int);
 extern void finish_transaction_stmt		(tree, tree, int, tree);
 extern tree build_transaction_expr		(location_t, tree, int, tree);
--- gcc/cp/parser.c.jj	2015-06-22 14:30:25.000000000 +0200
+++ gcc/cp/parser.c	2015-06-25 17:58:29.649322440 +0200
@@ -30538,13 +30538,15 @@ cp_parser_omp_for_incr (cp_parser *parse
 	    ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
       cp_lexer_consume_token (parser->lexer);
       lhs = cp_parser_simple_cast_expression (parser);
-      if (lhs != decl)
+      if (lhs != decl
+	  && (!processing_template_decl || !cp_tree_equal (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)
+  if (lhs != decl
+      && (!processing_template_decl || !cp_tree_equal (lhs, decl)))
     return error_mark_node;
 
   token = cp_lexer_peek_token (parser->lexer);
@@ -30570,7 +30572,8 @@ cp_parser_omp_for_incr (cp_parser *parse
   lhs = cp_parser_binary_expression (parser, false, false,
 				     PREC_ADDITIVE_EXPRESSION, NULL);
   token = cp_lexer_peek_token (parser->lexer);
-  decl_first = lhs == decl;
+  decl_first = (lhs == decl
+		|| (processing_template_decl && cp_tree_equal (lhs, decl)));
   if (decl_first)
     lhs = NULL_TREE;
   if (token->type != CPP_PLUS
@@ -30603,7 +30606,9 @@ cp_parser_omp_for_incr (cp_parser *parse
 
   if (!decl_first)
     {
-      if (rhs != decl || op == MINUS_EXPR)
+      if ((rhs != decl
+	   && (!processing_template_decl || !cp_tree_equal (rhs, decl)))
+	  || op == MINUS_EXPR)
 	return error_mark_node;
       rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
     }
@@ -30619,7 +30624,7 @@ cp_parser_omp_for_incr (cp_parser *parse
    Return true if the resulting construct should have an
    OMP_CLAUSE_PRIVATE added to it.  */
 
-static bool
+static tree
 cp_parser_omp_for_loop_init (cp_parser *parser,
 			     enum tree_code code,
 			     tree &this_pre_body,
@@ -30629,9 +30634,9 @@ cp_parser_omp_for_loop_init (cp_parser *
 			     tree &real_decl)
 {
   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-    return false;
+    return NULL_TREE;
 
-  bool add_private_clause = false;
+  tree add_private_clause = NULL_TREE;
 
   /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
 
@@ -30762,6 +30767,33 @@ cp_parser_omp_for_loop_init (cp_parser *
       cp_parser_parse_tentatively (parser);
       decl = cp_parser_primary_expression (parser, false, false,
 					   false, &idk);
+      cp_token *last_tok = cp_lexer_peek_token (parser->lexer);
+      if (!cp_parser_error_occurred (parser)
+	  && decl
+	  && (TREE_CODE (decl) == COMPONENT_REF
+	      || (TREE_CODE (decl) == SCOPE_REF && TREE_TYPE (decl))))
+	{
+	  cp_parser_abort_tentative_parse (parser);
+	  cp_parser_parse_tentatively (parser);
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+	  tree name = cp_parser_id_expression (parser, /*template_p=*/false,
+					       /*check_dependency_p=*/true,
+					       /*template_p=*/NULL,
+					       /*declarator_p=*/false,
+					       /*optional_p=*/false);
+	  if (name != error_mark_node
+	      && last_tok == cp_lexer_peek_token (parser->lexer))
+	    {
+	      decl = cp_parser_lookup_name_simple (parser, name,
+						   token->location);
+	      if (TREE_CODE (decl) == FIELD_DECL)
+		add_private_clause = omp_privatize_field (decl);
+	    }
+	  cp_parser_abort_tentative_parse (parser);
+	  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)
@@ -30776,7 +30808,8 @@ cp_parser_omp_for_loop_init (cp_parser *
 						 decl, NOP_EXPR,
 						 rhs,
 						 tf_warning_or_error));
-	  add_private_clause = true;
+	  if (!add_private_clause)
+	    add_private_clause = decl;
 	}
       else
 	{
@@ -30824,7 +30857,7 @@ cp_parser_omp_for_loop (cp_parser *parse
   for (i = 0; i < collapse; i++)
     {
       int bracecount = 0;
-      bool add_private_clause = false;
+      tree add_private_clause = NULL_TREE;
       location_t loc;
 
       if (code != CILK_FOR
@@ -30848,9 +30881,9 @@ cp_parser_omp_for_loop (cp_parser *parse
       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);
+	= cp_parser_omp_for_loop_init (parser, code,
+				       this_pre_body, for_block,
+				       init, decl, real_decl);
 
       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       if (this_pre_body)
@@ -30899,13 +30932,13 @@ cp_parser_omp_for_loop (cp_parser *parse
 		    OMP_CLAUSE_CHAIN (l) = clauses;
 		    clauses = l;
 		  }
-		add_private_clause = false;
+		add_private_clause = NULL_TREE;
 	      }
 	    else
 	      {
 		if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE
 		    && OMP_CLAUSE_DECL (*c) == real_decl)
-		  add_private_clause = false;
+		  add_private_clause = NULL_TREE;
 		c = &OMP_CLAUSE_CHAIN (*c);
 	      }
 	}
@@ -30931,13 +30964,22 @@ cp_parser_omp_for_loop (cp_parser *parse
 	    }
 	  if (c == NULL)
 	    {
-	      c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
-	      OMP_CLAUSE_DECL (c) = decl;
-	      c = finish_omp_clauses (c, false);
+	      if (code != OMP_SIMD)
+		c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
+	      else if (collapse == 1)
+		c = build_omp_clause (loc, OMP_CLAUSE_LINEAR);
+	      else
+		c = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
+	      OMP_CLAUSE_DECL (c) = add_private_clause;
+	      c = finish_omp_clauses (c, true);
 	      if (c)
 		{
 		  OMP_CLAUSE_CHAIN (c) = clauses;
 		  clauses = c;
+		  /* For linear, signal that we need to fill up
+		     the so far unknown linear step.  */
+		  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
+		    OMP_CLAUSE_LINEAR_STEP (c) = NULL_TREE;
 		}
 	    }
 	}
@@ -30954,7 +30996,8 @@ cp_parser_omp_for_loop (cp_parser *parse
 	     until finish_omp_for.  */
 	  if (real_decl
 	      && ((processing_template_decl
-		   && !POINTER_TYPE_P (TREE_TYPE (real_decl)))
+		   && (TREE_TYPE (real_decl) == NULL_TREE
+		       || !POINTER_TYPE_P (TREE_TYPE (real_decl))))
 		  || CLASS_TYPE_P (TREE_TYPE (real_decl))))
 	    incr = cp_parser_omp_for_incr (parser, real_decl);
 	  else
@@ -33876,19 +33919,19 @@ cp_parser_pragma (cp_parser *parser, enu
     case PRAGMA_OMP_TEAMS:
       if (context != pragma_stmt && context != pragma_compound)
 	goto bad_stmt;
-      stmt = push_omp_privatization_clauses ();
+      stmt = push_omp_privatization_clauses (false);
       cp_parser_omp_construct (parser, pragma_tok);
       pop_omp_privatization_clauses (stmt);
       return true;
 
     case PRAGMA_OMP_ORDERED:
-      stmt = push_omp_privatization_clauses ();
+      stmt = push_omp_privatization_clauses (false);
       ret = cp_parser_omp_ordered (parser, pragma_tok, context);
       pop_omp_privatization_clauses (stmt);
       return ret;
 
     case PRAGMA_OMP_TARGET:
-      stmt = push_omp_privatization_clauses ();
+      stmt = push_omp_privatization_clauses (false);
       ret = cp_parser_omp_target (parser, pragma_tok, context);
       pop_omp_privatization_clauses (stmt);
       return ret;
@@ -33932,7 +33975,7 @@ cp_parser_pragma (cp_parser *parser, enu
 		    "%<#pragma simd%> must be inside a function");
 	  break;
 	}
-      stmt = push_omp_privatization_clauses ();
+      stmt = push_omp_privatization_clauses (false);
       cp_parser_cilk_simd (parser, pragma_tok);
       pop_omp_privatization_clauses (stmt);
       return true;
--- gcc/cp/pt.c.jj	2015-06-18 10:57:22.000000000 +0200
+++ gcc/cp/pt.c	2015-06-26 13:07:29.931105279 +0200
@@ -13528,7 +13528,8 @@ static tree
 tsubst_omp_clauses (tree clauses, bool declare_simd, bool allow_fields,
 		    tree args, tsubst_flags_t complain, tree in_decl)
 {
-  tree new_clauses = NULL, nc, oc;
+  tree new_clauses = NULL_TREE, nc, oc;
+  tree linear_no_step = NULL_TREE;
 
   for (oc = clauses; oc ; oc = OMP_CLAUSE_CHAIN (oc))
     {
@@ -13609,6 +13610,12 @@ tsubst_omp_clauses (tree clauses, bool d
 	  OMP_CLAUSE_OPERAND (nc, 1)
 	    = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
 			   in_decl, /*integral_constant_expression_p=*/false);
+	  if (OMP_CLAUSE_CODE (oc) == OMP_CLAUSE_LINEAR
+	      && OMP_CLAUSE_LINEAR_STEP (oc) == NULL_TREE)
+	    {
+	      gcc_assert (!linear_no_step);
+	      linear_no_step = nc;
+	    }
 	  break;
 	case OMP_CLAUSE_NOWAIT:
 	case OMP_CLAUSE_DEFAULT:
@@ -13688,7 +13695,16 @@ tsubst_omp_clauses (tree clauses, bool d
 
   new_clauses = nreverse (new_clauses);
   if (!declare_simd)
-    new_clauses = finish_omp_clauses (new_clauses, allow_fields);
+    {
+      new_clauses = finish_omp_clauses (new_clauses, allow_fields);
+      if (linear_no_step)
+	for (nc = new_clauses; nc; nc = OMP_CLAUSE_CHAIN (nc))
+	  if (nc == linear_no_step)
+	    {
+	      OMP_CLAUSE_LINEAR_STEP (nc) = NULL_TREE;
+	      break;
+	    }
+    }
   return new_clauses;
 }
 
@@ -13735,6 +13751,12 @@ tsubst_copy_asm_operands (tree t, tree a
 #undef RECUR
 }
 
+/* Used to temporarily communicate the list of #pragma omp parallel
+   clauses to #pragma omp for instantiation if they are combined
+   together.  */
+
+static tree *omp_parallel_combined_clauses;
+
 /* Substitute one OMP_FOR iterator.  */
 
 static void
@@ -13763,7 +13785,41 @@ tsubst_omp_for_iterator (tree t, int i,
       decl = tsubst_decl (decl, args, complain);
     }
   else
-    decl = RECUR (decl);
+    {
+      if (TREE_CODE (decl) == SCOPE_REF)
+	{
+	  decl = RECUR (decl);
+	  if (TREE_CODE (decl) == COMPONENT_REF)
+	    {
+	      tree v = decl;
+	      while (v)
+		switch (TREE_CODE (v))
+		  {
+		  case COMPONENT_REF:
+		  case MEM_REF:
+		  case INDIRECT_REF:
+		  CASE_CONVERT:
+		  case POINTER_PLUS_EXPR:
+		    v = TREE_OPERAND (v, 0);
+		    continue;
+		  case PARM_DECL:
+		    if (DECL_CONTEXT (v) == current_function_decl
+			&& DECL_ARTIFICIAL (v)
+			&& DECL_NAME (v) == this_identifier)
+		      {
+			decl = TREE_OPERAND (decl, 1);
+			decl = omp_privatize_field (decl);
+		      }
+		    /* FALLTHRU */
+		  default:
+		    v = NULL_TREE;
+		    break;
+		  }
+	    }
+	}
+      else
+	decl = RECUR (decl);
+    }
   init = RECUR (init);
 
   tree auto_node = type_uses_auto (TREE_TYPE (decl));
@@ -13810,25 +13866,51 @@ tsubst_omp_for_iterator (tree t, int i,
     }
   else if (init)
     {
-      tree c;
-      for (c = *clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+      tree *pc;
+      int j;
+      for (j = (omp_parallel_combined_clauses == NULL ? 1 : 0); j < 2; j++)
 	{
-	  if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
-	       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
-	      && OMP_CLAUSE_DECL (c) == decl)
+	  for (pc = j ? clauses : omp_parallel_combined_clauses; *pc; )
+	    {
+	      if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
+		  && OMP_CLAUSE_DECL (*pc) == decl)
+		break;
+	      else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE
+		       && OMP_CLAUSE_DECL (*pc) == decl)
+		{
+		  if (j)
+		    break;
+		  /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES.  */
+		  tree c = *pc;
+		  *pc = OMP_CLAUSE_CHAIN (c);
+		  OMP_CLAUSE_CHAIN (c) = *clauses;
+		  *clauses = c;
+		}
+	      else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_FIRSTPRIVATE
+		       && OMP_CLAUSE_DECL (*pc) == decl)
+		{
+		  error ("iteration variable %qD should not be firstprivate",
+			 decl);
+		  *pc = OMP_CLAUSE_CHAIN (*pc);
+		}
+	      else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_REDUCTION
+		       && OMP_CLAUSE_DECL (*pc) == decl)
+		{
+		  error ("iteration variable %qD should not be reduction",
+			 decl);
+		  *pc = OMP_CLAUSE_CHAIN (*pc);
+		}
+	      else
+		pc = &OMP_CLAUSE_CHAIN (*pc);
+	    }
+	  if (*pc)
 	    break;
-	  else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
-		   && OMP_CLAUSE_DECL (c) == decl)
-	    error ("iteration variable %qD should not be firstprivate", decl);
-	  else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
-		   && OMP_CLAUSE_DECL (c) == decl)
-	    error ("iteration variable %qD should not be reduction", decl);
 	}
-      if (c == NULL)
+      if (*pc == NULL_TREE)
 	{
-	  c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
+	  tree c = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
 	  OMP_CLAUSE_DECL (c) = decl;
-	  c = finish_omp_clauses (c, false);
+	  c = finish_omp_clauses (c, true);
 	  if (c)
 	    {
 	      OMP_CLAUSE_CHAIN (c) = *clauses;
@@ -14289,18 +14371,21 @@ tsubst_expr (tree t, tree args, tsubst_f
       break;
 
     case OMP_PARALLEL:
-      r = push_omp_privatization_clauses ();
+      r = push_omp_privatization_clauses (OMP_PARALLEL_COMBINED (t));
       tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), false, true,
 				args, complain, in_decl);
+      if (OMP_PARALLEL_COMBINED (t))
+	omp_parallel_combined_clauses = &tmp;
       stmt = begin_omp_parallel ();
       RECUR (OMP_PARALLEL_BODY (t));
+      gcc_assert (omp_parallel_combined_clauses == NULL);
       OMP_PARALLEL_COMBINED (finish_omp_parallel (tmp, stmt))
 	= OMP_PARALLEL_COMBINED (t);
       pop_omp_privatization_clauses (r);
       break;
 
     case OMP_TASK:
-      r = push_omp_privatization_clauses ();
+      r = push_omp_privatization_clauses (false);
       tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), false, true,
 				args, complain, in_decl);
       stmt = begin_omp_task ();
@@ -14321,7 +14406,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 	tree incrv = NULL_TREE;
 	int i;
 
-	r = push_omp_privatization_clauses ();
+	r = push_omp_privatization_clauses (OMP_FOR_INIT (t) == NULL_TREE);
 	clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false, true,
 				      args, complain, in_decl);
 	if (OMP_FOR_INIT (t) != NULL_TREE)
@@ -14343,6 +14428,7 @@ tsubst_expr (tree t, tree args, tsubst_f
 	    tsubst_omp_for_iterator (t, i, declv, initv, condv, incrv,
 				     &clauses, args, complain, in_decl,
 				     integral_constant_expression_p);
+	omp_parallel_combined_clauses = NULL;
 
 	body = push_stmt_list ();
 	RECUR (OMP_FOR_BODY (t));
@@ -14368,10 +14454,13 @@ tsubst_expr (tree t, tree args, tsubst_f
       break;
 
     case OMP_SECTIONS:
+      omp_parallel_combined_clauses = NULL;
+      /* FALLTHRU */
     case OMP_SINGLE:
     case OMP_TEAMS:
     case OMP_CRITICAL:
-      r = push_omp_privatization_clauses ();
+      r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS
+					  && OMP_TEAMS_COMBINED (t));
       tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, true,
 				args, complain, in_decl);
       stmt = push_stmt_list ();
@@ -20270,7 +20359,7 @@ instantiate_decl (tree d, int defer_ok,
   bool external_p;
   bool deleted_p;
   tree fn_context;
-  bool nested;
+  bool nested = false;
 
   /* This function should only be used to instantiate templates for
      functions and static member variables.  */
@@ -20492,6 +20581,10 @@ instantiate_decl (tree d, int defer_ok,
 
   fn_context = decl_function_context (d);
   nested = (current_function_decl != NULL_TREE);
+  vec<tree> omp_privatization_save;
+  if (nested)
+    save_omp_privatization_clauses (omp_privatization_save);
+
   if (!fn_context)
     push_to_top_level ();
   else
@@ -20661,6 +20754,8 @@ out:
   c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
   pop_deferring_access_checks ();
   pop_tinst_level ();
+  if (nested)
+    restore_omp_privatization_clauses (omp_privatization_save);
 
   timevar_pop (TV_TEMPLATE_INST);
 
@@ -21999,7 +22094,8 @@ dependent_omp_for_p (tree declv, tree in
       tree cond = TREE_VEC_ELT (condv, i);
       tree incr = TREE_VEC_ELT (incrv, i);
 
-      if (type_dependent_expression_p (decl))
+      if (type_dependent_expression_p (decl)
+	  || TREE_CODE (decl) == SCOPE_REF)
 	return true;
 
       if (init && type_dependent_expression_p (init))
--- gcc/cp/semantics.c.jj	2015-06-23 16:24:16.000000000 +0200
+++ gcc/cp/semantics.c	2015-06-25 17:28:25.399646095 +0200
@@ -70,6 +70,7 @@ static tree capture_decltype (tree);
 
 static hash_map<tree, tree> *omp_private_member_map;
 static vec<tree> omp_private_member_vec;
+static bool omp_private_member_ignore_next;
 
 
 /* Deferred Access Checking Overview
@@ -4324,7 +4325,7 @@ omp_note_field_privatization (tree f, tr
 /* Privatize FIELD_DECL T, return corresponding DECL_OMP_PRIVATIZED_MEMBER
    dummy VAR_DECL.  */
 
-static tree
+tree
 omp_privatize_field (tree t)
 {
   tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
@@ -6517,8 +6518,14 @@ finish_omp_clauses (tree clauses, bool a
    privatization clauses for non-static data members.  */
 
 tree
-push_omp_privatization_clauses (void)
+push_omp_privatization_clauses (bool ignore_next)
 {
+  if (omp_private_member_ignore_next)
+    {
+      omp_private_member_ignore_next = ignore_next;
+      return NULL_TREE;
+    }
+  omp_private_member_ignore_next = ignore_next;
   if (omp_private_member_map)
     omp_private_member_vec.safe_push (error_mark_node);
   return push_stmt_list ();
@@ -6530,6 +6537,8 @@ push_omp_privatization_clauses (void)
 void
 pop_omp_privatization_clauses (tree stmt)
 {
+  if (stmt == NULL_TREE)
+    return;
   stmt = pop_stmt_list (stmt);
   if (omp_private_member_map)
     {
@@ -6563,8 +6572,12 @@ void
 save_omp_privatization_clauses (vec<tree> &save)
 {
   save = vNULL;
+  if (omp_private_member_ignore_next)
+    save.safe_push (integer_one_node);
+  omp_private_member_ignore_next = false;
   if (!omp_private_member_map)
     return;
+
   while (!omp_private_member_vec.is_empty ())
     {
       tree t = omp_private_member_vec.pop ();
@@ -6594,8 +6607,16 @@ void
 restore_omp_privatization_clauses (vec<tree> &save)
 {
   gcc_assert (omp_private_member_vec.is_empty ());
+  omp_private_member_ignore_next = false;
   if (save.is_empty ())
     return;
+  if (save.length () == 1 && save[0] == integer_one_node)
+    {
+      omp_private_member_ignore_next = true;
+      save.release ();
+      return;
+    }
+    
   omp_private_member_map = new hash_map <tree, tree>;
   while (!save.is_empty ())
     {
@@ -6603,6 +6624,12 @@ restore_omp_privatization_clauses (vec<t
       tree n = t;
       if (t != error_mark_node)
 	{
+	  if (t == integer_one_node)
+	    {
+	      omp_private_member_ignore_next = true;
+	      gcc_assert (save.is_empty ());
+	      break;
+	    }
 	  if (t == integer_zero_node)
 	    t = save.pop ();
 	  tree &v = omp_private_member_map->get_or_insert (t);
@@ -7323,6 +7350,68 @@ finish_omp_for (location_t locus, enum t
     }
   OMP_FOR_CLAUSES (omp_for) = clauses;
 
+  /* For simd loops with non-static data member iterators, we could have added
+     OMP_CLAUSE_LINEAR clauses without OMP_CLAUSE_LINEAR_STEP.  As we know the
+     step at this point, fill it in.  */
+  if (code == OMP_SIMD && !processing_template_decl
+      && TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)) == 1)
+    for (tree c = find_omp_clause (clauses, OMP_CLAUSE_LINEAR); c;
+	 c = find_omp_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_LINEAR))
+      if (OMP_CLAUSE_LINEAR_STEP (c) == NULL_TREE)
+	{
+	  decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0), 0);
+	  gcc_assert (decl == OMP_CLAUSE_DECL (c));
+	  incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0);
+	  tree step, stept;
+	  switch (TREE_CODE (incr))
+	    {
+	    case PREINCREMENT_EXPR:
+	    case POSTINCREMENT_EXPR:
+	      /* c_omp_for_incr_canonicalize_ptr() should have been
+		 called to massage things appropriately.  */
+	      gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+	      OMP_CLAUSE_LINEAR_STEP (c) = build_int_cst (TREE_TYPE (decl), 1);
+	      break;
+	    case PREDECREMENT_EXPR:
+	    case POSTDECREMENT_EXPR:
+	      /* c_omp_for_incr_canonicalize_ptr() should have been
+		 called to massage things appropriately.  */
+	      gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
+	      OMP_CLAUSE_LINEAR_STEP (c)
+		= build_int_cst (TREE_TYPE (decl), -1);
+	      break;
+	    case MODIFY_EXPR:
+	      gcc_assert (TREE_OPERAND (incr, 0) == decl);
+	      incr = TREE_OPERAND (incr, 1);
+	      switch (TREE_CODE (incr))
+		{
+		case PLUS_EXPR:
+		  if (TREE_OPERAND (incr, 1) == decl)
+		    step = TREE_OPERAND (incr, 0);
+		  else
+		    step = TREE_OPERAND (incr, 1);
+		  break;
+		case MINUS_EXPR:
+		case POINTER_PLUS_EXPR:
+		  gcc_assert (TREE_OPERAND (incr, 0) == decl);
+		  step = TREE_OPERAND (incr, 1);
+		  break;
+		default:
+		  gcc_unreachable ();
+		}
+	      stept = TREE_TYPE (decl);
+	      if (POINTER_TYPE_P (stept))
+		stept = sizetype;
+	      step = fold_convert (stept, step);
+	      if (TREE_CODE (incr) == MINUS_EXPR)
+		step = fold_build1 (NEGATE_EXPR, stept, step);
+	      OMP_CLAUSE_LINEAR_STEP (c) = step;
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
+	}
+
   if (block)
     {
       tree omp_par = make_node (OMP_PARALLEL);
--- libgomp/testsuite/libgomp.c++/member-1.C.jj	2015-06-03 09:45:48.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/member-1.C	2015-06-25 11:17:21.588886636 +0200
@@ -1,5 +1,4 @@
 // { dg-do run }
-// { dg-options "-O2 -fopenmp" }
 
 #include <omp.h>
 
--- libgomp/testsuite/libgomp.c++/member-2.C.jj	2015-06-03 09:46:46.000000000 +0200
+++ libgomp/testsuite/libgomp.c++/member-2.C	2015-06-25 11:17:29.656761918 +0200
@@ -1,5 +1,4 @@
 // { dg-do run }
-// { dg-options "-O2 -fopenmp" }
 
 #include <omp.h>
 
--- libgomp/testsuite/libgomp.c++/member-3.C.jj	2015-06-25 11:17:07.708101213 +0200
+++ libgomp/testsuite/libgomp.c++/member-3.C	2015-06-25 18:17:15.924234255 +0200
@@ -0,0 +1,105 @@
+// { dg-do run }
+
+struct R { R () {}; ~R () {}; int r; };
+struct T { T () {}; virtual ~T () {}; int t; };
+int c;
+struct A : public R, virtual public T { A () : b(c) {} int a; int &b; void m1 (); };
+int d[64];
+
+void
+A::m1 ()
+{
+  r = 0;
+  #pragma omp parallel for private (a) reduction(|:R::r)
+  for (a = 0; A::a < 31; a += 2)
+    r |= (1 << A::a);
+  if (r != 0x55555555)
+    __builtin_abort ();
+  #pragma omp parallel for simd linear (R::r)
+  for (R::r = 0; r < 32; R::r++)
+    d[r + 8] |= 1;
+  for (int i = 0; i < 64; i++)
+    if (d[i] != ((i >= 8 && i < 32 + 8) ? 1 : 0))
+      __builtin_abort ();
+  #pragma omp parallel for lastprivate (t)
+  for (T::t = 0; t < 32; t += 3)
+    d[T::t + 2] |= 2;
+  if (T::t != 33)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)))
+      __builtin_abort ();
+  #pragma omp simd linear (t)
+  for (t = 0; t < 32; t++)
+    d[T::t + 9] |= 4;
+  if (t != 32)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)))
+      __builtin_abort ();
+  r = 0;
+  #pragma omp parallel for reduction(|:r)
+  for (a = 0; A::a < 31; a += 2)
+    r |= (1 << A::a);
+  if (r != 0x55555555)
+    __builtin_abort ();
+  #pragma omp parallel for simd
+  for (R::r = 0; r < 32; R::r += 2)
+    d[r + 8] |= 8;
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)))
+      __builtin_abort ();
+  #pragma omp simd collapse(2)
+  for (T::t = 0; t < 7; t += 2)
+    for (a = 0; A::a < 8; a++)
+      d[((t << 2) | a) + 3] |= 16;
+  if (t != 8 || A::a != 8)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? 16 : 0)))
+      __builtin_abort ();
+  T::t = 32;
+  a = 16;
+  #pragma omp parallel
+  #pragma omp single
+  #pragma omp taskloop simd collapse(2)
+  for (t = 0; T::t < 7; T::t += 2)
+    for (A::a = 0; a < 8; A::a++)
+      d[((t << 2) | A::a) + 3] |= 32;
+  if (T::t != 8 || a != 8)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0)))
+      __builtin_abort ();
+  #pragma omp parallel
+  #pragma omp single
+  #pragma omp taskloop simd
+  for (R::r = 0; r < 31; R::r += 2)
+    d[r + 8] |= 64;
+  if (r != 32)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (64 | 8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0)))
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  A a;
+  a.m1 ();
+}
--- libgomp/testsuite/libgomp.c++/member-4.C.jj	2015-06-25 17:54:13.264212461 +0200
+++ libgomp/testsuite/libgomp.c++/member-4.C	2015-06-25 18:17:28.981036156 +0200
@@ -0,0 +1,108 @@
+// { dg-do run }
+
+int c, d, e;
+struct R { R () {}; ~R () {}; int r; };
+template <typename Q>
+struct T { T () : t(d) {}; virtual ~T () {}; Q t; };
+template <typename Q>
+struct A : public R, virtual public T<Q> { A () : b(c), a(e) {} Q a; int &b; void m1 (); };
+int f[64];
+
+template <typename Q>
+void
+A<Q>::m1 ()
+{
+  r = 0;
+  #pragma omp parallel for private (a) reduction(|:R::r)
+  for (a = 0; A::a < 31; a += 2)
+    r |= (1 << A::a);
+  if (r != 0x55555555)
+    __builtin_abort ();
+  #pragma omp parallel for simd linear (R::r)
+  for (R::r = 0; r < 32; R::r++)
+    f[r + 8] |= 1;
+  for (int i = 0; i < 64; i++)
+    if (f[i] != ((i >= 8 && i < 32 + 8) ? 1 : 0))
+      __builtin_abort ();
+  #pragma omp parallel for lastprivate (T<Q>::t)
+  for (T<Q>::t = 0; T<Q>::t < 32; T<Q>::t += 3)
+    f[T<Q>::t + 2] |= 2;
+  if (T<Q>::t != 33)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (f[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)))
+      __builtin_abort ();
+  #pragma omp simd linear (T<Q>::t)
+  for (T<Q>::t = 0; T<Q>::t < 32; T<Q>::t++)
+    f[T<Q>::t + 9] |= 4;
+  if (T<Q>::t != 32)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (f[i] != (((i >= 8 && i < 32 + 8) ? 1 : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)))
+      __builtin_abort ();
+  r = 0;
+  #pragma omp parallel for reduction(|:r)
+  for (a = 0; A::a < 31; a += 2)
+    r |= (1 << A::a);
+  if (r != 0x55555555)
+    __builtin_abort ();
+  #pragma omp parallel for simd
+  for (R::r = 0; r < 32; R::r += 2)
+    f[r + 8] |= 8;
+  for (int i = 0; i < 64; i++)
+    if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)))
+      __builtin_abort ();
+  #pragma omp simd collapse(2)
+  for (T<Q>::t = 0; T<Q>::t < 7; T<Q>::t += 2)
+    for (a = 0; A::a < 8; a++)
+      f[((T<Q>::t << 2) | a) + 3] |= 16;
+  if (T<Q>::t != 8 || A::a != 8)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? 16 : 0)))
+      __builtin_abort ();
+  T<Q>::t = 32;
+  a = 16;
+  #pragma omp parallel
+  #pragma omp single
+  #pragma omp taskloop simd collapse(2)
+  for (T<Q>::t = 0; T<Q>::t < 7; T<Q>::t += 2)
+    for (A::a = 0; a < 8; A::a++)
+      f[((T<Q>::t << 2) | A::a) + 3] |= 32;
+  if (T<Q>::t != 8 || a != 8)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0)))
+      __builtin_abort ();
+  #pragma omp parallel
+  #pragma omp single
+  #pragma omp taskloop simd
+  for (R::r = 0; r < 31; R::r += 2)
+    f[r + 8] |= 64;
+  if (r != 32)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (f[i] != (((i >= 8 && i < 32 + 8) ? ((i & 1) ? 1 : (64 | 8 | 1)) : 0)
+		 | ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 2 : 0)
+		 | ((i >= 9 && i < 32 + 9) ? 4 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? (16 | 32) : 0)))
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  A<int> a;
+  a.m1 ();
+}
--- libgomp/testsuite/libgomp.c++/member-5.C.jj	2015-06-26 12:41:13.018061723 +0200
+++ libgomp/testsuite/libgomp.c++/member-5.C	2015-06-26 10:18:10.000000000 +0200
@@ -0,0 +1,183 @@
+// { dg-do run }
+
+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> 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); }
+
+struct R { R () {}; ~R () {}; I<int> r; };
+struct T { T () {}; virtual ~T () {}; I<int> t; };
+struct A : public R, virtual public T { A () {} I<int> a; void m1 (const I<int> &, const I<int> &); };
+template <typename Q>
+struct U { U () {}; virtual ~U () {}; Q t; };
+template <typename Q>
+struct B : public R, virtual public U<Q> { B () {} Q a; void m2 (const Q &, const Q &, const I<int> &, const I<int> &); };
+
+int d[64];
+
+void
+A::m1 (const I<int> &x, const I<int> &y)
+{
+  int w = 0;
+  #pragma omp parallel for private (a) reduction(|:w)
+  for (a = x; A::a < y - 33; a += 2)
+    w |= (1 << *A::a);
+  if (w != 0x55555555)
+    __builtin_abort ();
+  #pragma omp parallel for lastprivate (t)
+  for (T::t = x; t < y - 32; t += 3)
+    d[*T::t + 2] |= 1;
+  if (*T::t != 33)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0))
+      __builtin_abort ();
+  w = 0;
+  #pragma omp parallel for reduction(|:w)
+  for (a = x; A::a < y - 33; a += 2)
+    w |= (1 << *A::a);
+  if (w != 0x55555555)
+    __builtin_abort ();
+  #pragma omp taskloop
+  for (R::r = x; r < y - 32; R::r += 2)
+    d[*r + 8] |= 2;
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0)
+		 | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0)))
+      __builtin_abort ();
+  #pragma omp taskloop collapse(2)
+  for (T::t = x; t < y - 57; t += 2)
+    for (a = x; A::a < y - 56; a++)
+      d[((*t << 2) | *a) + 3] |= 4;
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0)
+		 | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? 4 : 0)))
+      __builtin_abort ();
+}
+
+template <typename Q>
+void
+B<Q>::m2 (const Q &u, const Q &v, const I<int> &x, const I<int> &y)
+{
+  int w = 0;
+  #pragma omp parallel for private (a) reduction(|:w)
+  for (a = u; B::a < v - 33; a += 2)
+    w |= (1 << *B::a);
+  if (w != 0x55555555)
+    __builtin_abort ();
+  #pragma omp parallel for lastprivate (U<Q>::t)
+  for (U<Q>::t = u; U<Q>::t < v - 32; U<Q>::t += 3)
+    d[*U<Q>::t + 2] |= 1;
+  if (*U<Q>::t != 33)
+    __builtin_abort ();
+  for (int i = 0; i < 64; i++)
+    if (d[i] != ((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0))
+      __builtin_abort ();
+  w = 0;
+  #pragma omp parallel for reduction(|:w)
+  for (a = u; B::a < v - 33; a += 2)
+    w |= (1 << *B::a);
+  if (w != 0x55555555)
+    __builtin_abort ();
+  #pragma omp taskloop
+  for (R::r = x; r < y - 32; R::r += 2)
+    d[*r + 8] |= 2;
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0)
+		 | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0)))
+      __builtin_abort ();
+  #pragma omp taskloop collapse(2)
+  for (U<Q>::t = u; U<Q>::t < v - 57; U<Q>::t += 2)
+    for (a = u; B::a < v - 56; a++)
+      d[((*U<Q>::t << 2) | *a) + 3] |= 4;
+  for (int i = 0; i < 64; i++)
+    if (d[i] != (((i >= 2 && i < 32 + 2 && (i - 2) % 3 == 0) ? 1 : 0)
+		 | ((i >= 8 && i < 32 + 8 && (i & 1) == 0) ? 2 : 0)
+		 | ((i >= 3 && i < 32 + 3) ? 4 : 0)))
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  A a;
+  int b[128];
+  for (int i = 0; i < 128; i++)
+    b[i] = i - 32;
+  a.m1 (&b[32], &b[96]);
+  for (int i = 0; i < 64; i++)
+    d[i] = 0;
+  B<I<int> > c;
+  c.m2 (&b[32], &b[96], &b[32], &b[96]);
+  for (int i = 0; i < 64; i++)
+    d[i] = 0;
+  B<int *> d;
+  d.m2 (&b[32], &b[96], &b[32], &b[96]);
+}

	Jakub



More information about the Gcc-patches mailing list