[committed] Diagnose invalid OpenMP copyprivate clause arguments (PR libgomp/59467)

Jakub Jelinek jakub@redhat.com
Thu Dec 12 09:02:00 GMT 2013


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  <jakub@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



More information about the Gcc-patches mailing list