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  <jos...@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  <ce...@codesourcery.com>

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

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;
+}

-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to