Hi!

Copyprivate clause has following restriction (in 2.5, 3.0, 3.1 and 4.0):
"All list items that appear in the copyprivate clause must be either
threadprivate or private in the enclosing context."
but we weren't diagnosing it and even in crayptr2.f90 testcase violated it.

Fixed thusly, regtested on x86_64-linux, committed to trunk and 4.8.

2013-12-12  Jakub Jelinek  <ja...@redhat.com>

        PR libgomp/59467
        * gimplify.c (omp_check_private): Add copyprivate argument, if it
        is true, don't check omp_privatize_by_reference.
        (gimplify_scan_omp_clauses): For OMP_CLAUSE_COPYPRIVATE verify
        decl is private in outer context.  Adjust omp_check_private caller.

        * gfortran.dg/gomp/pr59467.f90: New test.
        * c-c++-common/gomp/pr59467.c: New test.

        * testsuite/libgomp.fortran/crayptr2.f90: Add private (d) clause to
        !$omp parallel.

--- gcc/gimplify.c.jj   2013-12-03 08:44:02.000000000 +0100
+++ gcc/gimplify.c      2013-12-11 13:40:13.098838596 +0100
@@ -5829,7 +5829,7 @@ omp_is_private (struct gimplify_omp_ctx
    region's REDUCTION clause.  */
 
 static bool
-omp_check_private (struct gimplify_omp_ctx *ctx, tree decl)
+omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
 {
   splay_tree_node n;
 
@@ -5838,8 +5838,11 @@ omp_check_private (struct gimplify_omp_c
       ctx = ctx->outer_context;
       if (ctx == NULL)
        return !(is_global_var (decl)
-                /* References might be private, but might be shared too.  */
-                || lang_hooks.decls.omp_privatize_by_reference (decl));
+                /* References might be private, but might be shared too,
+                   when checking for copyprivate, assume they might be
+                   private, otherwise assume they might be shared.  */
+                || (!copyprivate
+                    && lang_hooks.decls.omp_privatize_by_reference (decl)));
 
       if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0)
        continue;
@@ -6049,12 +6052,36 @@ gimplify_scan_omp_clauses (tree *list_p,
              remove = true;
              break;
            }
+         if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
+             && !remove
+             && !omp_check_private (ctx, decl, true))
+           {
+             remove = true;
+             if (is_global_var (decl))
+               {
+                 if (DECL_THREAD_LOCAL_P (decl))
+                   remove = false;
+                 else if (DECL_HAS_VALUE_EXPR_P (decl))
+                   {
+                     tree value = get_base_address (DECL_VALUE_EXPR (decl));
+
+                     if (value
+                         && DECL_P (value)
+                         && DECL_THREAD_LOCAL_P (value))
+                       remove = false;
+                   }
+               }
+             if (remove)
+               error_at (OMP_CLAUSE_LOCATION (c),
+                         "copyprivate variable %qE is not threadprivate"
+                         " or private in outer context", DECL_NAME (decl));
+           }
        do_notice:
          if (outer_ctx)
            omp_notice_variable (outer_ctx, decl, true);
          if (check_non_private
              && region_type == ORT_WORKSHARE
-             && omp_check_private (ctx, decl))
+             && omp_check_private (ctx, decl, false))
            {
              error ("%s variable %qE is private in outer context",
                     check_non_private, DECL_NAME (decl));
--- gcc/testsuite/gfortran.dg/gomp/pr59467.f90.jj       2013-12-11 
12:56:10.651397907 +0100
+++ gcc/testsuite/gfortran.dg/gomp/pr59467.f90  2013-12-11 12:59:44.336333836 
+0100
@@ -0,0 +1,24 @@
+! PR libgomp/59467
+! { dg-do compile }
+! { dg-options "-fopenmp" }
+  FUNCTION t()
+    INTEGER :: a, b, t
+    a = 0
+    b = 0
+    !$OMP PARALLEL REDUCTION(+:b)
+      !$OMP SINGLE     ! { dg-error "is not threadprivate or private in outer 
context" }
+        !$OMP ATOMIC WRITE
+        a = 6
+      !$OMP END SINGLE COPYPRIVATE (a)
+      b = a
+    !$OMP END PARALLEL
+    t = b
+    b = 0
+    !$OMP PARALLEL REDUCTION(+:b)
+      !$OMP SINGLE
+        !$OMP ATOMIC WRITE
+        b = 6
+      !$OMP END SINGLE COPYPRIVATE (b)
+    !$OMP END PARALLEL
+    t = t + b
+  END FUNCTION
--- gcc/testsuite/c-c++-common/gomp/pr59467.c.jj        2013-12-11 
12:55:35.115581435 +0100
+++ gcc/testsuite/c-c++-common/gomp/pr59467.c   2013-12-11 13:09:58.879187656 
+0100
@@ -0,0 +1,68 @@
+/* PR libgomp/59467 */
+
+int v;
+
+void
+foo (void)
+{
+  int x = 0, y = 0;
+  #pragma omp parallel
+  {
+    int z;
+    #pragma omp single copyprivate (x) /* { dg-error "is not threadprivate or 
private in outer context" } */
+    {
+      #pragma omp atomic write
+       x = 6;
+    }
+    #pragma omp atomic read
+    z = x;
+    #pragma omp atomic
+    y += z;
+  }
+  #pragma omp parallel
+  {
+    int z;
+    #pragma omp single copyprivate (v) /* { dg-error "is not threadprivate or 
private in outer context" } */
+    {
+      #pragma omp atomic write
+       v = 6;
+    }
+    #pragma omp atomic read
+    z = v;
+    #pragma omp atomic
+    y += z;
+  }
+  #pragma omp parallel private (x)
+  {
+    int z;
+    #pragma omp single copyprivate (x)
+    {
+      #pragma omp atomic write
+       x = 6;
+    }
+    #pragma omp atomic read
+    z = x;
+    #pragma omp atomic
+    y += z;
+  }
+  x = 0;
+  #pragma omp parallel reduction (+:x)
+  {
+    #pragma omp single copyprivate (x)
+    {
+      #pragma omp atomic write
+       x = 6;
+    }
+    #pragma omp atomic
+    y += x;
+  }
+  #pragma omp single copyprivate (x)
+  {
+    x = 7;
+  }
+  #pragma omp single copyprivate (v)   /* { dg-error "is not threadprivate or 
private in outer context" } */
+  {
+    #pragma omp atomic write
+      v = 6;
+  }
+}
--- libgomp/testsuite/libgomp.fortran/crayptr2.f90.jj   2009-12-23 
12:45:04.000000000 +0100
+++ libgomp/testsuite/libgomp.fortran/crayptr2.f90      2013-12-12 
09:14:29.657164503 +0100
@@ -12,7 +12,7 @@
   b = 2
   c = 3
   l = .false.
-!$omp parallel num_threads (3) reduction (.or.:l)
+!$omp parallel num_threads (3) reduction (.or.:l) private (d)
   if (omp_get_thread_num () .eq. 0) then
     ip = loc (a)
   elseif (omp_get_thread_num () .eq. 1) then

        Jakub

Reply via email to