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