OpenACC 2.6 deep copy: C and C++ front-end parts
authorJulian Brown <julian@codesourcery.com>
Fri, 20 Dec 2019 01:20:38 +0000 (01:20 +0000)
committerJulian Brown <jules@gcc.gnu.org>
Fri, 20 Dec 2019 01:20:38 +0000 (01:20 +0000)
gcc/c-family/
* c-common.h (c_omp_map_clause_name): Add prototype.
* c-omp.c (c_omp_map_clause_name): New function.
* c-pragma.h (pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_ATTACH and
PRAGMA_OACC_CLAUSE_DETACH.

gcc/c/
* c-parser.c (c_parser_omp_clause_name): Add parsing of attach and
detach clauses.
(c_parser_omp_variable_list): Add ALLOW_DEREF optional parameter.
Allow deref (->) in variable lists if true.
(c_parser_omp_var_list_parens): Add ALLOW_DEREF optional parameter.
Pass to c_parser_omp_variable_list.
(c_parser_oacc_data_clause): Support attach and detach clauses.  Update
call to c_parser_omp_variable_list.
(c_parser_oacc_all_clauses): Support attach and detach clauses.
(OACC_DATA_CLAUSE_MASK, OACC_ENTER_DATA_CLAUSE_MASK,
OACC_KERNELS_CLAUSE_MASK, OACC_PARALLEL_CLAUSE_MASK,
OACC_SERIAL_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_ATTACH.
(OACC_EXIT_DATA_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_DETACH.
* c-typeck.c (handle_omp_array_sections_1): Reject subarrays for attach
and detach.  Support deref.
(handle_omp_array_sections): Use GOMP_MAP_ATTACH_DETACH instead of
GOMP_MAP_ALWAYS_POINTER for OpenACC.
(c_oacc_check_attachments): New function.
(c_finish_omp_clauses): Check attach/detach arguments for being
pointers using above.  Support deref.

gcc/cp/
* parser.c (cp_parser_omp_clause_name): Support attach and detach
clauses.
(cp_parser_omp_var_list_no_open): Add ALLOW_DEREF optional parameter.
Parse deref if true.
(cp_parser_omp_var_list): Add ALLOW_DEREF optional parameter.  Pass to
cp_parser_omp_var_list_no_open.
(cp_parser_oacc_data_clause): Support attach and detach clauses.
Update call to cp_parser_omp_var_list_no_open.
(cp_parser_oacc_all_clauses): Support attach and detach.
(OACC_DATA_CLAUSE_MASK, OACC_ENTER_DATA_CLAUSE_MASK,
OACC_KERNELS_CLAUSE_MASK, OACC_PARALLEL_CLAUSE_MASK,
OACC_SERIAL_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_ATTACH.
(OACC_EXIT_DATA_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_DETACH.
* semantics.c (handle_omp_array_sections_1): Reject subarrays for
attach and detach.
(handle_omp_array_sections): Use GOMP_MAP_ATTACH_DETACH instead of
GOMP_MAP_ALWAYS_POINTER for OpenACC.
(cp_oacc_check_attachments): New function.
(finish_omp_clauses): Use above function.  Allow structure fields and
class members to appear in OpenACC data clauses.  Support
GOMP_MAP_ATTACH_DETACH.  Support deref.

gcc/testsuite/
* c-c++-common/goacc/deep-copy-arrayofstruct.c: New test.
* c-c++-common/goacc/mdc-1.c: New test.
* c-c++-common/goacc/mdc-2.c: New test.
* gcc.dg/goacc/mdc.C: New test.

Co-Authored-By: Cesar Philippidis <cesar@codesourcery.com>
From-SVN: r279627

15 files changed:
gcc/c-family/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/c-omp.c
gcc/c-family/c-pragma.h
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/goacc/mdc-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/goacc/mdc-2.c [new file with mode: 0644]
gcc/testsuite/g++.dg/goacc/mdc.C [new file with mode: 0644]

index 77d928a30780bf5d86ed8d92b51db24b222480f2..30cbc133dc391f0a872c13997b34235f065a4c86 100644 (file)
@@ -1,3 +1,10 @@
+2019-12-19  Julian Brown  <julian@codesourcery.com>
+
+       * c-common.h (c_omp_map_clause_name): Add prototype.
+       * c-omp.c (c_omp_map_clause_name): New function.
+       * c-pragma.h (pragma_omp_clause): Add PRAGMA_OACC_CLAUSE_ATTACH and
+       PRAGMA_OACC_CLAUSE_DETACH.
+
 2019-12-19  Julian Brown  <julian@codesourcery.com>
            Maciej W. Rozycki  <macro@codesourcery.com>
            Tobias Burnus  <tobias@codesourcery.com>
index 2bcb54f66b91f2f53a6fdc202c6abbf3247d9fd9..2d89451b6934d9cead2990f0bae8445202e71f86 100644 (file)
@@ -1205,6 +1205,7 @@ extern bool c_omp_predefined_variable (tree);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 extern tree c_omp_check_context_selector (location_t, tree);
 extern void c_omp_mark_declare_variant (location_t, tree, tree);
+extern const char *c_omp_map_clause_name (tree, bool);
 
 /* Return next tree in the chain for chain_next walking of tree nodes.  */
 static inline tree
index a4be2d68b9a9e0e7c62010b9dfc4e4de1d62abfe..04f2c0b06824ee6ebd932e2c60dc02a21ab55423 100644 (file)
@@ -2259,3 +2259,36 @@ c_omp_mark_declare_variant (location_t loc, tree variant, tree construct)
     error_at (loc, "%qD used as a variant with incompatible %<construct%> "
                   "selector sets", variant);
 }
+
+/* For OpenACC, the OMP_CLAUSE_MAP_KIND of an OMP_CLAUSE_MAP is used internally
+   to distinguish clauses as seen by the user.  Return the "friendly" clause
+   name for error messages etc., where possible.  See also
+   c/c-parser.c:c_parser_oacc_data_clause and
+   cp/parser.c:cp_parser_oacc_data_clause.  */
+
+const char *
+c_omp_map_clause_name (tree clause, bool oacc)
+{
+  if (oacc && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP)
+    switch (OMP_CLAUSE_MAP_KIND (clause))
+    {
+    case GOMP_MAP_FORCE_ALLOC:
+    case GOMP_MAP_ALLOC: return "create";
+    case GOMP_MAP_FORCE_TO:
+    case GOMP_MAP_TO: return "copyin";
+    case GOMP_MAP_FORCE_FROM:
+    case GOMP_MAP_FROM: return "copyout";
+    case GOMP_MAP_FORCE_TOFROM:
+    case GOMP_MAP_TOFROM: return "copy";
+    case GOMP_MAP_RELEASE: return "delete";
+    case GOMP_MAP_FORCE_PRESENT: return "present";
+    case GOMP_MAP_ATTACH: return "attach";
+    case GOMP_MAP_FORCE_DETACH:
+    case GOMP_MAP_DETACH: return "detach";
+    case GOMP_MAP_DEVICE_RESIDENT: return "device_resident";
+    case GOMP_MAP_LINK: return "link";
+    case GOMP_MAP_FORCE_DEVICEPTR: return "deviceptr";
+    default: break;
+    }
+  return omp_clause_code_name[OMP_CLAUSE_CODE (clause)];
+}
index 3754c5fda45e3c0c32a4dabcf3f59d14444cc951..bf57d3ddb6d0e104c42644a00068cc0210a3ac20 100644 (file)
@@ -143,11 +143,13 @@ enum pragma_omp_clause {
 
   /* Clauses for OpenACC.  */
   PRAGMA_OACC_CLAUSE_ASYNC,
+  PRAGMA_OACC_CLAUSE_ATTACH,
   PRAGMA_OACC_CLAUSE_AUTO,
   PRAGMA_OACC_CLAUSE_COPY,
   PRAGMA_OACC_CLAUSE_COPYOUT,
   PRAGMA_OACC_CLAUSE_CREATE,
   PRAGMA_OACC_CLAUSE_DELETE,
+  PRAGMA_OACC_CLAUSE_DETACH,
   PRAGMA_OACC_CLAUSE_DEVICEPTR,
   PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT,
   PRAGMA_OACC_CLAUSE_FINALIZE,
index f4a088a95118967c4f60520b12330a150ccdf913..469dc5d5d3483a246622f28d9ee76985e1f5fbcf 100644 (file)
@@ -1,3 +1,27 @@
+2019-12-19  Julian Brown  <julian@codesourcery.com>
+           Cesar Philippidis  <cesar@codesourcery.com>
+
+       * c-parser.c (c_parser_omp_clause_name): Add parsing of attach and
+       detach clauses.
+       (c_parser_omp_variable_list): Add ALLOW_DEREF optional parameter.
+       Allow deref (->) in variable lists if true.
+       (c_parser_omp_var_list_parens): Add ALLOW_DEREF optional parameter.
+       Pass to c_parser_omp_variable_list.
+       (c_parser_oacc_data_clause): Support attach and detach clauses.  Update
+       call to c_parser_omp_variable_list.
+       (c_parser_oacc_all_clauses): Support attach and detach clauses.
+       (OACC_DATA_CLAUSE_MASK, OACC_ENTER_DATA_CLAUSE_MASK,
+       OACC_KERNELS_CLAUSE_MASK, OACC_PARALLEL_CLAUSE_MASK,
+       OACC_SERIAL_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_ATTACH.
+       (OACC_EXIT_DATA_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_DETACH.
+       * c-typeck.c (handle_omp_array_sections_1): Reject subarrays for attach
+       and detach.  Support deref.
+       (handle_omp_array_sections): Use GOMP_MAP_ATTACH_DETACH instead of
+       GOMP_MAP_ALWAYS_POINTER for OpenACC.
+       (c_oacc_check_attachments): New function.
+       (c_finish_omp_clauses): Check attach/detach arguments for being
+       pointers using above.  Support deref.
+
 2019-12-19  Julian Brown  <julian@codesourcery.com>
            Maciej W. Rozycki  <macro@codesourcery.com>
            Tobias Burnus  <tobias@codesourcery.com>
index 9b8008816d2310785245125c6e775c6d7415da72..b3763c2e8886a238f6e28338e1794db3730b0291 100644 (file)
@@ -12564,6 +12564,8 @@ c_parser_omp_clause_name (c_parser *parser)
            result = PRAGMA_OMP_CLAUSE_ALIGNED;
          else if (!strcmp ("async", p))
            result = PRAGMA_OACC_CLAUSE_ASYNC;
+         else if (!strcmp ("attach", p))
+           result = PRAGMA_OACC_CLAUSE_ATTACH;
          break;
        case 'b':
          if (!strcmp ("bind", p))
@@ -12590,6 +12592,8 @@ c_parser_omp_clause_name (c_parser *parser)
            result = PRAGMA_OACC_CLAUSE_DELETE;
          else if (!strcmp ("depend", p))
            result = PRAGMA_OMP_CLAUSE_DEPEND;
+         else if (!strcmp ("detach", p))
+           result = PRAGMA_OACC_CLAUSE_DETACH;
          else if (!strcmp ("device", p))
            result = PRAGMA_OMP_CLAUSE_DEVICE;
          else if (!strcmp ("deviceptr", p))
@@ -12835,12 +12839,16 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
    If KIND is nonzero, CLAUSE_LOC is the location of the clause.
 
    If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
-   return the list created.  */
+   return the list created.
+
+   The optional ALLOW_DEREF argument is true if list items can use the deref
+   (->) operator.  */
 
 static tree
 c_parser_omp_variable_list (c_parser *parser,
                            location_t clause_loc,
-                           enum omp_clause_code kind, tree list)
+                           enum omp_clause_code kind, tree list,
+                           bool allow_deref = false)
 {
   auto_vec<c_token> tokens;
   unsigned int tokens_avail = 0;
@@ -12967,9 +12975,13 @@ c_parser_omp_variable_list (c_parser *parser,
            case OMP_CLAUSE_MAP:
            case OMP_CLAUSE_FROM:
            case OMP_CLAUSE_TO:
-             while (c_parser_next_token_is (parser, CPP_DOT))
+             while (c_parser_next_token_is (parser, CPP_DOT)
+                    || (allow_deref
+                        && c_parser_next_token_is (parser, CPP_DEREF)))
                {
                  location_t op_loc = c_parser_peek_token (parser)->location;
+                 if (c_parser_next_token_is (parser, CPP_DEREF))
+                   t = build_simple_mem_ref (t);
                  c_parser_consume_token (parser);
                  if (!c_parser_next_token_is (parser, CPP_NAME))
                    {
@@ -13091,11 +13103,12 @@ c_parser_omp_variable_list (c_parser *parser,
 }
 
 /* Similarly, but expect leading and trailing parenthesis.  This is a very
-   common case for OpenACC and OpenMP clauses.  */
+   common case for OpenACC and OpenMP clauses.  The optional ALLOW_DEREF
+   argument is true if list items can use the deref (->) operator.  */
 
 static tree
 c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
-                             tree list)
+                             tree list, bool allow_deref = false)
 {
   /* The clauses location.  */
   location_t loc = c_parser_peek_token (parser)->location;
@@ -13103,7 +13116,7 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
   matching_parens parens;
   if (parens.require_open (parser))
     {
-      list = c_parser_omp_variable_list (parser, loc, kind, list);
+      list = c_parser_omp_variable_list (parser, loc, kind, list, allow_deref);
       parens.skip_until_found_close (parser);
     }
   return list;
@@ -13118,7 +13131,9 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
    present ( variable-list )
 
    OpenACC 2.6:
-   no_create ( variable-list ) */
+   no_create ( variable-list )
+   attach ( variable-list )
+   detach ( variable-list ) */
 
 static tree
 c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
@@ -13127,6 +13142,9 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
   enum gomp_map_kind kind;
   switch (c_kind)
     {
+    case PRAGMA_OACC_CLAUSE_ATTACH:
+      kind = GOMP_MAP_ATTACH;
+      break;
     case PRAGMA_OACC_CLAUSE_COPY:
       kind = GOMP_MAP_TOFROM;
       break;
@@ -13142,6 +13160,9 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
     case PRAGMA_OACC_CLAUSE_DELETE:
       kind = GOMP_MAP_RELEASE;
       break;
+    case PRAGMA_OACC_CLAUSE_DETACH:
+      kind = GOMP_MAP_DETACH;
+      break;
     case PRAGMA_OACC_CLAUSE_DEVICE:
       kind = GOMP_MAP_FORCE_TO;
       break;
@@ -13164,7 +13185,7 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
       gcc_unreachable ();
     }
   tree nl, c;
-  nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list);
+  nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, true);
 
   for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
     OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -15879,6 +15900,10 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
                                                 clauses);
          c_name = "auto";
          break;
+       case PRAGMA_OACC_CLAUSE_ATTACH:
+         clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
+         c_name = "attach";
+         break;
        case PRAGMA_OACC_CLAUSE_COLLAPSE:
          clauses = c_parser_omp_clause_collapse (parser, clauses);
          c_name = "collapse";
@@ -15907,6 +15932,10 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
          clauses = c_parser_omp_clause_default (parser, clauses, true);
          c_name = "default";
          break;
+       case PRAGMA_OACC_CLAUSE_DETACH:
+         clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
+         c_name = "detach";
+         break;
        case PRAGMA_OACC_CLAUSE_DEVICE:
          clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
          c_name = "device";
@@ -16421,7 +16450,8 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
 */
 
 #define OACC_DATA_CLAUSE_MASK                                          \
-       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)              \
@@ -16605,6 +16635,7 @@ c_parser_oacc_declare (c_parser *parser)
 #define OACC_ENTER_DATA_CLAUSE_MASK                                    \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)                  \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
@@ -16614,6 +16645,7 @@ c_parser_oacc_declare (c_parser *parser)
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE)              \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE)            \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
 
@@ -16753,6 +16785,7 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
 
 #define OACC_KERNELS_CLAUSE_MASK                                       \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
@@ -16769,6 +16802,7 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
 
 #define OACC_PARALLEL_CLAUSE_MASK                                      \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
@@ -16788,6 +16822,7 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
 
 #define OACC_SERIAL_CLAUSE_MASK                                        \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
index ce5e6495fb12fe4548ff47a7e2e3aa67334ec85f..4fe4ab6f273f3e26004b7b2ccf638dddee95d36d 100644 (file)
@@ -12897,7 +12897,6 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
          return error_mark_node;
        }
       if (TREE_CODE (t) == COMPONENT_REF
-         && ort == C_ORT_OMP
          && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM))
@@ -12918,6 +12917,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
                  return error_mark_node;
                }
              t = TREE_OPERAND (t, 0);
+             if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF)
+               {
+                 if (maybe_ne (mem_ref_offset (t), 0))
+                   error_at (OMP_CLAUSE_LOCATION (c),
+                             "cannot dereference %qE in %qs clause", t,
+                             omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                 else
+                   t = TREE_OPERAND (t, 0);
+               }
            }
        }
       if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
@@ -13003,7 +13011,18 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
     length = fold_convert (sizetype, length);
   if (low_bound == NULL_TREE)
     low_bound = integer_zero_node;
-
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+      && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+         || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
+    {
+      if (length != integer_one_node)
+       {
+         error_at (OMP_CLAUSE_LOCATION (c),
+                   "expected single pointer in %qs clause",
+                   c_omp_map_clause_name (c, ort == C_ORT_ACC));
+         return error_mark_node;
+       }
+    }
   if (length != NULL_TREE)
     {
       if (!integer_nonzerop (length))
@@ -13444,7 +13463,11 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
       if (ort != C_ORT_OMP && ort != C_ORT_ACC)
        OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
       else if (TREE_CODE (t) == COMPONENT_REF)
-       OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+       {
+         gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                              : GOMP_MAP_ALWAYS_POINTER;
+         OMP_CLAUSE_SET_MAP_KIND (c2, k);
+       }
       else
        OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
       if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
@@ -13681,6 +13704,35 @@ c_omp_finish_iterators (tree iter)
   return ret;
 }
 
+/* Ensure that pointers are used in OpenACC attach and detach clauses.
+   Return true if an error has been detected.  */
+
+static bool
+c_oacc_check_attachments (tree c)
+{
+  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+    return false;
+
+  /* OpenACC attach / detach clauses must be pointers.  */
+  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+      || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+    {
+      tree t = OMP_CLAUSE_DECL (c);
+
+      while (TREE_CODE (t) == TREE_LIST)
+       t = TREE_CHAIN (t);
+
+      if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+       {
+         error_at (OMP_CLAUSE_LOCATION (c), "expected pointer in %qs clause",
+                   c_omp_map_clause_name (c, true));
+         return true;
+       }
+    }
+
+  return false;
+}
+
 /* For all elements of CLAUSES, validate them against their constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -14434,6 +14486,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                        }
                    }
                }
+             if (c_oacc_check_attachments (c))
+               remove = true;
              break;
            }
          if (t == error_mark_node)
@@ -14441,8 +14495,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              remove = true;
              break;
            }
+         /* OpenACC attach / detach clauses must be pointers.  */
+         if (c_oacc_check_attachments (c))
+           {
+             remove = true;
+             break;
+           }
          if (TREE_CODE (t) == COMPONENT_REF
-             && (ort & C_ORT_OMP)
              && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
            {
              if (DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
@@ -14477,6 +14536,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                      break;
                    }
                  t = TREE_OPERAND (t, 0);
+                 if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF)
+                   {
+                     if (maybe_ne (mem_ref_offset (t), 0))
+                       error_at (OMP_CLAUSE_LOCATION (c),
+                                 "cannot dereference %qE in %qs clause", t,
+                                 omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+                     else
+                       t = TREE_OPERAND (t, 0);
+                   }
                }
              if (remove)
                break;
index 40c8621004393b8650d83c8898dfea82ad779222..2b90d0ca7cfd9887b1a47f8bc0516941867dc713 100644 (file)
@@ -1,3 +1,28 @@
+2019-12-19  Julian Brown  <julian@codesourcery.com>
+           Cesar Philippidis  <cesar@codesourcery.com>
+
+       * parser.c (cp_parser_omp_clause_name): Support attach and detach
+       clauses.
+       (cp_parser_omp_var_list_no_open): Add ALLOW_DEREF optional parameter.
+       Parse deref if true.
+       (cp_parser_omp_var_list): Add ALLOW_DEREF optional parameter.  Pass to
+       cp_parser_omp_var_list_no_open.
+       (cp_parser_oacc_data_clause): Support attach and detach clauses.
+       Update call to cp_parser_omp_var_list_no_open.
+       (cp_parser_oacc_all_clauses): Support attach and detach.
+       (OACC_DATA_CLAUSE_MASK, OACC_ENTER_DATA_CLAUSE_MASK,
+       OACC_KERNELS_CLAUSE_MASK, OACC_PARALLEL_CLAUSE_MASK,
+       OACC_SERIAL_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_ATTACH.
+       (OACC_EXIT_DATA_CLAUSE_MASK): Add PRAGMA_OACC_CLAUSE_DETACH.
+       * semantics.c (handle_omp_array_sections_1): Reject subarrays for
+       attach and detach.
+       (handle_omp_array_sections): Use GOMP_MAP_ATTACH_DETACH instead of
+       GOMP_MAP_ALWAYS_POINTER for OpenACC.
+       (cp_oacc_check_attachments): New function.
+       (finish_omp_clauses): Use above function.  Allow structure fields and
+       class members to appear in OpenACC data clauses.  Support
+       GOMP_MAP_ATTACH_DETACH.  Support deref.
+
 2019-12-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/52320 - EH cleanups for partially constructed arrays.
index ce2e4b5b1253706dd450db384d3528e1656000ad..c3c968d9ce413e638f3c22635a1dbc8a45c12aa3 100644 (file)
@@ -33538,6 +33538,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_ALIGNED;
          else if (!strcmp ("async", p))
            result = PRAGMA_OACC_CLAUSE_ASYNC;
+         else if (!strcmp ("attach", p))
+           result = PRAGMA_OACC_CLAUSE_ATTACH;
          break;
        case 'b':
          if (!strcmp ("bind", p))
@@ -33562,6 +33564,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
            result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
          else if (!strcmp ("depend", p))
            result = PRAGMA_OMP_CLAUSE_DEPEND;
+         else if (!strcmp ("detach", p))
+           result = PRAGMA_OACC_CLAUSE_DETACH;
          else if (!strcmp ("device", p))
            result = PRAGMA_OMP_CLAUSE_DEVICE;
          else if (!strcmp ("deviceptr", p))
@@ -33766,11 +33770,15 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
 
    COLON can be NULL if only closing parenthesis should end the list,
    or pointer to bool which will receive false if the list is terminated
-   by closing parenthesis or true if the list is terminated by colon.  */
+   by closing parenthesis or true if the list is terminated by colon.
+
+   The optional ALLOW_DEREF argument is true if list items can use the deref
+   (->) operator.  */
 
 static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
-                               tree list, bool *colon)
+                               tree list, bool *colon,
+                               bool allow_deref = false)
 {
   cp_token *token;
   bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
@@ -33851,15 +33859,20 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
            case OMP_CLAUSE_MAP:
            case OMP_CLAUSE_FROM:
            case OMP_CLAUSE_TO:
-             while (cp_lexer_next_token_is (parser->lexer, CPP_DOT))
+             while (cp_lexer_next_token_is (parser->lexer, CPP_DOT)
+                    || (allow_deref
+                        && cp_lexer_next_token_is (parser->lexer, CPP_DEREF)))
                {
+                 cpp_ttype ttype
+                   = cp_lexer_next_token_is (parser->lexer, CPP_DOT)
+                     ? CPP_DOT : CPP_DEREF;
                  location_t loc
                    = cp_lexer_peek_token (parser->lexer)->location;
                  cp_id_kind idk = CP_ID_KIND_NONE;
                  cp_lexer_consume_token (parser->lexer);
                  decl = convert_from_reference (decl);
                  decl
-                   = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT,
+                   = cp_parser_postfix_dot_deref_expression (parser, ttype,
                                                              decl, false,
                                                              &idk, loc);
                }
@@ -33977,10 +33990,12 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
    common case for omp clauses.  */
 
 static tree
-cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
+cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list,
+                       bool allow_deref = false)
 {
   if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return cp_parser_omp_var_list_no_open (parser, kind, list, NULL);
+    return cp_parser_omp_var_list_no_open (parser, kind, list, NULL,
+                                          allow_deref);
   return list;
 }
 
@@ -33993,7 +34008,9 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
    present ( variable-list )
 
    OpenACC 2.6:
-   no_create ( variable-list ) */
+   no_create ( variable-list )
+   attach ( variable-list )
+   detach ( variable-list ) */
 
 static tree
 cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
@@ -34002,6 +34019,9 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
   enum gomp_map_kind kind;
   switch (c_kind)
     {
+    case PRAGMA_OACC_CLAUSE_ATTACH:
+      kind = GOMP_MAP_ATTACH;
+      break;
     case PRAGMA_OACC_CLAUSE_COPY:
       kind = GOMP_MAP_TOFROM;
       break;
@@ -34017,6 +34037,9 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
     case PRAGMA_OACC_CLAUSE_DELETE:
       kind = GOMP_MAP_RELEASE;
       break;
+    case PRAGMA_OACC_CLAUSE_DETACH:
+      kind = GOMP_MAP_DETACH;
+      break;
     case PRAGMA_OACC_CLAUSE_DEVICE:
       kind = GOMP_MAP_FORCE_TO;
       break;
@@ -34039,7 +34062,7 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
       gcc_unreachable ();
     }
   tree nl, c;
-  nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list);
+  nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, true);
 
   for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
     OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -36517,6 +36540,10 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
                                                  clauses);
          c_name = "auto";
          break;
+       case PRAGMA_OACC_CLAUSE_ATTACH:
+         clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
+         c_name = "attach";
+         break;
        case PRAGMA_OACC_CLAUSE_COLLAPSE:
          clauses = cp_parser_omp_clause_collapse (parser, clauses, here);
          c_name = "collapse";
@@ -36545,6 +36572,10 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
          clauses = cp_parser_omp_clause_default (parser, clauses, here, true);
          c_name = "default";
          break;
+       case PRAGMA_OACC_CLAUSE_DETACH:
+         clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
+         c_name = "detach";
+         break;
        case PRAGMA_OACC_CLAUSE_DEVICE:
          clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
          c_name = "device";
@@ -40397,10 +40428,12 @@ cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok)
      structured-block  */
 
 #define OACC_DATA_CLAUSE_MASK                                          \
-       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
+       ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)              \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR)           \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)                  \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE)           \
@@ -40601,6 +40634,7 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
 
 #define OACC_ENTER_DATA_CLAUSE_MASK                                    \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF)                  \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE)              \
@@ -40611,6 +40645,7 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE)              \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE)            \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
 
@@ -40718,6 +40753,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
 
 #define OACC_KERNELS_CLAUSE_MASK                                       \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
@@ -40734,6 +40770,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
 
 #define OACC_PARALLEL_CLAUSE_MASK                                      \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
@@ -40753,6 +40790,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
 
 #define OACC_SERIAL_CLAUSE_MASK                                                \
        ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC)               \
+       | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY)                \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN)              \
        | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT)             \
index 69010dc85cd3f73a514ab41db1eb32143d019f99..a3058d7a78751b6bd9e39d27d11153d71bc7e3d1 100644 (file)
@@ -4744,7 +4744,6 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
        t = TREE_OPERAND (t, 0);
       ret = t;
       if (TREE_CODE (t) == COMPONENT_REF
-         && ort == C_ORT_OMP
          && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
              || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
@@ -4768,6 +4767,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
                  return error_mark_node;
                }
              t = TREE_OPERAND (t, 0);
+             if (ort == C_ORT_ACC && TREE_CODE (t) == INDIRECT_REF)
+               t = TREE_OPERAND (t, 0);
            }
          if (REFERENCE_REF_P (t))
            t = TREE_OPERAND (t, 0);
@@ -4867,6 +4868,18 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
   if (low_bound == NULL_TREE)
     low_bound = integer_zero_node;
 
+  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+      && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+         || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
+    {
+      if (length != integer_one_node)
+       {
+         error_at (OMP_CLAUSE_LOCATION (c),
+                   "expected single pointer in %qs clause",
+                   c_omp_map_clause_name (c, ort == C_ORT_ACC));
+         return error_mark_node;
+       }
+    }
   if (length != NULL_TREE)
     {
       if (!integer_nonzerop (length))
@@ -5315,12 +5328,18 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
          if ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP && ort != C_ORT_ACC)
            OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
          else if (TREE_CODE (t) == COMPONENT_REF)
-           OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+           {
+             gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                                  : GOMP_MAP_ALWAYS_POINTER;
+             OMP_CLAUSE_SET_MAP_KIND (c2, k);
+           }
          else if (REFERENCE_REF_P (t)
                   && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
            {
              t = TREE_OPERAND (t, 0);
-             OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+             gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                                  : GOMP_MAP_ALWAYS_POINTER;
+             OMP_CLAUSE_SET_MAP_KIND (c2, k);
            }
          else
            OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
@@ -6243,6 +6262,41 @@ cp_omp_finish_iterators (tree iter)
   return ret;
 }
 
+/* Ensure that pointers are used in OpenACC attach and detach clauses.
+   Return true if an error has been detected.  */
+
+static bool
+cp_oacc_check_attachments (tree c)
+{
+  if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
+    return false;
+
+  /* OpenACC attach / detach clauses must be pointers.  */
+  if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
+      || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
+    {
+      tree t = OMP_CLAUSE_DECL (c);
+      tree type;
+
+      while (TREE_CODE (t) == TREE_LIST)
+       t = TREE_CHAIN (t);
+
+      type = TREE_TYPE (t);
+
+      if (TREE_CODE (type) == REFERENCE_TYPE)
+       type = TREE_TYPE (type);
+
+      if (TREE_CODE (type) != POINTER_TYPE)
+       {
+         error_at (OMP_CLAUSE_LOCATION (c), "expected pointer in %qs clause",
+                   c_omp_map_clause_name (c, true));
+         return true;
+       }
+    }
+
+  return false;
+}
+
 /* For all elements of CLAUSES, validate them vs OpenMP constraints.
    Remove any elements from the list that are invalid.  */
 
@@ -6507,7 +6561,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            t = OMP_CLAUSE_DECL (c);
        check_dup_generic_t:
          if (t == current_class_ptr
-             && (ort != C_ORT_OMP_DECLARE_SIMD
+             && ((ort != C_ORT_OMP_DECLARE_SIMD && ort != C_ORT_ACC)
                  || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
                      && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM)))
            {
@@ -6577,8 +6631,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
        handle_field_decl:
          if (!remove
              && TREE_CODE (t) == FIELD_DECL
-             && t == OMP_CLAUSE_DECL (c)
-             && ort != C_ORT_ACC)
+             && t == OMP_CLAUSE_DECL (c))
            {
              OMP_CLAUSE_DECL (c)
                = omp_privatize_field (t, (OMP_CLAUSE_CODE (c)
@@ -6645,7 +6698,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
          else
            t = OMP_CLAUSE_DECL (c);
-         if (t == current_class_ptr)
+         if (ort != C_ORT_ACC && t == current_class_ptr)
            {
              error_at (OMP_CLAUSE_LOCATION (c),
                        "%<this%> allowed in OpenMP only in %<declare simd%>"
@@ -7134,7 +7187,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            }
          if (t == error_mark_node)
            remove = true;
-         else if (t == current_class_ptr)
+         else if (ort != C_ORT_ACC && t == current_class_ptr)
            {
              error_at (OMP_CLAUSE_LOCATION (c),
                        "%<this%> allowed in OpenMP only in %<declare simd%>"
@@ -7266,6 +7319,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                        }
                    }
                }
+             if (cp_oacc_check_attachments (c))
+               remove = true;
              break;
            }
          if (t == error_mark_node)
@@ -7273,14 +7328,25 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              remove = true;
              break;
            }
+         /* OpenACC attach / detach clauses must be pointers.  */
+         if (cp_oacc_check_attachments (c))
+           {
+             remove = true;
+             break;
+           }
          if (REFERENCE_REF_P (t)
              && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)
            {
              t = TREE_OPERAND (t, 0);
              OMP_CLAUSE_DECL (c) = t;
            }
+         if (ort == C_ORT_ACC
+             && TREE_CODE (t) == COMPONENT_REF
+             && TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF)
+           t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
          if (TREE_CODE (t) == COMPONENT_REF
-             && (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+             && ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
+                 || ort == C_ORT_ACC)
              && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_)
            {
              if (type_dependent_expression_p (t))
@@ -7330,7 +7396,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                break;
              if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
                  && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
-                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER))
+                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
+                     || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH))
                break;
              if (DECL_P (t))
                error_at (OMP_CLAUSE_LOCATION (c),
@@ -7412,7 +7479,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              else
                bitmap_set_bit (&generic_head, DECL_UID (t));
            }
-         else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+         else if (bitmap_bit_p (&map_head, DECL_UID (t))
+                  && (ort != C_ORT_ACC
+                      || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
            {
              if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
                error_at (OMP_CLAUSE_LOCATION (c),
@@ -7467,7 +7536,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                  tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
                                              OMP_CLAUSE_MAP);
                  if (TREE_CODE (t) == COMPONENT_REF)
-                   OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER);
+                   {
+                     gomp_map_kind k
+                       = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
+                                            : GOMP_MAP_ALWAYS_POINTER;
+                     OMP_CLAUSE_SET_MAP_KIND (c2, k);
+                   }
                  else
                    OMP_CLAUSE_SET_MAP_KIND (c2,
                                             GOMP_MAP_FIRSTPRIVATE_REFERENCE);
index 5dfb3ec4ec2c569188ca833953f4bd9cabbdb570..9cd38fd2a1a1f8608ec4a56a34bdea250ef1669a 100644 (file)
@@ -1,3 +1,11 @@
+2019-12-19  Julian Brown  <julian@codesourcery.com>
+           Cesar Philippidis  <cesar@codesourcery.com>
+
+       * c-c++-common/goacc/deep-copy-arrayofstruct.c: New test.
+       * c-c++-common/goacc/mdc-1.c: New test.
+       * c-c++-common/goacc/mdc-2.c: New test.
+       * gcc.dg/goacc/mdc.C: New test.
+
 2019-12-19  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR target/92905
diff --git a/gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c b/gcc/testsuite/c-c++-common/goacc/deep-copy-arrayofstruct.c
new file mode 100644 (file)
index 0000000..d411bcf
--- /dev/null
@@ -0,0 +1,84 @@
+/* { dg-do compile } */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+typedef struct {
+  int *a;
+  int *b;
+  int *c;
+} mystruct;
+
+int main(int argc, char* argv[])
+{
+  const int N = 1024;
+  const int S = 32;
+  mystruct *m = (mystruct *) calloc (S, sizeof (*m));
+  int i, j;
+
+  for (i = 0; i < S; i++)
+    {
+      m[i].a = (int *) malloc (N * sizeof (int));
+      m[i].b = (int *) malloc (N * sizeof (int));
+      m[i].c = (int *) malloc (N * sizeof (int));
+    }
+
+  for (j = 0; j < S; j++)
+    for (i = 0; i < N; i++)
+      {
+       m[j].a[i] = 0;
+       m[j].b[i] = 0;
+       m[j].c[i] = 0;
+      }
+
+#pragma acc enter data copyin(m[0:1])
+
+  for (int i = 0; i < 99; i++)
+    {
+      int j, k;
+      for (k = 0; k < S; k++)
+#pragma acc parallel loop copy(m[k].a[0:N]) /* { dg-error "expected .\\\). before .\\\.. token" } */
+        for (j = 0; j < N; j++)
+          m[k].a[j]++;
+
+      for (k = 0; k < S; k++)
+#pragma acc parallel loop copy(m[k].b[0:N], m[k].c[5:N-10]) /* { dg-error "expected .\\\). before .\\\.. token" } */
+       /* { dg-error ".m. appears more than once in data clauses" "" { target c++ } .-1 } */
+       for (j = 0; j < N; j++)
+         {
+           m[k].b[j]++;
+           if (j > 5 && j < N - 5)
+             m[k].c[j]++;
+       }
+    }
+
+#pragma acc exit data copyout(m[0:1])
+
+  for (j = 0; j < S; j++)
+    {
+      for (i = 0; i < N; i++)
+       {
+         if (m[j].a[i] != 99)
+           abort ();
+         if (m[j].b[i] != 99)
+           abort ();
+         if (i > 5 && i < N-5)
+           {
+             if (m[j].c[i] != 99)
+               abort ();
+           }
+         else
+           {
+             if (m[j].c[i] != 0)
+               abort ();
+           }
+       }
+
+      free (m[j].a);
+      free (m[j].b);
+      free (m[j].c);
+    }
+  free (m);
+
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/mdc-1.c b/gcc/testsuite/c-c++-common/goacc/mdc-1.c
new file mode 100644 (file)
index 0000000..6c6a81e
--- /dev/null
@@ -0,0 +1,55 @@
+/* Test OpenACC's support for manual deep copy, including the attach
+   and detach clauses.  */
+
+/* { dg-do compile { target int32 } } */
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
+void
+t1 ()
+{
+  struct foo {
+    int *a, *b, c, d, *e;
+  } s;
+
+  int *a, *z;
+
+#pragma acc enter data copyin(s)
+  {
+#pragma acc data copy(s.a[0:10]) copy(z[0:10])
+    {
+      s.e = z;
+#pragma acc parallel loop attach(s.e)
+      for (int i = 0; i < 10; i++)
+        s.a[i] = s.e[i];
+
+
+      a = s.e;
+#pragma acc enter data attach(a)
+#pragma acc exit data detach(a)
+    }
+
+#pragma acc enter data copyin(a)
+#pragma acc acc enter data attach(s.e)
+#pragma acc exit data detach(s.e)
+
+#pragma acc data attach(s.e)
+    {
+    }
+#pragma acc exit data delete(a)
+
+#pragma acc exit data detach(a) finalize
+#pragma acc exit data detach(s.a) finalize
+  }
+}
+
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data map.to:s .len: 32.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_data map.tofrom:.z .len: 40.. map.struct:s .len: 1.. map.alloc:s.a .len: 8.. map.tofrom:._1 .len: 40.. map.attach:s.a .bias: 0.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_parallel map.attach:s.e .bias: 8.. map.tofrom:s .len: 32" 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data map.attach:a .bias: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data map.detach:a .bias: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data map.to:a .len: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data map.detach:s.e .bias: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_data map.attach:s.e .bias: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data map.release:a .len: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data finalize map.force_detach:a .bias: 8.." 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "pragma omp target oacc_enter_exit_data finalize map.force_detach:s.a .bias: 8.." 1 "omplower" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/mdc-2.c b/gcc/testsuite/c-c++-common/goacc/mdc-2.c
new file mode 100644 (file)
index 0000000..fae8667
--- /dev/null
@@ -0,0 +1,62 @@
+/* Test OpenACC's support for manual deep copy, including the attach
+   and detach clauses.  */
+
+void
+t1 ()
+{
+  struct foo {
+    int *a, *b, c, d, *e;
+  } s;
+
+  int *a, *z, scalar, **y;
+
+#pragma acc enter data copyin(s) detach(z) /* { dg-error ".detach. is not valid for" } */
+  {
+#pragma acc data copy(s.a[0:10]) copy(z[0:10])
+    {
+      s.e = z;
+#pragma acc parallel loop attach(s.e) detach(s.b) /* { dg-error ".detach. is not valid for" } */
+      for (int i = 0; i < 10; i++)
+        s.a[i] = s.e[i];
+
+      a = s.e;
+#pragma acc enter data attach(a) detach(s.c) /* { dg-error ".detach. is not valid for" } */
+#pragma acc exit data detach(a)
+    }
+
+#pragma acc enter data attach(z[:5]) /* { dg-error "expected single pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(z[:5]) /* { dg-error "expected single pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(z[1:]) /* { dg-error "expected single pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(z[1:]) /* { dg-error "expected single pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(z[:]) /* { dg-error "expected single pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(z[:]) /* { dg-error "expected single pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(z[3]) /* { dg-error "expected pointer in .attach. clause" } */
+#pragma acc exit data detach(z[3]) /* { dg-error "expected pointer in .detach. clause" } */
+
+#pragma acc acc enter data attach(s.e)
+#pragma acc exit data detach(s.e) attach(z) /* { dg-error ".attach. is not valid for" } */
+
+#pragma acc data attach(s.e)
+    {
+    }
+#pragma acc exit data delete(a) attach(s.a) /* { dg-error ".attach. is not valid for" } */
+
+#pragma acc enter data attach(scalar) /* { dg-error "expected pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(scalar) /* { dg-error "expected pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(s) /* { dg-error "expected pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(s) /* { dg-error "expected pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+  }
+
+#pragma acc enter data attach(y[10])
+#pragma acc exit data detach(y[10])
+}
diff --git a/gcc/testsuite/g++.dg/goacc/mdc.C b/gcc/testsuite/g++.dg/goacc/mdc.C
new file mode 100644 (file)
index 0000000..b3abab3
--- /dev/null
@@ -0,0 +1,68 @@
+/* Test OpenACC's support for manual deep copy, including the attach
+   and detach clauses.  */
+
+void
+t1 ()
+{
+  struct foo {
+    int *a, *b, c, d, *e;
+  } s;
+
+  struct foo& rs = s;
+  
+  int *a, *z, scalar, **y;
+  int* const &ra = a;
+  int* const &rz = z;
+  int& rscalar = scalar;
+  int** const &ry = y;
+
+#pragma acc enter data copyin(rs) detach(rz) /* { dg-error ".detach. is not valid for" } */
+  {
+#pragma acc data copy(rs.a[0:10]) copy(rz[0:10])
+    {
+      s.e = z;
+#pragma acc parallel loop attach(rs.e) detach(rs.b) /* { dg-error ".detach. is not valid for" } */
+      for (int i = 0; i < 10; i++)
+        s.a[i] = s.e[i];
+
+      a = s.e;
+#pragma acc enter data attach(ra) detach(rs.c) /* { dg-error ".detach. is not valid for" } */
+#pragma acc exit data detach(ra)
+    }
+
+#pragma acc enter data attach(rz[:5]) /* { dg-error "expected single pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(rz[:5]) /* { dg-error "expected single pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(rz[1:]) /* { dg-error "expected single pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(rz[1:]) /* { dg-error "expected single pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(rz[:]) /* { dg-error "expected single pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(rz[:]) /* { dg-error "expected single pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(rz[3]) /* { dg-error "expected pointer in .attach. clause" } */
+#pragma acc exit data detach(rz[3]) /* { dg-error "expected pointer in .detach. clause" } */
+
+#pragma acc acc enter data attach(rs.e)
+#pragma acc exit data detach(rs.e) attach(rz) /* { dg-error ".attach. is not valid for" } */
+
+#pragma acc data attach(rs.e)
+    {
+    }
+#pragma acc exit data delete(ra) attach(rs.a) /* { dg-error ".attach. is not valid for" } */
+
+#pragma acc enter data attach(rscalar) /* { dg-error "expected pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(rscalar) /* { dg-error "expected pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc enter data attach(rs) /* { dg-error "expected pointer in .attach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+#pragma acc exit data detach(rs) /* { dg-error "expected pointer in .detach. clause" } */
+/* { dg-error "has no data movement clause" "" { target *-*-* } .-1 } */
+  }
+
+#pragma acc enter data attach(ry[10])
+#pragma acc exit data detach(ry[10])
+}