diff mbox

[gomp4.1] Support C++ "this" in OpenMP directives

Message ID 20150709085014.GK10247@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek July 9, 2015, 8:50 a.m. UTC
On Wed, Jun 10, 2015 at 11:38:25AM +0000, Joseph Myers wrote:
> This patch, for gomp-4_0-branch, adds support for C++ "this" in
> OpenACC directives.  (This patch does not do anything to handle OpenMP
> differently from OpenACC; that - bug 66053 - will need to be resolved
> for mainline, either deciding these cases should be accepted for
> OpenMP or making the parsing only accept them in OpenACC directives
> and not OpenMP ones.)

So, OpenMP 4.1 is going to accept this only in linear/uniform/aligned
clauses and only in #pragma omp declare simd construct.

This patch implements this, but as there is no oacc argument to
finish_omp_clauses on the trunk/gomp-4_1-branch, I haven't used that
to allow it in OpenACC directives, so that will need to be resolved
when the branches are merged to trunk.

Note I'm afraid your gomp-4_0-branch patch will not do the right thing
if you use this outside of non-static member functions (which is why I've
added the finish_this_expr for diagnostics).

Anyway, committed to gomp4.1 branch.

2015-07-09  Jakub Jelinek  <jakub@redhat.com>

	* parser.c (cp_parser_omp_var_list_no_open): Parse this.
	* cp-tree.h (finish_omp_declare_simd_methods): New prototype.
	* semantics.c (handle_omp_array_sections_1): Disallow this based
	array sections for OpenMP.
	(finish_omp_declare_simd_methods): New function.
	(finish_omp_clauses): Don't attempt to adjust linear step of
	this if it points to TYPE_BEING_DEFINED.  Disallow this in
	all clauses expecting variable lists, except for declare simd
	linear/uniform/aligned clauses.
	(finish_struct_1): Call finish_omp_declare_simd_methods.

	* g++.dg/vect/simd-clone-2.cc: New test.
	* g++.dg/vect/simd-clone-2.h: New file.
	* g++.dg/vect/simd-clone-3.cc: New test.
	* g++.dg/vect/simd-clone-4.cc: New test.
	* g++.dg/vect/simd-clone-4.h: New file.
	* g++.dg/vect/simd-clone-5.cc: New test.
	* g++.dg/gomp/this-1.C: New test.
	* g++.dg/gomp/this-2.C: New test.



	Jakub

Comments

Ilya Verbin July 15, 2015, 12:47 p.m. UTC | #1
On Thu, Jul 09, 2015 at 10:50:14 +0200, Jakub Jelinek wrote:
> 	* parser.c (cp_parser_omp_var_list_no_open): Parse this.
> 	* cp-tree.h (finish_omp_declare_simd_methods): New prototype.
> 	* semantics.c (handle_omp_array_sections_1): Disallow this based
> 	array sections for OpenMP.
> 	(finish_omp_declare_simd_methods): New function.
> 	(finish_omp_clauses): Don't attempt to adjust linear step of
> 	this if it points to TYPE_BEING_DEFINED.  Disallow this in
> 	all clauses expecting variable lists, except for declare simd
> 	linear/uniform/aligned clauses.
> 	(finish_struct_1): Call finish_omp_declare_simd_methods.
> 
> 	* g++.dg/vect/simd-clone-2.cc: New test.
> 	* g++.dg/vect/simd-clone-2.h: New file.
> 	* g++.dg/vect/simd-clone-3.cc: New test.
> 	* g++.dg/vect/simd-clone-4.cc: New test.
> 	* g++.dg/vect/simd-clone-4.h: New file.
> 	* g++.dg/vect/simd-clone-5.cc: New test.
> 	* g++.dg/gomp/this-1.C: New test.
> 	* g++.dg/gomp/this-2.C: New test.

One more warning:

gcc/cp/parser.c: In function ‘tree_node* cp_parser_omp_var_list_no_open(cp_parser*, omp_clause_code, tree, bool*)’:
gcc/cp/parser.c:27931:26: error: ‘name’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
          token->location);
                          ^
cc1plus: all warnings being treated as errors
make[4]: *** [cp/parser.o] Error 1

  -- Ilya
diff mbox

Patch

--- gcc/cp/parser.c.jj	2015-07-06 13:42:22.000000000 +0200
+++ gcc/cp/parser.c	2015-07-08 11:33:17.255688547 +0200
@@ -27881,15 +27881,26 @@  cp_parser_omp_var_list_no_open (cp_parse
       tree name, decl;
 
       token = cp_lexer_peek_token (parser->lexer);
-      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)
-	goto skip_comma;
+      if (current_class_ptr && cp_parser_is_keyword (token, RID_THIS))
+	{
+	  decl = finish_this_expr ();
+	  if (TREE_CODE (decl) == NON_LVALUE_EXPR
+	      || CONVERT_EXPR_P (decl))
+	    decl = TREE_OPERAND (decl, 0);
+	  cp_lexer_consume_token (parser->lexer);
+	}
+      else
+	{
+	  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)
+	    goto skip_comma;
 
-      decl = cp_parser_lookup_name_simple (parser, name, token->location);
+	  decl = cp_parser_lookup_name_simple (parser, name, token->location);
+	}
       if (decl == error_mark_node)
 	cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
 				     token->location);
--- gcc/cp/cp-tree.h.jj	2015-07-01 12:50:49.000000000 +0200
+++ gcc/cp/cp-tree.h	2015-07-08 17:27:02.787472523 +0200
@@ -5998,6 +5998,7 @@  extern void note_decl_for_pch			(tree);
 extern tree omp_reduction_id			(enum tree_code, tree, tree);
 extern tree cp_remove_omp_priv_cleanup_stmt	(tree *, int *, void *);
 extern void cp_check_omp_declare_reduction	(tree);
+extern void finish_omp_declare_simd_methods	(tree);
 extern tree finish_omp_clauses			(tree, bool, bool = false);
 extern tree push_omp_privatization_clauses	(bool);
 extern void pop_omp_privatization_clauses	(tree);
--- gcc/cp/semantics.c.jj	2015-07-06 19:20:51.000000000 +0200
+++ gcc/cp/semantics.c	2015-07-08 19:26:01.837813436 +0200
@@ -4390,6 +4390,15 @@  handle_omp_array_sections_1 (tree c, tre
 		      omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
 	  return error_mark_node;
 	}
+      else if (TREE_CODE (t) == PARM_DECL
+	       && DECL_ARTIFICIAL (t)
+	       && DECL_NAME (t) == this_identifier)
+	{
+	  error_at (OMP_CLAUSE_LOCATION (c),
+		    "%<this%> allowed in OpenMP only in %<declare simd%>"
+		    " clauses");
+	  return error_mark_node;
+	}
       else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
 	       && VAR_P (t) && DECL_THREAD_LOCAL_P (t))
 	{
@@ -5491,6 +5500,39 @@  finish_omp_reduction_clause (tree c, boo
   return false;
 }
 
+/* Called from finish_struct_1.  linear(this) or linear(this:step)
+   clauses might not be finalized yet because the class has been incomplete
+   when parsing #pragma omp declare simd methods.  Fix those up now.  */
+
+void
+finish_omp_declare_simd_methods (tree t)
+{
+  if (processing_template_decl)
+    return;
+
+  for (tree x = TYPE_METHODS (t); x; x = DECL_CHAIN (x))
+    {
+      if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE)
+	continue;
+      tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x));
+      if (!ods || !TREE_VALUE (ods))
+	continue;
+      for (tree c = TREE_VALUE (TREE_VALUE (ods)); c; c = OMP_CLAUSE_CHAIN (c))
+	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+	    && integer_zerop (OMP_CLAUSE_DECL (c))
+	    && OMP_CLAUSE_LINEAR_STEP (c)
+	    && TREE_CODE (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c)))
+	       == POINTER_TYPE)
+	  {
+	    tree s = OMP_CLAUSE_LINEAR_STEP (c);
+	    s = fold_convert_loc (OMP_CLAUSE_LOCATION (c), sizetype, s);
+	    s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MULT_EXPR,
+				 sizetype, s, TYPE_SIZE_UNIT (t));
+	    OMP_CLAUSE_LINEAR_STEP (c) = s;
+	  }
+    }
+}
+
 /* For all elements of CLAUSES, validate them vs OpenMP constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -5626,7 +5668,15 @@  finish_omp_clauses (tree clauses, bool a
 			  break;
 			}
 		    }
-		  else if (TREE_CODE (type) == POINTER_TYPE)
+		  else if (TREE_CODE (type) == POINTER_TYPE
+			   /* Can't multiply the step yet if *this
+			      is still incomplete type.  */
+			   && (!declare_simd
+			       || TREE_CODE (OMP_CLAUSE_DECL (c)) != PARM_DECL
+			       || !DECL_ARTIFICIAL (OMP_CLAUSE_DECL (c))
+			       || DECL_NAME (OMP_CLAUSE_DECL (c))
+				  != this_identifier
+			       || !TYPE_BEING_DEFINED (TREE_TYPE (type))))
 		    {
 		      tree d = convert_from_reference (OMP_CLAUSE_DECL (c));
 		      t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
@@ -5655,6 +5705,16 @@  finish_omp_clauses (tree clauses, bool a
 	  else
 	    t = OMP_CLAUSE_DECL (c);
 	check_dup_generic_t:
+	  if (t == current_class_ptr
+	      && (!declare_simd
+		  || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
+		      && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
+	    {
+	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+		     " clauses");
+	      remove = true;
+	      break;
+	    }
 	  if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
 	      && (!field_ok || TREE_CODE (t) != FIELD_DECL))
 	    {
@@ -5696,6 +5756,13 @@  finish_omp_clauses (tree clauses, bool a
 	    omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
 	  else
 	    t = OMP_CLAUSE_DECL (c);
+	  if (t == current_class_ptr)
+	    {
+	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+		     " clauses");
+	      remove = true;
+	      break;
+	    }
 	  if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
 	      && (!allow_fields || TREE_CODE (t) != FIELD_DECL))
 	    {
@@ -5723,6 +5790,13 @@  finish_omp_clauses (tree clauses, bool a
 	    omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
 	  else
 	    t = OMP_CLAUSE_DECL (c);
+	  if (t == current_class_ptr)
+	    {
+	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+		     " clauses");
+	      remove = true;
+	      break;
+	    }
 	  if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL
 	      && (!allow_fields || TREE_CODE (t) != FIELD_DECL))
 	    {
@@ -6000,6 +6074,13 @@  finish_omp_clauses (tree clauses, bool a
 
 	case OMP_CLAUSE_ALIGNED:
 	  t = OMP_CLAUSE_DECL (c);
+	  if (t == current_class_ptr && !declare_simd)
+	    {
+	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+		     " clauses");
+	      remove = true;
+	      break;
+	    }
 	  if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
 	    {
 	      if (processing_template_decl)
@@ -6086,6 +6167,12 @@  finish_omp_clauses (tree clauses, bool a
 		error ("%qE is not a variable in %<depend%> clause", t);
 	      remove = true;
 	    }
+	  else if (t == current_class_ptr)
+	    {
+	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+		     " clauses");
+	      remove = true;
+	    }
 	  else if (!processing_template_decl
 		   && !cxx_mark_addressable (t))
 	    remove = true;
@@ -6139,6 +6226,13 @@  finish_omp_clauses (tree clauses, bool a
 		     omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
 	      remove = true;
 	    }
+	  else if (t == current_class_ptr)
+	    {
+	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
+		     " clauses");
+	      remove = true;
+	      break;
+	    }
 	  else if (!processing_template_decl
 		   && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
 		   && !cxx_mark_addressable (t))
--- gcc/cp/class.c.jj	2015-06-30 14:25:15.000000000 +0200
+++ gcc/cp/class.c	2015-07-08 17:06:57.182745066 +0200
@@ -6651,6 +6651,8 @@  finish_struct_1 (tree t)
 
   finish_struct_bits (t);
   set_method_tm_attributes (t);
+  if (flag_openmp || flag_openmp_simd)
+    finish_omp_declare_simd_methods (t);
 
   /* Complete the rtl for any static member objects of the type we're
      working on.  */
--- gcc/testsuite/g++.dg/vect/simd-clone-2.cc.jj	2015-07-08 18:05:43.898418797 +0200
+++ gcc/testsuite/g++.dg/vect/simd-clone-2.cc	2015-07-08 18:34:57.039683991 +0200
@@ -0,0 +1,55 @@ 
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline -DONE_FILE" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+#ifdef ONE_FILE
+#include "simd-clone-3.cc"
+#else
+#include "simd-clone-2.h"
+#endif
+
+T b __attribute__((aligned (32)));
+
+void
+do_main ()
+{
+  int i, r = 0;
+  S a[64];
+  for (i = 0; i < 64; i++)
+    {
+      a[i].s = i;
+      b.t[i] = i;
+    }
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += a[16].f0 (i);
+  if (r != 64 * 63 / 2 + 64 * 16)
+    __builtin_abort ();
+  r = 0;
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += a[32].f1 (i);
+  if (r != 64 * 63 / 2 + 64 * 32)
+    __builtin_abort ();
+  r = 0;
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += a[i].f2 (i);
+  if (r != 64 * 63)
+    __builtin_abort ();
+  r = 0;
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += b.f3 (i);
+  if (r != 64 * 63 / 2)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  do_main ();
+}
--- gcc/testsuite/g++.dg/vect/simd-clone-2.h.jj	2015-07-08 18:06:14.945978075 +0200
+++ gcc/testsuite/g++.dg/vect/simd-clone-2.h	2015-07-08 18:02:21.459292430 +0200
@@ -0,0 +1,17 @@ 
+struct S
+{
+  int s;
+  #pragma omp declare simd notinbranch
+  int f0 (int x);
+  #pragma omp declare simd notinbranch uniform(this)
+  int f1 (int x);
+  #pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+  int f2 (int x);
+};
+
+struct T
+{
+  int t[64];
+  #pragma omp declare simd aligned(this:32) uniform(this) linear(x)
+  int f3 (int x);
+};
--- gcc/testsuite/g++.dg/vect/simd-clone-3.cc.jj	2015-07-08 18:05:48.203357688 +0200
+++ gcc/testsuite/g++.dg/vect/simd-clone-3.cc	2015-07-08 18:34:23.880149480 +0200
@@ -0,0 +1,34 @@ 
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-additional-sources "simd-clone-2.cc" }
+
+#include "simd-clone-2.h"
+
+#pragma omp declare simd notinbranch
+int
+S::f0 (int x)
+{
+  return x + s;
+}
+
+#pragma omp declare simd notinbranch uniform(this)
+int
+S::f1 (int x)
+{
+  return x + s;
+}
+
+#pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+int
+S::f2 (int x)
+{
+  return x + this->S::s;
+}
+
+#pragma omp declare simd uniform(this) aligned(this:32) linear(x)
+int
+T::f3 (int x)
+{
+  return t[x];
+}
--- gcc/testsuite/g++.dg/vect/simd-clone-4.cc.jj	2015-07-08 18:42:04.371685163 +0200
+++ gcc/testsuite/g++.dg/vect/simd-clone-4.cc	2015-07-08 18:42:23.137421732 +0200
@@ -0,0 +1,55 @@ 
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline -DONE_FILE" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+#ifdef ONE_FILE
+#include "simd-clone-5.cc"
+#else
+#include "simd-clone-4.h"
+#endif
+
+T<0> b __attribute__((aligned (32)));
+
+void
+do_main ()
+{
+  int i, r = 0;
+  S<0> a[64];
+  for (i = 0; i < 64; i++)
+    {
+      a[i].s = i;
+      b.t[i] = i;
+    }
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += a[16].f0 (i);
+  if (r != 64 * 63 / 2 + 64 * 16)
+    __builtin_abort ();
+  r = 0;
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += a[32].f1 (i);
+  if (r != 64 * 63 / 2 + 64 * 32)
+    __builtin_abort ();
+  r = 0;
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += a[i].f2 (i);
+  if (r != 64 * 63)
+    __builtin_abort ();
+  r = 0;
+  #pragma omp simd reduction(+:r)
+  for (i = 0; i < 64; i++)
+    r += b.f3 (i);
+  if (r != 64 * 63 / 2)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  check_vect ();
+  do_main ();
+}
--- gcc/testsuite/g++.dg/vect/simd-clone-4.h.jj	2015-07-08 18:42:31.770300545 +0200
+++ gcc/testsuite/g++.dg/vect/simd-clone-4.h	2015-07-08 18:42:45.939101645 +0200
@@ -0,0 +1,19 @@ 
+template <int N>
+struct S
+{
+  int s;
+  #pragma omp declare simd notinbranch
+  int f0 (int x);
+  #pragma omp declare simd notinbranch uniform(this)
+  int f1 (int x);
+  #pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+  int f2 (int x);
+};
+
+template <int N>
+struct T
+{
+  int t[64];
+  #pragma omp declare simd aligned(this:32) uniform(this) linear(x)
+  int f3 (int x);
+};
--- gcc/testsuite/g++.dg/vect/simd-clone-5.cc.jj	2015-07-08 18:42:58.486925500 +0200
+++ gcc/testsuite/g++.dg/vect/simd-clone-5.cc	2015-07-08 18:46:28.469983704 +0200
@@ -0,0 +1,41 @@ 
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd -fno-inline" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-additional-sources "simd-clone-4.cc" }
+
+#include "simd-clone-4.h"
+
+#pragma omp declare simd notinbranch
+template <int N>
+int
+S<N>::f0 (int x)
+{
+  return x + s;
+}
+
+#pragma omp declare simd notinbranch uniform(this)
+template <int N>
+int
+S<N>::f1 (int x)
+{
+  return x + s;
+}
+
+#pragma omp declare simd notinbranch linear(this:sizeof(this)/sizeof(this))
+template <int N>
+int
+S<N>::f2 (int x)
+{
+  return x + this->S::s;
+}
+
+#pragma omp declare simd uniform(this) aligned(this:32) linear(x)
+template <int N>
+int
+T<N>::f3 (int x)
+{
+  return t[x];
+}
+
+template struct S<0>;
+template struct T<0>;
--- gcc/testsuite/g++.dg/gomp/this-1.C.jj	2015-07-08 18:59:09.101366895 +0200
+++ gcc/testsuite/g++.dg/gomp/this-1.C	2015-07-08 19:28:30.836733226 +0200
@@ -0,0 +1,68 @@ 
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S
+{
+  #pragma omp declare simd linear(this)		// { dg-error "is not an function argument" }
+  static void foo ();
+  void bar ();
+};
+
+void
+S::bar ()
+{
+  #pragma omp parallel firstprivate (this)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp parallel for lastprivate (this)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  for (int i = 0; i < 10; i++)
+    ;
+  #pragma omp parallel shared (this)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp for linear (this)			// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  for (int i = 0; i < 10; i++)
+    ;
+  #pragma omp task depend(inout: this)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp task depend(inout: this[0])	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp parallel private (this)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  {
+    #pragma omp single copyprivate (this)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  }
+}
+
+template <int N>
+struct T
+{
+  #pragma omp declare simd linear(this)		// { dg-error "is not an function argument" }
+  static void foo ();
+  void bar ();
+};
+
+template <int N>
+void
+T<N>::bar ()
+{
+  #pragma omp parallel firstprivate (this)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp parallel for lastprivate (this)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  for (int i = 0; i < 10; i++)
+    ;
+  #pragma omp parallel shared (this)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp for linear (this)			// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  for (int i = 0; i < 10; i++)
+    ;
+  #pragma omp task depend(inout: this)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp task depend(inout: this[0])	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp parallel private (this)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  {
+    #pragma omp single copyprivate (this)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  }
+}
+
+template struct T<0>;
--- gcc/testsuite/g++.dg/gomp/this-2.C.jj	2015-07-08 18:59:16.693260928 +0200
+++ gcc/testsuite/g++.dg/gomp/this-2.C	2015-07-08 19:46:34.132605144 +0200
@@ -0,0 +1,42 @@ 
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S
+{
+  void bar (int);
+};
+
+void
+S::bar (int x)
+{
+  #pragma omp target map (this, x)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp target map (this[0], x)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp target update to (this, x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  #pragma omp target update to (this[0], x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  #pragma omp target update from (this, x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  #pragma omp target update from (this[1], x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+}
+
+template <int N>
+struct T
+{
+  void bar (int);
+};
+
+template <int N>
+void
+T<N>::bar (int x)
+{
+  #pragma omp target map (this, x)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp target map (this[0], x)		// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+    ;
+  #pragma omp target update to (this, x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  #pragma omp target update to (this[0], x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  #pragma omp target update from (this, x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+  #pragma omp target update from (this[1], x)	// { dg-error ".this. allowed in OpenMP only in .declare simd. clauses" }
+}
+
+template struct T<0>;