diff mbox

[gomp4] Support C++ "this" in OpenACC directives

Message ID alpine.DEB.2.10.1506101137220.2077@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers June 10, 2015, 11:38 a.m. UTC
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.)

Apart from parsing, it's necessary to prevent the "cannot take the
address of 'this', which is an rvalue expression" error from appearing
when "this" is used in such contexts.  This patch duly adds a new
argument to cxx_mark_addressable (default false so callers don't all
need to change) to allow disabling that error, passing that argument
in all calls that seem relevant to OpenACC directives.

Tested for x86_64-none-linux-gnu and applied to gomp-4_0-branch.

gcc/cp:
2015-06-10  Joseph Myers  <joseph@codesourcery.com>

	* parser.c (cp_parser_omp_var_list_no_open): Handle RID_THIS.
	* typeck.c (cxx_mark_addressable): Add argument ALLOW_THIS.
	* cp-tree.h (cxx_mark_addressable): Update prototype.
	* semantics.c (handle_omp_array_sections)
	(finish_omp_reduction_clause, finish_omp_clauses): Pass ALLOW_THIS
	to cxx_mark_addressable.

libgomp:
2015-06-10  Cesar Philippidis  <cesar@codesourcery.com>

	* testsuite/libgomp.oacc-c++/this.C: New test.

Comments

Jakub Jelinek June 10, 2015, 11:44 a.m. UTC | #1
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.)

For OpenMP 4.1, this is being considered as allowed (both alone or
supposedly in some cases also for array sections (like this[0],
this[:1] or this[0:1]) to a subset of clauses, but what exact clauses
will it be allowed on and the exact wording is a matter of hopefully next
few weeks.

	Jakub
diff mbox

Patch

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 224232)
+++ gcc/cp/parser.c	(working copy)
@@ -27872,19 +27872,27 @@  cp_parser_omp_var_list_no_open (cp_parser *parser,
       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 = current_class_ptr;
+	  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);
-      if (decl == error_mark_node)
-	cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
-				     token->location);
-      else if (kind != 0)
+	  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);
+	}
+      if (decl != error_mark_node && kind != 0)
 	{
 	  switch (kind)
 	    {
@@ -27958,7 +27966,7 @@  cp_parser_omp_var_list_no_open (cp_parser *parser,
 	  OMP_CLAUSE_CHAIN (u) = list;
 	  list = u;
 	}
-      else
+      else if (decl != error_mark_node)
 	list = tree_cons (decl, NULL_TREE, list);
 
     get_comma:
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 224232)
+++ gcc/cp/typeck.c	(working copy)
@@ -6019,10 +6019,11 @@  unary_complex_lvalue (enum tree_code code, tree ar
    address of it; it should not be allocated in a register.
    Value is true if successful.
 
-   C++: we do not allow `current_class_ptr' to be addressable.  */
+   C++: we do not allow `current_class_ptr' to be addressable unless
+   ALLOW_THIS is true.  */
 
 bool
-cxx_mark_addressable (tree exp)
+cxx_mark_addressable (tree exp, bool allow_this)
 {
   tree x = exp;
 
@@ -6040,7 +6041,8 @@  bool
       case PARM_DECL:
 	if (x == current_class_ptr)
 	  {
-	    error ("cannot take the address of %<this%>, which is an rvalue expression");
+	    if (!allow_this)
+	      error ("cannot take the address of %<this%>, which is an rvalue expression");
 	    TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later.  */
 	    return true;
 	  }
@@ -6083,7 +6085,7 @@  bool
 
       case TARGET_EXPR:
 	TREE_ADDRESSABLE (x) = 1;
-	cxx_mark_addressable (TREE_OPERAND (x, 0));
+	cxx_mark_addressable (TREE_OPERAND (x, 0), allow_this);
 	return true;
 
       default:
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 224232)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -6168,7 +6168,7 @@  extern void cxx_print_error_function		(diagnostic_
 						 struct diagnostic_info *);
 
 /* in typeck.c */
-extern bool cxx_mark_addressable		(tree);
+extern bool cxx_mark_addressable		(tree, bool = false);
 extern int string_conv_p			(const_tree, const_tree, int);
 extern tree cp_truthvalue_conversion		(tree);
 extern tree condition_conversion		(tree);
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 224232)
+++ gcc/cp/semantics.c	(working copy)
@@ -4673,7 +4673,7 @@  handle_omp_array_sections (tree c)
 	  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
 				      OMP_CLAUSE_MAP);
 	  OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
-	  if (!cxx_mark_addressable (t))
+	  if (!cxx_mark_addressable (t, true))
 	    return false;
 	  OMP_CLAUSE_DECL (c2) = t;
 	  t = build_fold_addr_expr (first);
@@ -5204,7 +5204,7 @@  finish_omp_reduction_clause (tree c, bool *need_de
 	      if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1]))
 		  && TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
 		     != REFERENCE_TYPE)
-		cxx_mark_addressable (OMP_CLAUSE_DECL (c));
+		cxx_mark_addressable (OMP_CLAUSE_DECL (c), true);
 	      tree omp_out = placeholder;
 	      tree omp_in = convert_from_reference (OMP_CLAUSE_DECL (c));
 	      if (need_static_cast)
@@ -5228,7 +5228,7 @@  finish_omp_reduction_clause (tree c, bool *need_de
 	      gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR
 			  && TREE_CODE (stmts[4]) == DECL_EXPR);
 	      if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])))
-		cxx_mark_addressable (OMP_CLAUSE_DECL (c));
+		cxx_mark_addressable (OMP_CLAUSE_DECL (c), true);
 	      if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4])))
 		cxx_mark_addressable (placeholder);
 	      tree omp_priv = convert_from_reference (OMP_CLAUSE_DECL (c));
@@ -5844,7 +5844,7 @@  finish_omp_clauses (tree clauses, bool oacc)
 	      remove = true;
 	    }
 	  else if (!processing_template_decl
-		   && !cxx_mark_addressable (t))
+		   && !cxx_mark_addressable (t, true))
 	    remove = true;
 	  break;
 
@@ -5907,7 +5907,7 @@  finish_omp_clauses (tree clauses, bool oacc)
 	    }
 	  else if (!processing_template_decl
 		   && TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE
-		   && !cxx_mark_addressable (t))
+		   && !cxx_mark_addressable (t, true))
 	    remove = true;
 	  else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
 		     && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
Index: libgomp/testsuite/libgomp.oacc-c++/this.C
===================================================================
--- libgomp/testsuite/libgomp.oacc-c++/this.C	(revision 0)
+++ libgomp/testsuite/libgomp.oacc-c++/this.C	(revision 0)
@@ -0,0 +1,43 @@ 
+#include <cstdlib>
+#include <iostream>
+using namespace std;
+
+class test {
+  public:
+  int a;
+
+  test ()
+  {
+    a = -1;
+#pragma acc enter data copyin (this[0:1])
+  }
+
+  ~test ()
+  {
+#pragma acc exit data delete (this[0:1])
+  }
+  
+  void set (int i)
+  {
+    a = i;
+#pragma acc update device (this[0:1])
+  }
+
+  int get ()
+  {
+#pragma acc update host (this[0:1])
+    return a;
+  }
+};
+
+int
+main ()
+{
+  test t;
+
+  t.set (4);
+  if (t.get () != 4)
+    abort ();
+
+  return 0;
+}