OSDN Git Service

* gcc.dg/20020201-1.c: Remove declarations for exit, abort,
[pf3gnuchains/gcc-fork.git] / gcc / omp-low.c
index dc61c0b..4247a80 100644 (file)
@@ -3,7 +3,7 @@
    marshalling to implement data sharing and copying clauses.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
-   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -851,6 +851,19 @@ omp_copy_decl_1 (tree var, omp_context *ctx)
   return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
 }
 
+/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
+   as appropriate.  */
+static tree
+omp_build_component_ref (tree obj, tree field)
+{
+  tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
+  if (TREE_THIS_VOLATILE (field))
+    TREE_THIS_VOLATILE (ret) |= 1;
+  if (TREE_READONLY (field))
+    TREE_READONLY (ret) |= 1;
+  return ret;
+}
+
 /* Build tree nodes to access the field for VAR on the receiver side.  */
 
 static tree
@@ -865,7 +878,7 @@ build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
     field = x;
 
   x = build_simple_mem_ref (ctx->receiver_decl);
-  x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
+  x = omp_build_component_ref (x, field);
   if (by_ref)
     x = build_simple_mem_ref (x);
 
@@ -915,8 +928,7 @@ static tree
 build_sender_ref (tree var, omp_context *ctx)
 {
   tree field = lookup_sfield (var, ctx);
-  return build3 (COMPONENT_REF, TREE_TYPE (field),
-                ctx->sender_decl, field, NULL);
+  return omp_build_component_ref (ctx->sender_decl, field);
 }
 
 /* Add a new field for VAR inside the structure CTX->SENDER_DECL.  */
@@ -1248,7 +1260,7 @@ finalize_task_copyfn (gimple task_stmt)
   old_fn = current_function_decl;
   push_cfun (child_cfun);
   current_function_decl = child_fn;
-  bind = gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
+  bind = gimplify_body (child_fn, false);
   seq = gimple_seq_alloc ();
   gimple_seq_add_stmt (&seq, bind);
   new_seq = maybe_catch_exception (seq);
@@ -1811,8 +1823,8 @@ scan_omp_single (gimple stmt, omp_context *outer_ctx)
 
 
 /* Check OpenMP nesting restrictions.  */
-static void
-check_omp_nesting_restrictions (gimple  stmt, omp_context *ctx)
+static bool
+check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
 {
   switch (gimple_code (stmt))
     {
@@ -1831,17 +1843,19 @@ check_omp_nesting_restrictions (gimple  stmt, omp_context *ctx)
          case GIMPLE_OMP_TASK:
            if (is_gimple_call (stmt))
              {
-               warning (0, "barrier region may not be closely nested inside "
-                           "of work-sharing, critical, ordered, master or "
-                           "explicit task region");
-               return;
+               error_at (gimple_location (stmt),
+                         "barrier region may not be closely nested inside "
+                         "of work-sharing, critical, ordered, master or "
+                         "explicit task region");
+               return false;
              }
-           warning (0, "work-sharing region may not be closely nested inside "
-                       "of work-sharing, critical, ordered, master or explicit "
-                       "task region");
-           return;
+           error_at (gimple_location (stmt),
+                     "work-sharing region may not be closely nested inside "
+                     "of work-sharing, critical, ordered, master or explicit "
+                     "task region");
+           return false;
          case GIMPLE_OMP_PARALLEL:
-           return;
+           return true;
          default:
            break;
          }
@@ -1854,11 +1868,12 @@ check_omp_nesting_restrictions (gimple  stmt, omp_context *ctx)
          case GIMPLE_OMP_SECTIONS:
          case GIMPLE_OMP_SINGLE:
          case GIMPLE_OMP_TASK:
-           warning (0, "master region may not be closely nested inside "
-                       "of work-sharing or explicit task region");
-           return;
+           error_at (gimple_location (stmt),
+                     "master region may not be closely nested inside "
+                     "of work-sharing or explicit task region");
+           return false;
          case GIMPLE_OMP_PARALLEL:
-           return;
+           return true;
          default:
            break;
          }
@@ -1869,17 +1884,22 @@ check_omp_nesting_restrictions (gimple  stmt, omp_context *ctx)
          {
          case GIMPLE_OMP_CRITICAL:
          case GIMPLE_OMP_TASK:
-           warning (0, "ordered region may not be closely nested inside "
-                       "of critical or explicit task region");
-           return;
+           error_at (gimple_location (stmt),
+                     "ordered region may not be closely nested inside "
+                     "of critical or explicit task region");
+           return false;
          case GIMPLE_OMP_FOR:
            if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
                                 OMP_CLAUSE_ORDERED) == NULL)
-             warning (0, "ordered region must be closely nested inside "
+             {
+               error_at (gimple_location (stmt),
+                         "ordered region must be closely nested inside "
                          "a loop region with an ordered clause");
-           return;
+               return false;
+             }
+           return true;
          case GIMPLE_OMP_PARALLEL:
-           return;
+           return true;
          default:
            break;
          }
@@ -1890,14 +1910,16 @@ check_omp_nesting_restrictions (gimple  stmt, omp_context *ctx)
            && (gimple_omp_critical_name (stmt)
                == gimple_omp_critical_name (ctx->stmt)))
          {
-           warning (0, "critical region may not be nested inside a critical "
-                       "region with the same name");
-           return;
+           error_at (gimple_location (stmt),
+                     "critical region may not be nested inside a critical "
+                     "region with the same name");
+           return false;
          }
       break;
     default:
       break;
     }
+  return true;
 }
 
 
@@ -1968,14 +1990,20 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
   /* Check the OpenMP nesting restrictions.  */
   if (ctx != NULL)
     {
+      bool remove = false;
       if (is_gimple_omp (stmt))
-       check_omp_nesting_restrictions (stmt, ctx);
+       remove = !check_omp_nesting_restrictions (stmt, ctx);
       else if (is_gimple_call (stmt))
        {
          tree fndecl = gimple_call_fndecl (stmt);
          if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
              && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
-           check_omp_nesting_restrictions (stmt, ctx);
+           remove = !check_omp_nesting_restrictions (stmt, ctx);
+       }
+      if (remove)
+       {
+         stmt = gimple_build_nop ();
+         gsi_replace (gsi, stmt, false);
        }
     }
 
@@ -4664,6 +4692,9 @@ expand_omp_for (struct omp_region *region)
     {
       int fn_index, start_ix, next_ix;
 
+      if (fd.chunk_size == NULL
+         && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
+       fd.chunk_size = integer_zero_node;
       gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
       fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
                  ? 3 : fd.sched_kind;
@@ -4727,45 +4758,40 @@ expand_omp_sections (struct omp_region *region)
   unsigned i, casei;
   bool exit_reachable = region->cont != NULL;
 
-  gcc_assert (exit_reachable == (region->exit != NULL));
+  gcc_assert (region->exit != NULL);
   entry_bb = region->entry;
   l0_bb = single_succ (entry_bb);
   l1_bb = region->cont;
   l2_bb = region->exit;
-  if (exit_reachable)
+  if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
+    l2 = gimple_block_label (l2_bb);
+  else
     {
-      if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
-       l2 = gimple_block_label (l2_bb);
+      /* This can happen if there are reductions.  */
+      len = EDGE_COUNT (l0_bb->succs);
+      gcc_assert (len > 0);
+      e = EDGE_SUCC (l0_bb, len - 1);
+      si = gsi_last_bb (e->dest);
+      l2 = NULL_TREE;
+      if (gsi_end_p (si)
+          || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
+       l2 = gimple_block_label (e->dest);
       else
-       {
-         /* This can happen if there are reductions.  */
-         len = EDGE_COUNT (l0_bb->succs);
-         gcc_assert (len > 0);
-         e = EDGE_SUCC (l0_bb, len - 1);
-         si = gsi_last_bb (e->dest);
-         l2 = NULL_TREE;
-         if (gsi_end_p (si)
-             || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
-           l2 = gimple_block_label (e->dest);
-         else
-           FOR_EACH_EDGE (e, ei, l0_bb->succs)
+       FOR_EACH_EDGE (e, ei, l0_bb->succs)
+         {
+           si = gsi_last_bb (e->dest);
+           if (gsi_end_p (si)
+               || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
              {
-               si = gsi_last_bb (e->dest);
-               if (gsi_end_p (si)
-                   || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
-                 {
-                   l2 = gimple_block_label (e->dest);
-                   break;
-                 }
+               l2 = gimple_block_label (e->dest);
+               break;
              }
-       }
-      default_bb = create_empty_bb (l1_bb->prev_bb);
+         }
     }
+  if (exit_reachable)
+    default_bb = create_empty_bb (l1_bb->prev_bb);
   else
-    {
-      default_bb = create_empty_bb (l0_bb);
-      l2 = gimple_block_label (default_bb);
-    }
+    default_bb = create_empty_bb (l0_bb);
 
   /* We will build a switch() with enough cases for all the
      GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
@@ -4818,13 +4844,9 @@ expand_omp_sections (struct omp_region *region)
       vnext = NULL_TREE;
     }
 
-  i = 0;
-  if (exit_reachable)
-    {
-      t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
-      VEC_quick_push (tree, label_vec, t);
-      i++;
-    }
+  t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
+  VEC_quick_push (tree, label_vec, t);
+  i = 1;
 
   /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR.  */
   for (inner = region->inner, casei = 1;
@@ -4894,18 +4916,18 @@ expand_omp_sections (struct omp_region *region)
       gsi_remove (&si, true);
 
       single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
-
-      /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
-      si = gsi_last_bb (l2_bb);
-      if (gimple_omp_return_nowait_p (gsi_stmt (si)))
-       t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
-      else
-       t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
-      stmt = gimple_build_call (t, 0);
-      gsi_insert_after (&si, stmt, GSI_SAME_STMT);
-      gsi_remove (&si, true);
     }
 
+  /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
+  si = gsi_last_bb (l2_bb);
+  if (gimple_omp_return_nowait_p (gsi_stmt (si)))
+    t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
+  else
+    t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
+  stmt = gimple_build_call (t, 0);
+  gsi_insert_after (&si, stmt, GSI_SAME_STMT);
+  gsi_remove (&si, true);
+
   set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
 }
 
@@ -4977,25 +4999,125 @@ expand_omp_synch (struct omp_region *region)
    operation as a normal volatile load.  */
 
 static bool
-expand_omp_atomic_load (basic_block load_bb, tree addr, tree loaded_val)
+expand_omp_atomic_load (basic_block load_bb, tree addr,
+                       tree loaded_val, int index)
 {
-  /* FIXME */
-  (void) load_bb;
-  (void) addr;
-  (void) loaded_val;
-  return false;
+  enum built_in_function tmpbase;
+  gimple_stmt_iterator gsi;
+  basic_block store_bb;
+  location_t loc;
+  gimple stmt;
+  tree decl, call, type, itype;
+
+  gsi = gsi_last_bb (load_bb);
+  stmt = gsi_stmt (gsi);
+  gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
+  loc = gimple_location (stmt);
+
+  /* ??? If the target does not implement atomic_load_optab[mode], and mode
+     is smaller than word size, then expand_atomic_load assumes that the load
+     is atomic.  We could avoid the builtin entirely in this case.  */
+
+  tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
+  decl = builtin_decl_explicit (tmpbase);
+  if (decl == NULL_TREE)
+    return false;
+
+  type = TREE_TYPE (loaded_val);
+  itype = TREE_TYPE (TREE_TYPE (decl));
+
+  call = build_call_expr_loc (loc, decl, 2, addr,
+                             build_int_cst (NULL, MEMMODEL_RELAXED));
+  if (!useless_type_conversion_p (type, itype))
+    call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
+  call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
+
+  force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
+  gsi_remove (&gsi, true);
+
+  store_bb = single_succ (load_bb);
+  gsi = gsi_last_bb (store_bb);
+  gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
+  gsi_remove (&gsi, true);
+
+  if (gimple_in_ssa_p (cfun))
+    update_ssa (TODO_update_ssa_no_phi);
+
+  return true;
 }
 
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
    operation as a normal volatile store.  */
 
 static bool
-expand_omp_atomic_store (basic_block load_bb, tree addr)
+expand_omp_atomic_store (basic_block load_bb, tree addr,
+                        tree loaded_val, tree stored_val, int index)
 {
-  /* FIXME */
-  (void) load_bb;
-  (void) addr;
-  return false;
+  enum built_in_function tmpbase;
+  gimple_stmt_iterator gsi;
+  basic_block store_bb = single_succ (load_bb);
+  location_t loc;
+  gimple stmt;
+  tree decl, call, type, itype;
+  enum machine_mode imode;
+  bool exchange;
+
+  gsi = gsi_last_bb (load_bb);
+  stmt = gsi_stmt (gsi);
+  gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
+
+  /* If the load value is needed, then this isn't a store but an exchange.  */
+  exchange = gimple_omp_atomic_need_value_p (stmt);
+
+  gsi = gsi_last_bb (store_bb);
+  stmt = gsi_stmt (gsi);
+  gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
+  loc = gimple_location (stmt);
+
+  /* ??? If the target does not implement atomic_store_optab[mode], and mode
+     is smaller than word size, then expand_atomic_store assumes that the store
+     is atomic.  We could avoid the builtin entirely in this case.  */
+
+  tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
+  tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
+  decl = builtin_decl_explicit (tmpbase);
+  if (decl == NULL_TREE)
+    return false;
+
+  type = TREE_TYPE (stored_val);
+
+  /* Dig out the type of the function's second argument.  */
+  itype = TREE_TYPE (decl);
+  itype = TYPE_ARG_TYPES (itype);
+  itype = TREE_CHAIN (itype);
+  itype = TREE_VALUE (itype);
+  imode = TYPE_MODE (itype);
+
+  if (exchange && !can_atomic_exchange_p (imode, true))
+    return false;
+
+  if (!useless_type_conversion_p (itype, type))
+    stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
+  call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
+                             build_int_cst (NULL, MEMMODEL_RELAXED));
+  if (exchange)
+    {
+      if (!useless_type_conversion_p (type, itype))
+       call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
+      call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
+    }
+
+  force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
+  gsi_remove (&gsi, true);
+
+  /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above.  */
+  gsi = gsi_last_bb (load_bb);
+  gsi_remove (&gsi, true);
+
+  if (gimple_in_ssa_p (cfun))
+    update_ssa (TODO_update_ssa_no_phi);
+
+  return true;
 }
 
 /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
@@ -5335,7 +5457,7 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
    loaded_val = *addr;
 
    and replace
-   GIMPLE_OMP_ATOMIC_ATORE (stored_val)  with
+   GIMPLE_OMP_ATOMIC_STORE (stored_val)  with
    *addr = stored_val;
 */
 
@@ -5403,33 +5525,30 @@ expand_omp_atomic (struct omp_region *region)
       /* __sync builtins require strict data alignment.  */
       if (exact_log2 (align) >= index)
        {
-         /* Atomic load.  FIXME: have some target hook signalize what loads
-            are actually atomic?  */
+         /* Atomic load.  */
          if (loaded_val == stored_val
              && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
                  || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
              && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
-             && expand_omp_atomic_load (load_bb, addr, loaded_val))
+             && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
            return;
 
-         /* Atomic store.  FIXME: have some target hook signalize what
-            stores are actually atomic?  */
+         /* Atomic store.  */
          if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
               || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
              && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
              && store_bb == single_succ (load_bb)
              && first_stmt (store_bb) == store
-             && expand_omp_atomic_store (load_bb, addr))
+             && expand_omp_atomic_store (load_bb, addr, loaded_val,
+                                         stored_val, index))
            return;
 
          /* When possible, use specialized atomic update functions.  */
          if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
-             && store_bb == single_succ (load_bb))
-           {
-             if (expand_omp_atomic_fetch_op (load_bb, addr,
-                                             loaded_val, stored_val, index))
-               return;
-           }
+             && store_bb == single_succ (load_bb)
+             && expand_omp_atomic_fetch_op (load_bb, addr,
+                                            loaded_val, stored_val, index))
+           return;
 
          /* If we don't have specialized __sync builtins, try and implement
             as a compare and swap loop.  */
@@ -6434,7 +6553,7 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
          sf = (tree) n->value;
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
          src = build_simple_mem_ref_loc (loc, sarg);
-         src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
+         src = omp_build_component_ref (src, sf);
          t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
          append_to_statement_list (t, &list);
        }
@@ -6457,9 +6576,9 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
        if (tcctx.cb.decl_map)
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
        src = build_simple_mem_ref_loc (loc, sarg);
-       src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
+       src = omp_build_component_ref (src, sf);
        dst = build_simple_mem_ref_loc (loc, arg);
-       dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
+       dst = omp_build_component_ref (dst, f);
        t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
        append_to_statement_list (t, &list);
        break;
@@ -6480,14 +6599,14 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
            if (tcctx.cb.decl_map)
              sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
            src = build_simple_mem_ref_loc (loc, sarg);
-           src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
+           src = omp_build_component_ref (src, sf);
            if (use_pointer_for_field (decl, NULL) || is_reference (decl))
              src = build_simple_mem_ref_loc (loc, src);
          }
        else
          src = decl;
        dst = build_simple_mem_ref_loc (loc, arg);
-       dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
+       dst = omp_build_component_ref (dst, f);
        t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
        append_to_statement_list (t, &list);
        break;
@@ -6506,14 +6625,14 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
            if (tcctx.cb.decl_map)
              sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
            src = build_simple_mem_ref_loc (loc, sarg);
-           src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
+           src = omp_build_component_ref (src, sf);
            if (use_pointer_for_field (decl, NULL))
              src = build_simple_mem_ref_loc (loc, src);
          }
        else
          src = decl;
        dst = build_simple_mem_ref_loc (loc, arg);
-       dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
+       dst = omp_build_component_ref (dst, f);
        t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
        append_to_statement_list (t, &list);
        break;
@@ -6545,10 +6664,10 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
          sf = (tree) n->value;
          sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
          src = build_simple_mem_ref_loc (loc, sarg);
-         src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL);
+         src = omp_build_component_ref (src, sf);
          src = build_simple_mem_ref_loc (loc, src);
          dst = build_simple_mem_ref_loc (loc, arg);
-         dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL);
+         dst = omp_build_component_ref (dst, f);
          t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
          append_to_statement_list (t, &list);
          n = splay_tree_lookup (ctx->field_map,
@@ -6556,7 +6675,7 @@ create_task_copyfn (gimple task_stmt, omp_context *ctx)
          df = (tree) n->value;
          df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
          ptr = build_simple_mem_ref_loc (loc, arg);
-         ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL);
+         ptr = omp_build_component_ref (ptr, df);
          t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
                      build_fold_addr_expr_loc (loc, dst));
          append_to_statement_list (t, &list);