Hi,

This patch arose from discussion of the manual deep copy patch here:

  https://gcc.gnu.org/ml/gcc-patches/2019-12/msg01439.html

In C/C++, it's not permitted to mix full struct-type accesses and
"attach/detach" accesses to the same struct's members within a single
directive.  This patch adds the same restriction to the Fortran front-end,
and adjusts some existing tests to match.  A test is also added for
detection of duplicate derived-type member accesses within a directive.

Tested with offloading to NVPTX. OK for mainline?

Thanks,

Julian

ChangeLog

2020-01-04  Julian Brown  <jul...@codesourcery.com>

        gcc/fortran/
        * gfortran.h (gfc_symbol): Add comp_mark bitfield.
        * openmp.c (resolve_omp_clauses): Disallow mixed component and
        full-derived-type accesses to the same variable within a single
        directive.

        libgomp/
        * testsuite/libgomp.oacc-fortran/deep-copy-2.f90: Remove test from here.
        * testsuite/libgomp.oacc-fortran/deep-copy-3.f90: Don't use mixed
        component/non-component variable refs in a single directive.
        * testsuite/libgomp.oacc-fortran/classtypes-1.f95: Likewise.

        gcc/testsuite/
        * gfortran.dg/goacc/deep-copy-2.f90: Add test here. Make a compilation
        test, and expect rejection of mixed component/non-component accesses.
        * gfortran.dg/goacc/mapping-tests-1.f90: New test.
---
 gcc/fortran/gfortran.h                        |  6 ++--
 gcc/fortran/openmp.c                          | 31 ++++++++++---------
 .../gfortran.dg/goacc}/deep-copy-2.f90        |  8 +++--
 .../gfortran.dg/goacc/mapping-tests-1.f90     | 15 +++++++++
 .../libgomp.oacc-fortran/classtypes-1.f95     |  6 ++--
 .../libgomp.oacc-fortran/deep-copy-3.f90      |  4 ++-
 6 files changed, 49 insertions(+), 21 deletions(-)
 rename {libgomp/testsuite/libgomp.oacc-fortran => 
gcc/testsuite/gfortran.dg/goacc}/deep-copy-2.f90 (63%)
 create mode 100644 gcc/testsuite/gfortran.dg/goacc/mapping-tests-1.f90

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index df07eeed8e3..1de5f0d171e 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1592,9 +1592,11 @@ typedef struct gfc_symbol
      current statement have the mark member nonzero.  Of these symbols,
      symbols with old_symbol equal to NULL are symbols created within
      the current statement.  Otherwise, old_symbol points to a copy of
-     the old symbol. gfc_new is used in symbol.c to flag new symbols.  */
+     the old symbol. gfc_new is used in symbol.c to flag new symbols.
+     comp_mark is used to indicate variables which have component accesses
+     in OpenACC directive clauses.  */
   struct gfc_symbol *old_symbol;
-  unsigned mark:1, gfc_new:1;
+  unsigned mark:1, comp_mark:1, gfc_new:1;
 
   /* The tlink field is used in the front end to carry the module
      declaration of separate module procedures so that the characteristics
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index c105657a91b..78351b190f7 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -4245,6 +4245,7 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses 
*omp_clauses,
     for (n = omp_clauses->lists[list]; n; n = n->next)
       {
        n->sym->mark = 0;
+       n->sym->comp_mark = 0;
        if (n->sym->attr.flavor == FL_VARIABLE
            || n->sym->attr.proc_pointer
            || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
@@ -4310,23 +4311,25 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses 
*omp_clauses,
        && (list != OMP_LIST_REDUCTION || !openacc))
       for (n = omp_clauses->lists[list]; n; n = n->next)
        {
-         bool array_only_p = true;
-         /* Disallow duplicate bare variable references and multiple
-            subarrays of the same array here, but allow multiple components of
-            the same (e.g. derived-type) variable.  For the latter, duplicate
-            components are detected elsewhere.  */
+         bool component_ref_p = false;
+
+         /* Allow multiple components of the same (e.g. derived-type)
+            variable here.  Duplicate components are detected elsewhere.  */
          if (openacc && n->expr && n->expr->expr_type == EXPR_VARIABLE)
            for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
-             if (ref->type != REF_ARRAY)
-               {
-                 array_only_p = false;
-                 break;
-               }
-         if (array_only_p)
+             if (ref->type == REF_COMPONENT)
+               component_ref_p = true;
+         if (openacc && ((!component_ref_p && n->sym->comp_mark)
+                         || (component_ref_p && n->sym->mark)))
+           gfc_error ("Symbol %qs has mixed component and non-component "
+                      "accesses at %L", n->sym->name, &n->where);
+         else if (n->sym->mark)
+           gfc_error ("Symbol %qs present on multiple clauses at %L",
+                      n->sym->name, &n->where);
+         else
            {
-             if (n->sym->mark)
-               gfc_error ("Symbol %qs present on multiple clauses at %L",
-                          n->sym->name, &n->where);
+             if (component_ref_p)
+               n->sym->comp_mark = 1;
              else
                n->sym->mark = 1;
            }
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/deep-copy-2.f90 
b/gcc/testsuite/gfortran.dg/goacc/deep-copy-2.f90
similarity index 63%
rename from libgomp/testsuite/libgomp.oacc-fortran/deep-copy-2.f90
rename to gcc/testsuite/gfortran.dg/goacc/deep-copy-2.f90
index 35936617b87..1e556b16b47 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/deep-copy-2.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/deep-copy-2.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do compile }
 
 ! Test of attach/detach with "acc data", two clauses at once.
 
@@ -14,7 +14,9 @@ program dtype
 
   allocate(var%a(1:n))
 
-!$acc data copy(var) copy(var%a)
+!$acc data copy(var) copy(var%a) ! { dg-error "Symbol .var. has mixed 
component and non-component accesses" }
+
+!$acc data copy(var%a) copy(var) ! { dg-error "Symbol .var. has mixed 
component and non-component accesses" }
 
 !$acc parallel loop
   do i = 1,n
@@ -22,6 +24,8 @@ program dtype
   end do
 !$acc end parallel loop
 
+!$acc end data
+
 !$acc end data
 
   do i = 1,n
diff --git a/gcc/testsuite/gfortran.dg/goacc/mapping-tests-1.f90 
b/gcc/testsuite/gfortran.dg/goacc/mapping-tests-1.f90
new file mode 100644
index 00000000000..c1bfe586842
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/mapping-tests-1.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+
+subroutine foo
+  type t
+    integer :: i, j
+  end type t
+
+  type(t) x
+
+  ! We should reject the duplicate reference here.
+!$acc enter data copyin(x%i, x%i)
+! { dg-error ".x.i. appears more than once in map clauses" "" { target "*-*-*" 
} 11 }
+
+
+end
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/classtypes-1.f95 
b/libgomp/testsuite/libgomp.oacc-fortran/classtypes-1.f95
index f16f42fc3af..c5f0ffffb02 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/classtypes-1.f95
+++ b/libgomp/testsuite/libgomp.oacc-fortran/classtypes-1.f95
@@ -31,7 +31,8 @@ program main
     myvar%p%p(i) = -1.0
   end do
 
-!$acc enter data copyin(myvar, myvar%p) create(myvar%p%p)
+!$acc enter data copyin(myvar)
+!$acc enter data copyin(myvar%p) create(myvar%p%p)
 
 !$acc parallel loop present(myvar%p%p)
   do i=1,100
@@ -39,7 +40,8 @@ program main
   end do
 !$acc end parallel loop
 
-!$acc exit data copyout(myvar%p%p) delete(myvar, myvar%p)
+!$acc exit data copyout(myvar%p%p) delete(myvar%p)
+!$acc exit data delete(myvar)
 
   do i=1,100
     if (myvar%p%p(i) .ne. i * 2) stop 1
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/deep-copy-3.f90 
b/libgomp/testsuite/libgomp.oacc-fortran/deep-copy-3.f90
index 667d944fecb..edb6b8d61a4 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/deep-copy-3.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/deep-copy-3.f90
@@ -16,12 +16,14 @@ program dtype
   allocate(var%a(1:n))
   allocate(var%b(1:n))
 
-!$acc parallel loop copy(var) copy(var%a(1:n)) copy(var%b(1:n))
+!$acc data copy(var)
+!$acc parallel loop copy(var%a(1:n)) copy(var%b(1:n))
   do i = 1,n
     var%a(i) = i
     var%b(i) = i
   end do
 !$acc end parallel loop
+!$acc end data
 
   do i = 1,n
     if (i .ne. var%a(i)) stop 1
-- 
2.23.0

Reply via email to