]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Revert "Lambda capturing of pointers and references in target directives"
authorChung-Lin Tang <cltang@codesourcery.com>
Wed, 26 May 2021 11:11:39 +0000 (19:11 +0800)
committerChung-Lin Tang <cltang@codesourcery.com>
Sat, 29 May 2021 19:53:18 +0000 (03:53 +0800)
This reverts commit 9228d5a2ce3d0f5c19f2068b1ad42dd4ba4936c7.

gcc/cp/cp-tree.h
gcc/cp/lambda.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/gomp/target-lambda-1.C [deleted file]
libgomp/testsuite/libgomp.c++/target-lambda-1.C [deleted file]

index 33d87e9ee36f5a153843e6e04ff6b3790b4afff3..4ee5e0fd324495e0aace90adc35b78a57bbe6bc6 100644 (file)
@@ -7567,7 +7567,7 @@ extern void finish_lambda_function                (tree body);
 extern bool regenerated_lambda_fn_p            (tree);
 extern tree most_general_lambda                        (tree);
 extern tree finish_omp_target                  (location_t, tree, tree, bool);
-extern void finish_omp_target_clauses          (location_t, tree, tree *);
+extern void set_omp_target_this_expr           (tree);
 
 /* in tree.c */
 extern int cp_tree_operand_length              (const_tree);
index 16e2b4c18b4c966c492481dec2b65634da4e8675..23c1682893c4cd995dad9c5bf5ce0d4b213b1874 100644 (file)
@@ -845,6 +845,9 @@ lambda_expr_this_capture (tree lambda, int add_capture_p)
         type cast (_expr.cast_ 5.4) to the type of 'this'. [ The cast
         ensures that the transformed expression is an rvalue. ] */
       result = rvalue (result);
+
+      /* Acknowledge to OpenMP target that 'this' was referenced.  */
+      set_omp_target_this_expr (result);
     }
 
   return result;
index 916a96482d7a6feee98fe598a80e7d38e9a46f79..0927f29bfe7da5d1ebe1f6b01d5afacc7a343c6b 100644 (file)
@@ -42144,6 +42144,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
          keep_next_level (true);
          tree sb = begin_omp_structured_block (), ret;
          unsigned save = cp_parser_begin_omp_structured_block (parser);
+         set_omp_target_this_expr (NULL_TREE);
          switch (ccode)
            {
            case OMP_TEAMS:
@@ -42238,6 +42239,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
                                            "#pragma omp target", pragma_tok);
   c_omp_adjust_map_clauses (clauses, true);
   keep_next_level (true);
+  set_omp_target_this_expr (NULL_TREE);
   tree body = cp_parser_omp_structured_block (parser, if_p);
 
   finish_omp_target (pragma_tok->location, clauses, body, false);
index 59f5513fc79d726f487b2d5e134174d4443e0fc9..56217f86831db44a1d5aaf9fdc49b5478ef7f591 100644 (file)
@@ -18978,11 +18978,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
       t = copy_node (t);
       OMP_BODY (t) = stmt;
       OMP_CLAUSES (t) = tmp;
-
-      if (TREE_CODE (t) == OMP_TARGET)
-       finish_omp_target_clauses (EXPR_LOCATION (t), OMP_BODY (t),
-                                  &OMP_CLAUSES (t));
-
       if (TREE_CODE (t) == OMP_TARGET && OMP_TARGET_COMBINED (t))
        {
          tree teams = cp_walk_tree (&stmt, tsubst_find_omp_teams, NULL, NULL);
index 66b44ddb5903baf3394768822051229a070de1d7..2eeab999841d5a7306653f0e8c1b8a17631b8606 100644 (file)
@@ -61,6 +61,11 @@ static hash_map<tree, tree> *omp_private_member_map;
 static vec<tree> omp_private_member_vec;
 static bool omp_private_member_ignore_next;
 
+/* Used for OpenMP target region 'this' references.  */
+static tree omp_target_this_expr = NULL_TREE;
+
+static hash_map<tree, tree> omp_target_ptr_members_accessed;
+
 /* Deferred Access Checking Overview
    ---------------------------------
 
@@ -2075,6 +2080,7 @@ tree
 finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 {
   gcc_assert (TREE_CODE (decl) == FIELD_DECL);
+  tree orig_object = object;
   bool try_omp_private = !object && omp_private_member_map;
   tree ret;
 
@@ -2113,6 +2119,14 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
       return error_mark_node;
     }
 
+  if (orig_object == NULL_TREE)
+    {
+      tree this_expr = TREE_OPERAND (object, 0);
+
+      /* Acknowledge to OpenMP target that 'this' was referenced.  */
+      set_omp_target_this_expr (this_expr);
+    }
+
   if (current_class_ptr)
     TREE_USED (current_class_ptr) = 1;
   if (processing_template_decl)
@@ -2173,6 +2187,13 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
       if (v)
        ret = convert_from_reference (*v);
     }
+  else if (omp_target_this_expr
+          && TREE_TYPE (ret)
+          && POINTER_TYPE_P (TREE_TYPE (ret)))
+    {
+      if (omp_target_ptr_members_accessed.get (decl) == NULL)
+       omp_target_ptr_members_accessed.put (decl, ret);
+    }
 
   return ret;
 }
@@ -2914,6 +2935,9 @@ finish_this_expr (void)
       /* The keyword 'this' is a prvalue expression.  */
       result = rvalue (result);
 
+      /* Acknowledge to OpenMP target that 'this' was referenced.  */
+      set_omp_target_this_expr (result);
+
       return result;
     }
 
@@ -6573,6 +6597,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   bool order_seen = false;
   bool schedule_seen = false;
   bool oacc_async = false;
+  bool indirect_ref_p = false;
   bool indir_component_ref_p = false;
   tree last_iterators = NULL_TREE;
   bool last_iterators_remove = false;
@@ -7821,6 +7846,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
              indir_component_ref_p = true;
              STRIP_NOPS (t);
            }
+         indirect_ref_p = false;
+         if ((ort == C_ORT_ACC || ort == C_ORT_OMP)
+             && INDIRECT_REF_P (t))
+           {
+             t = TREE_OPERAND (t, 0);
+             indirect_ref_p = true;
+             STRIP_NOPS (t);
+           }
          if (TREE_CODE (t) == COMPONENT_REF
              && ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP
                  || ort == C_ORT_ACC)
@@ -7856,6 +7889,12 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                      break;
                    }
                  t = TREE_OPERAND (t, 0);
+                 if (INDIRECT_REF_P (t))
+                   {
+                     t = TREE_OPERAND (t, 0);
+                     indir_component_ref_p = true;
+                     STRIP_NOPS (t);
+                   }
                }
              if (remove)
                break;
@@ -7919,6 +7958,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
                       || (OMP_CLAUSE_MAP_KIND (c)
                           != GOMP_MAP_FIRSTPRIVATE_POINTER))
                   && !indir_component_ref_p
+                  && !indirect_ref_p
                   && !cxx_mark_addressable (t))
            remove = true;
          else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
@@ -8013,7 +8053,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
            }
          else
            {
-             bitmap_set_bit (&map_head, DECL_UID (t));
+             if (!indirect_ref_p && !indir_component_ref_p)
+               bitmap_set_bit (&map_head, DECL_UID (t));
              if (t != OMP_CLAUSE_DECL (c)
                  && TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
                bitmap_set_bit (&map_field_head, DECL_UID (t));
@@ -9038,126 +9079,26 @@ finish_omp_construct (enum tree_code code, tree body, tree clauses)
   return add_stmt (stmt);
 }
 
-/* Used to walk OpenMP target directive body.  */
-
-struct omp_target_walk_data
-{
-  tree current_object;
-  bool this_expr_accessed;
-
-  hash_map<tree, tree> ptr_members_accessed;
-  hash_set<tree> lambda_objects_accessed;
-
-  tree current_closure;
-  hash_set<tree> closure_vars_accessed;
-};
-
-static tree
-finish_omp_target_clauses_r (tree *tp, int *walk_subtrees, void *ptr)
+void
+set_omp_target_this_expr (tree this_val)
 {
-  tree t = *tp;
-  struct omp_target_walk_data *data = (struct omp_target_walk_data *) ptr;
-  tree current_object = data->current_object;
-  tree current_closure = data->current_closure;
+  omp_target_this_expr = this_val;
 
-  if (current_object)
-    {
-      tree this_expr = TREE_OPERAND (current_object, 0);
-
-      if (operand_equal_p (t, this_expr))
-       {
-         data->this_expr_accessed = true;
-         *walk_subtrees = 0;
-         return NULL_TREE;
-       }
-
-      if (TREE_CODE (t) == COMPONENT_REF
-         && POINTER_TYPE_P (TREE_TYPE (t))
-         && operand_equal_p (TREE_OPERAND (t, 0), current_object)
-         && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL)
-       {
-         data->this_expr_accessed = true;
-         tree fld = TREE_OPERAND (t, 1);
-         if (data->ptr_members_accessed.get (fld) == NULL)
-           {
-             if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
-               t = convert_from_reference (t);
-             data->ptr_members_accessed.put (fld, t);
-           }
-         *walk_subtrees = 0;
-         return NULL_TREE;
-       }
-    }
-
-  /* When the current_function_decl is a lambda function, the closure object
-     argument's type seems to not yet have fields layed out, so a recording
-     of DECL_VALUE_EXPRs during the target body walk seems the only way to
-     find them.  */
-  if (current_closure
-      && (TREE_CODE (t) == VAR_DECL
-         || TREE_CODE (t) == PARM_DECL
-         || TREE_CODE (t) == RESULT_DECL)
-      && DECL_HAS_VALUE_EXPR_P (t)
-      && TREE_CODE (DECL_VALUE_EXPR (t)) == COMPONENT_REF
-      && operand_equal_p (current_closure,
-                         TREE_OPERAND (DECL_VALUE_EXPR (t), 0)))
-    {
-      if (!data->closure_vars_accessed.contains (t))
-       data->closure_vars_accessed.add (t);
-      *walk_subtrees = 0;
-      return NULL_TREE;
-    }
-
-  if (TREE_TYPE(t) && LAMBDA_TYPE_P (TREE_TYPE (t)))
-    {
-      tree lt = TREE_TYPE (t);
-      gcc_assert (CLASS_TYPE_P (lt));
-
-      if (!data->lambda_objects_accessed.contains (t))
-       data->lambda_objects_accessed.add (t);
-      *walk_subtrees = 0;
-      return NULL_TREE;
-    }
-
-  return NULL_TREE;
+  if (omp_target_this_expr == NULL_TREE)
+    omp_target_ptr_members_accessed.empty ();
 }
 
-void
-finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
+tree
+finish_omp_target (location_t loc, tree clauses, tree body, bool combined_p)
 {
-  omp_target_walk_data data;
-  data.this_expr_accessed = false;
+  tree last_inserted_clause = NULL_TREE;
 
-  tree ct = current_nonlambda_class_type ();
-  if (ct)
+  if (omp_target_this_expr)
     {
-      tree object = maybe_dummy_object (ct, NULL);
-      object = maybe_resolve_dummy (object, true);
-      data.current_object = object;
-    }
-  else
-    data.current_object = NULL_TREE;
-
-  if (DECL_LAMBDA_FUNCTION_P (current_function_decl))
-    {
-      tree closure = DECL_ARGUMENTS (current_function_decl);
-      data.current_closure = build_indirect_ref (loc, closure, RO_UNARY_STAR);
-    }
-  else
-    data.current_closure = NULL_TREE;
-
-  cp_walk_tree_without_duplicates (&body, finish_omp_target_clauses_r, &data);
-
-  auto_vec<tree, 16> new_clauses;
-
-  if (data.this_expr_accessed)
-    {
-      tree omp_target_this_expr = TREE_OPERAND (data.current_object, 0);
-
       /* See if explicit user-specified map(this[:]) clause already exists.
         If not, we create an implicit map(tofrom:this[:1]) clause.  */
       tree *explicit_this_deref_map = NULL;
-      for (tree *c = clauses_ptr; *c; c = &OMP_CLAUSE_CHAIN (*c))
+      for (tree *c = &clauses; *c; c = &OMP_CLAUSE_CHAIN (*c))
        if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_MAP
            && TREE_CODE (OMP_CLAUSE_DECL (*c)) == INDIRECT_REF
            && operand_equal_p (TREE_OPERAND (OMP_CLAUSE_DECL (*c), 0),
@@ -9177,72 +9118,23 @@ finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
          OMP_CLAUSE_DECL (c)
            = build_indirect_ref (loc, closure, RO_UNARY_STAR);
          OMP_CLAUSE_SIZE (c)
-           = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure)));
-         new_clauses.safe_push (c);
-
-         tree closure_obj = OMP_CLAUSE_DECL (c);
-         tree closure_type = TREE_TYPE (closure_obj);
-
-         gcc_assert (LAMBDA_TYPE_P (closure_type)
-                     && CLASS_TYPE_P (closure_type));
+           = (processing_template_decl
+              ? NULL_TREE
+              : TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure))));
 
          tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
          OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
          OMP_CLAUSE_DECL (c2) = closure;
          OMP_CLAUSE_SIZE (c2) = size_zero_node;
-         new_clauses.safe_push (c2);
+         OMP_CLAUSE_CHAIN (c2) = clauses;
+         OMP_CLAUSE_CHAIN (c) = c2;
+         last_inserted_clause = c2;
+         clauses = c;
 
          STRIP_NOPS (omp_target_this_expr);
          gcc_assert (DECL_HAS_VALUE_EXPR_P (omp_target_this_expr));
          omp_target_this_expr = DECL_VALUE_EXPR (omp_target_this_expr);
 
-         for (hash_set<tree>::iterator i = data.closure_vars_accessed.begin ();
-              i != data.closure_vars_accessed.end (); ++i)
-           {
-             tree orig_decl = *i;
-             tree closure_expr = DECL_VALUE_EXPR (orig_decl);
-
-             if (TREE_CODE (TREE_TYPE (orig_decl)) == POINTER_TYPE)
-               {
-                 /* this-pointer is processed outside this loop.  */
-                 if (operand_equal_p (closure_expr, omp_target_this_expr))
-                   continue;
-
-                 tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
-                 OMP_CLAUSE_DECL (c)
-                   = build_indirect_ref (loc, closure_expr, RO_UNARY_STAR);
-                 OMP_CLAUSE_SIZE (c) = size_zero_node;
-                 OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
-                 new_clauses.safe_push (c);
-
-                 c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND
-                   (c, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION);
-                 OMP_CLAUSE_DECL (c) = closure_expr;
-                 OMP_CLAUSE_SIZE (c) = size_zero_node;
-                 new_clauses.safe_push (c);
-               }
-             else if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE)
-               {
-                 tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
-                 OMP_CLAUSE_DECL (c)
-                   = build1 (INDIRECT_REF,
-                             TREE_TYPE (TREE_TYPE (closure_expr)),
-                             closure_expr);
-                 OMP_CLAUSE_SIZE (c)
-                   = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure_expr)));
-                 new_clauses.safe_push (c);
-
-                 c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
-                 OMP_CLAUSE_DECL (c) = closure_expr;
-                 OMP_CLAUSE_SIZE (c) = size_zero_node;
-                 new_clauses.safe_push (c);
-               }
-           }
-
          if (explicit_this_deref_map)
            {
              /* Transform *this into *__closure->this in maps.  */
@@ -9257,13 +9149,12 @@ finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
              OMP_CLAUSE_DECL (nc) = omp_target_this_expr;
              OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_POINTER);
 
-             /* Unlink this two-map sequence away from the chain.  */
-             *explicit_this_deref_map = OMP_CLAUSE_CHAIN (nc);
-
              /* Move map(*__closure->this) map(always_pointer:__closure->this)
                 sequence to right after __closure map.  */
-             new_clauses.safe_push (this_map);
-             new_clauses.safe_push (nc);
+             *explicit_this_deref_map = OMP_CLAUSE_CHAIN (nc);
+             OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c2);
+             OMP_CLAUSE_CHAIN (c2) = this_map;
+             last_inserted_clause = nc;
            }
          else
            {
@@ -9272,7 +9163,9 @@ finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
              OMP_CLAUSE_DECL (c3)
                = build_indirect_ref (loc, omp_target_this_expr, RO_UNARY_STAR);
              OMP_CLAUSE_SIZE (c3)
-               = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (omp_target_this_expr)));
+               = (processing_template_decl
+                  ? NULL_TREE
+                  : TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (omp_target_this_expr))));
 
              tree c4 = build_omp_clause (loc, OMP_CLAUSE_MAP);
              OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_ALWAYS_POINTER);
@@ -9280,8 +9173,10 @@ finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
              OMP_CLAUSE_DECL (c4) = omp_target_this_expr;
              OMP_CLAUSE_SIZE (c4) = size_zero_node;
 
-             new_clauses.safe_push (c3);
-             new_clauses.safe_push (c4);
+             OMP_CLAUSE_CHAIN (c3) = c4;
+             OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (c2);
+             OMP_CLAUSE_CHAIN (c2) = c3;
+             last_inserted_clause = c4;
            }
        }
       else
@@ -9295,177 +9190,112 @@ finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr)
              OMP_CLAUSE_DECL (c)
                = build_indirect_ref (loc, omp_target_this_expr, RO_UNARY_STAR);
              OMP_CLAUSE_SIZE (c)
-               = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (omp_target_this_expr)));
+               = (processing_template_decl
+                  ? NULL_TREE
+                  : TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (omp_target_this_expr))));
 
              tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
              OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
              STRIP_NOPS (omp_target_this_expr);
              OMP_CLAUSE_DECL (c2) = omp_target_this_expr;
              OMP_CLAUSE_SIZE (c2) = size_zero_node;
-
-             new_clauses.safe_push (c);
-             new_clauses.safe_push (c2);
+             OMP_CLAUSE_CHAIN (c2) = clauses;
+             OMP_CLAUSE_CHAIN (c) = c2;
+             clauses = c;
+             last_inserted_clause = c2;
            }
        }
-
-      if (!data.ptr_members_accessed.is_empty ())
-       for (hash_map<tree, tree>::iterator i
-              = data.ptr_members_accessed.begin ();
-            i != data.ptr_members_accessed.end (); ++i)
-         {
-           /* For each referenced member that is of pointer or
-              reference-to-pointer type, create the equivalent of
-              map(alloc:this->ptr[:0]).  */
-           tree field_decl = (*i).first;
-           tree ptr_member = (*i).second;
-
-           for (tree c = *clauses_ptr; c; c = OMP_CLAUSE_CHAIN (c))
-             {
-               /* If map(this->ptr[:N] already exists, avoid creating another
-                  such map.  */
-               tree decl = OMP_CLAUSE_DECL (c);
-               if ((TREE_CODE (decl) == INDIRECT_REF
-                    || TREE_CODE (decl) == MEM_REF)
-                   && operand_equal_p (TREE_OPERAND (decl, 0),
-                                       ptr_member))
-                 goto next_ptr_member;
-             }
-
-           if (!cxx_mark_addressable (ptr_member))
-             gcc_unreachable ();
-
-           if (TREE_CODE (TREE_TYPE (field_decl)) == REFERENCE_TYPE)
-             {
-               /* For reference to pointers, we need to map the referenced
-                  pointer first for things to be correct.  */
-               tree ptr_member_type = TREE_TYPE (ptr_member);
-
-               /* Map pointer target as zero-length array section.  */
-               tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-               OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
-               OMP_CLAUSE_DECL (c)
-                 = build1 (INDIRECT_REF, TREE_TYPE (ptr_member_type), ptr_member);
-               OMP_CLAUSE_SIZE (c) = size_zero_node;
-               OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
-
-               /* Map pointer to zero-length array section.  */
-               tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
-               OMP_CLAUSE_SET_MAP_KIND
-                 (c2, GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION);
-               OMP_CLAUSE_DECL (c2) = ptr_member;
-               OMP_CLAUSE_SIZE (c2) = size_zero_node;
-
-               /* Attach reference-to-pointer field to pointer.  */
-               tree c3 = build_omp_clause (loc, OMP_CLAUSE_MAP);
-               OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH);
-               OMP_CLAUSE_DECL (c3) = TREE_OPERAND (ptr_member, 0);
-               OMP_CLAUSE_SIZE (c3) = size_zero_node;
-
-               new_clauses.safe_push (c);
-               new_clauses.safe_push (c2);
-               new_clauses.safe_push (c3);
-             }
-           else if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE)
-             {
-               /* Map pointer target as zero-length array section.  */
-               tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-               OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
-               OMP_CLAUSE_DECL (c)
-                 = build_indirect_ref (loc, ptr_member, RO_UNARY_STAR);
-               OMP_CLAUSE_SIZE (c) = size_zero_node;
-               OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
-
-               /* Attach zero-length array section to pointer.  */
-               tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
-               OMP_CLAUSE_SET_MAP_KIND
-                 (c2, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION);
-               OMP_CLAUSE_DECL (c2) = ptr_member;
-               OMP_CLAUSE_SIZE (c2) = size_zero_node;
-
-               new_clauses.safe_push (c);
-               new_clauses.safe_push (c2);
-             }
-           else
-             gcc_unreachable ();
-
-         next_ptr_member:
-           ;
-         }
+      omp_target_this_expr = NULL_TREE;
     }
 
-  if (!data.lambda_objects_accessed.is_empty ())
-    {
-      for (hash_set<tree>::iterator i = data.lambda_objects_accessed.begin ();
-          i != data.lambda_objects_accessed.end (); ++i)
-       {
-         tree lobj = *i;
-         tree lt = TREE_TYPE (lobj);
-         gcc_assert (LAMBDA_TYPE_P (lt) && CLASS_TYPE_P (lt));
+  if (last_inserted_clause && !omp_target_ptr_members_accessed.is_empty ())
+    for (hash_map<tree, tree>::iterator i
+          = omp_target_ptr_members_accessed.begin ();
+        i != omp_target_ptr_members_accessed.end (); ++i)
+      {
+       /* For each referenced member that is of pointer or reference-to-pointer
+          type, create the equivalent of map(alloc:this->ptr[:0]).  */
+       tree field_decl = (*i).first;
+       tree ptr_member = (*i).second;
 
-         tree lc = build_omp_clause (loc, OMP_CLAUSE_MAP);
-         OMP_CLAUSE_SET_MAP_KIND (lc, GOMP_MAP_TO);
-         OMP_CLAUSE_DECL (lc) = lobj;
-         OMP_CLAUSE_SIZE (lc) = TYPE_SIZE_UNIT (lt);
-         new_clauses.truncate (0);
-         new_clauses.safe_push (lc);
+       for (tree nc = OMP_CLAUSE_CHAIN (last_inserted_clause);
+            nc != NULL_TREE; nc = OMP_CLAUSE_CHAIN (nc))
+         {
+           /* If map(this->ptr[:N] already exists, avoid creating another
+              such map.  */
+           tree decl = OMP_CLAUSE_DECL (nc);
+           if ((TREE_CODE (decl) == INDIRECT_REF
+                || TREE_CODE (decl) == MEM_REF)
+               && operand_equal_p (TREE_OPERAND (decl, 0),
+                                   ptr_member))
+             goto next_ptr_member;
+         }
 
-         for (tree fld = TYPE_FIELDS (lt); fld; fld = DECL_CHAIN (fld))
-           {
-             if (TREE_CODE (TREE_TYPE (fld)) == POINTER_TYPE)
-               {
-                 tree exp = build3 (COMPONENT_REF, TREE_TYPE (fld),
-                                    lobj, fld, NULL_TREE);
-                 tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
-                 OMP_CLAUSE_DECL (c)
-                   = build_indirect_ref (loc, exp, RO_UNARY_STAR);
-                 OMP_CLAUSE_SIZE (c) = size_zero_node;
-                 OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
-                 new_clauses.safe_push (c);
-
-                 c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND
-                   (c, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION);
-                 OMP_CLAUSE_DECL (c) = exp;
-                 OMP_CLAUSE_SIZE (c) = size_zero_node;
-                 new_clauses.safe_push (c);
-               }
-             else if (TREE_CODE (TREE_TYPE (fld)) == REFERENCE_TYPE)
-               {
-                 tree exp = build3 (COMPONENT_REF, TREE_TYPE (fld),
-                                    lobj, fld, NULL_TREE);
-                 tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
-                 OMP_CLAUSE_DECL (c)
-                   = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
-                 OMP_CLAUSE_SIZE (c)
-                   = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (exp)));
-                 new_clauses.safe_push (c);
-
-                 c = build_omp_clause (loc, OMP_CLAUSE_MAP);
-                 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
-                 OMP_CLAUSE_DECL (c) = exp;
-                 OMP_CLAUSE_SIZE (c) = size_zero_node;
-                 new_clauses.safe_push (c);
-               }
-           }
-       }
-    }
+       if (!cxx_mark_addressable (ptr_member))
+         gcc_unreachable ();
 
-  tree c = *clauses_ptr;
-  for (int i = new_clauses.length () - 1; i >= 0; i--)
-    {
-      OMP_CLAUSE_CHAIN (new_clauses[i]) = c;
-      c = new_clauses[i];
-    }
-  *clauses_ptr = c;
-}
+       if (TREE_CODE (TREE_TYPE (field_decl)) == REFERENCE_TYPE)
+         {
+           /* For reference to pointers, we need to map the referenced pointer
+              first for things to be correct.  */
+           tree ptr_member_type = TREE_TYPE (ptr_member);
+
+           /* Map pointer target as zero-length array section.  */
+           tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+           OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
+           OMP_CLAUSE_DECL (c)
+             = build1 (INDIRECT_REF, TREE_TYPE (ptr_member_type), ptr_member);
+           OMP_CLAUSE_SIZE (c) = size_zero_node;
+           OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+
+           /* Map pointer to zero-length array section.  */
+           tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+           OMP_CLAUSE_SET_MAP_KIND
+             (c2, GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION);
+           OMP_CLAUSE_DECL (c2) = ptr_member;
+           OMP_CLAUSE_SIZE (c2) = size_zero_node;
+
+           /* Attach reference-to-pointer field to pointer.  */
+           tree c3 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+           OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH);
+           OMP_CLAUSE_DECL (c3) = TREE_OPERAND (ptr_member, 0);
+           OMP_CLAUSE_SIZE (c3) = size_zero_node;
+
+           OMP_CLAUSE_CHAIN (c) = c2;
+           OMP_CLAUSE_CHAIN (c2) = c3;
+           OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last_inserted_clause);
+
+           OMP_CLAUSE_CHAIN (last_inserted_clause) = c;
+           last_inserted_clause = c3;
+         }
+       else if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE)
+         {
+           /* Map pointer target as zero-length array section.  */
+           tree c = build_omp_clause (loc, OMP_CLAUSE_MAP);
+           OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC);
+           OMP_CLAUSE_DECL (c)
+             = build_indirect_ref (loc, ptr_member, RO_UNARY_STAR);
+           OMP_CLAUSE_SIZE (c) = size_zero_node;
+           OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1;
+
+           /* Attach zero-length array section to pointer.  */
+           tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
+           OMP_CLAUSE_SET_MAP_KIND
+             (c2, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION);
+           OMP_CLAUSE_DECL (c2) = ptr_member;
+           OMP_CLAUSE_SIZE (c2) = size_zero_node;
+
+           OMP_CLAUSE_CHAIN (c) = c2;
+           OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last_inserted_clause);
+           OMP_CLAUSE_CHAIN (last_inserted_clause) = c;
+           last_inserted_clause = c2;
+         }
+       else
+         gcc_unreachable ();
 
-tree
-finish_omp_target (location_t loc, tree clauses, tree body, bool combined_p)
-{
-  if (!processing_template_decl)
-    finish_omp_target_clauses (loc, body, &clauses);
+      next_ptr_member:
+       ;
+      }
 
   tree stmt = make_node (OMP_TARGET);
   TREE_TYPE (stmt) = void_type_node;
diff --git a/gcc/testsuite/g++.dg/gomp/target-lambda-1.C b/gcc/testsuite/g++.dg/gomp/target-lambda-1.C
deleted file mode 100644 (file)
index 7dceef8..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// We use 'auto' without a function return type, so specify dialect here
-// { dg-additional-options "-std=c++14 -fdump-tree-gimple" }
-#include <cstdlib>
-#include <cstring>
-
-template <typename L>
-void
-omp_target_loop (int begin, int end, L loop)
-{
-  #pragma omp target teams distribute parallel for
-  for (int i = begin; i < end; i++)
-    loop (i);
-}
-
-struct S
-{
-  int a, len;
-  int *ptr;
-
-  auto merge_data_func (int *iptr, int &b)
-  {
-    auto fn = [=](void) -> bool
-      {
-       bool mapped;
-       #pragma omp target map(from:mapped)
-       {
-         mapped = (ptr != NULL && iptr != NULL);
-         if (mapped)
-           {
-             for (int i = 0; i < len; i++)
-               ptr[i] += a + b + iptr[i];
-           }
-       }
-       return mapped;
-      };
-    return fn;
-  }
-};
-
-int x = 1;
-
-int main (void)
-{
-  const int N = 10;
-  int *data1 = new int[N];
-  int *data2 = new int[N];
-  memset (data1, 0xab, sizeof (int) * N);
-  memset (data1, 0xcd, sizeof (int) * N);
-
-  int val = 1;
-  int &valref = val;
-  #pragma omp target enter data map(alloc: data1[:N], data2[:N])
-
-  omp_target_loop (0, N, [=](int i) { data1[i] = val; });
-  omp_target_loop (0, N, [=](int i) { data2[i] = valref + 1; });
-
-  #pragma omp target update from(data1[:N], data2[:N])
-
-  for (int i = 0; i < N; i++)
-    {
-      if (data1[i] != 1) abort ();
-      if (data2[i] != 2) abort ();
-    }
-
-  #pragma omp target exit data map(delete: data1[:N], data2[:N])
-
-  int b = 8;
-  S s = { 4, N, data1 };
-  auto f = s.merge_data_func (data2, b);
-
-  if (f ()) abort ();
-
-  #pragma omp target enter data map(to: data1[:N])
-  if (f ()) abort ();
-
-  #pragma omp target enter data map(to: data2[:N])
-  if (!f ()) abort ();
-
-  #pragma omp target exit data map(from: data1[:N], data2[:N])
-
-  for (int i = 0; i < N; i++)
-    {
-      if (data1[i] != 0xf) abort ();
-      if (data2[i] != 2) abort ();
-    }
-
-  return 0;
-}
-
-/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(to:\*__closure \[len: [0-9]+\]\) map\(firstprivate:__closure \[pointer assign, bias: 0\]\) map\(attach_zero_length_array_section:__closure->__iptr \[bias: 0\]\) map\(struct:\*__closure \[len: 1\]\) map\(alloc:__closure->__this \[len: [0-9]+\]\) map\(tofrom:\*_[0-9]+ \[len: [0-9]+\]\) map\(always_pointer:__closure->__this \[pointer assign, bias: 0\]\) map\(attach_zero_length_array_section:_[0-9]+->ptr \[bias: 0\]\) map\(from:mapped \[len: [0-9]+\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) firstprivate\(b\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:iptr \[pointer assign, bias: 0\]\) map\(alloc:MEM.* \[len: 0\]\) map\(firstprivate:this \[pointer assign, bias: 0\]\)} "gimple" } } */
-
-/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(to:loop \[len: [0-9]+\]\) map\(attach_zero_length_array_section:loop\.__data1 \[bias: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) firstprivate\(end\) firstprivate\(begin\)} "gimple" } } */
-
-/* { dg-final { scan-tree-dump {#pragma omp target num_teams.* map\(to:loop \[len: [0-9]+\]\) map\(attach_zero_length_array_section:loop\.__data2 \[bias: 0\]\) map\(alloc:\*_[0-9]+ \[len: 0\]\) firstprivate\(end\) firstprivate\(begin\)} "gimple" } } */
diff --git a/libgomp/testsuite/libgomp.c++/target-lambda-1.C b/libgomp/testsuite/libgomp.c++/target-lambda-1.C
deleted file mode 100644 (file)
index 06c6470..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-#include <cstdlib>
-#include <cstring>
-
-template <typename L>
-void
-omp_target_loop (int begin, int end, L loop)
-{
-  #pragma omp target teams distribute parallel for
-  for (int i = begin; i < end; i++)
-    loop (i);
-}
-
-struct S
-{
-  int a, len;
-  int *ptr;
-
-  auto merge_data_func (int *iptr, int &b)
-  {
-    auto fn = [=](void) -> bool
-      {
-       bool mapped;
-       #pragma omp target map(from:mapped)
-       {
-         mapped = (ptr != NULL && iptr != NULL);
-         if (mapped)
-           {
-             for (int i = 0; i < len; i++)
-               ptr[i] += a + b + iptr[i];
-           }
-       }
-       return mapped;
-      };
-    return fn;
-  }
-};
-
-int x = 1;
-
-int main (void)
-{
-  const int N = 10;
-  int *data1 = new int[N];
-  int *data2 = new int[N];
-  memset (data1, 0xab, sizeof (int) * N);
-  memset (data1, 0xcd, sizeof (int) * N);
-
-  int val = 1;
-  int &valref = val;
-  #pragma omp target enter data map(alloc: data1[:N], data2[:N])
-
-  omp_target_loop (0, N, [=](int i) { data1[i] = val; });
-  omp_target_loop (0, N, [=](int i) { data2[i] = valref + 1; });
-
-  #pragma omp target update from(data1[:N], data2[:N])
-
-  for (int i = 0; i < N; i++)
-    {
-      if (data1[i] != 1) abort ();
-      if (data2[i] != 2) abort ();
-    }
-
-  #pragma omp target exit data map(delete: data1[:N], data2[:N])
-
-  int b = 8;
-  S s = { 4, N, data1 };
-  auto f = s.merge_data_func (data2, b);
-
-  if (f ()) abort ();
-
-  #pragma omp target enter data map(to: data1[:N])
-  if (f ()) abort ();
-
-  #pragma omp target enter data map(to: data2[:N])
-  if (!f ()) abort ();
-
-  #pragma omp target exit data map(from: data1[:N], data2[:N])
-
-  for (int i = 0; i < N; i++)
-    {
-      if (data1[i] != 0xf) abort ();
-      if (data2[i] != 2) abort ();
-    }
-
-  return 0;
-}