Ups. Good catch. – I think the follow-up patch is obvious.
Unless there are comments, I will commit it as such.

Tobias

On 6/16/20 4:41 PM, Thomas Schwinge wrote:

Hi!

On 2020-06-16T13:27:43+0200, Tobias Burnus <tob...@codesourcery.com> wrote:
when looking into a PURE/ELEMENTAL issue with OpenACC, Thomas and
I came across the analogous OpenMP code – and stumbled over
ELEMENTAL.

In Fortran, ELEMENTAL implies PURE but one can also have an IMPURE
ELEMENTAL procedure.

As PR 79154 quotes, OpenMP 4 had:
"OpenMP directives may not appear in PURE or ELEMENTAL procedures."

While OpenMP 4.5 (and later) have:
"OpenMP directives, except SIMD and declare target directives,
   may not appear in pure procedures."

ELEMENTAL is still mentioned – but only for:
"OpenMP runtime library routines may not be called
   from PURE or ELEMENTAL procedures."
... but that's mentioned not only diagnoesd here:

--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -849,7 +849,7 @@ decode_omp_directive (void)
    /* match is for directives that should be recognized only if
       -fopenmp, matchs for directives that should be recognized
       if either -fopenmp or -fopenmp-simd.
-     Handle only the directives allowed in PURE/ELEMENTAL procedures
+     Handle only the directives allowed in PURE procedures
       first (those also shall not turn off implicit pure).  */
    switch (c)
      {
@@ -868,7 +868,7 @@ decode_omp_directive (void)
    if (flag_openmp && gfc_pure (NULL))
      {
        gfc_error_now ("OpenMP directives other than SIMD or DECLARE TARGET "
-                  "at %C may not appear in PURE or ELEMENTAL procedures");
+                  "at %C may not appear in PURE procedures");
        gfc_error_recovery ();
        return ST_NONE;
      }
..., but also further down, in the 'finish' label:

      finish:
       if (!pure_ok)
         {
           gfc_unset_implicit_pure (NULL);

           if (!flag_openmp && gfc_pure (NULL))
             {
               gfc_error_now ("OpenMP directives other than SIMD or DECLARE TARGET 
"
                              "at %C may not appear in PURE or ELEMENTAL "
                              "procedures");
               reject_statement ();
               gfc_error_recovery ();
               return ST_NONE;
             }
         }
       return ret;

..., so I suppose this needs to be changed, too -- and maybe is missing
testsuite coverage?

--- a/gcc/testsuite/gfortran.dg/gomp/pr79154-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr79154-1.f90
@@ -2,7 +2,7 @@
  ! { dg-do compile }

  pure real function foo (a, b)                ! { dg-warning "GCC does not currently support 
mixed size types for 'simd' functions" "" { target aarch64*-*-* } }
-!$omp declare simd(foo)                      ! { dg-bogus "may not appear in PURE 
or ELEMENTAL" }
+!$omp declare simd(foo)                      ! { dg-bogus "may not appear in 
PURE" }
    real, intent(in) :: a, b
    foo = a + b
  end function foo
@@ -10,23 +10,28 @@ pure function bar (a, b)
    real, intent(in) :: a(8), b(8)
    real :: bar(8)
    integer :: i
-!$omp simd                           ! { dg-bogus "may not appear in PURE or 
ELEMENTAL" }
+!$omp simd                           ! { dg-bogus "may not appear in PURE" }
    do i = 1, 8
      bar(i) = a(i) + b(i)
    end do
  end function bar
  pure real function baz (a, b)
-!$omp declare target                 ! { dg-bogus "may not appear in PURE or 
ELEMENTAL" }
+!$omp declare target                 ! { dg-bogus "may not appear in PURE" }
    real, intent(in) :: a, b
    baz = a + b
  end function baz
  elemental real function fooe (a, b)  ! { dg-warning "GCC does not currently support mixed 
size types for 'simd' functions" "" { target aarch64*-*-* } }
-!$omp declare simd(fooe)             ! { dg-bogus "may not appear in PURE or 
ELEMENTAL" }
+!$omp declare simd(fooe)             ! { dg-bogus "may not appear in PURE" }
    real, intent(in) :: a, b
    fooe = a + b
  end function fooe
  elemental real function baze (a, b)
-!$omp declare target                 ! { dg-bogus "may not appear in PURE or 
ELEMENTAL" }
+!$omp declare target                 ! { dg-bogus "may not appear in PURE" }
    real, intent(in) :: a, b
    baze = a + b
  end function baze
+elemental impure real function bazei (a, b)
+!$omp declare target                 ! { dg-bogus "may not appear in PURE" }
+  real, intent(in) :: a, b
+  baze = a + b
Shouldn't this assign to 'bazei' instead of 'baze'?

+end function bazei
--- a/gcc/testsuite/gfortran.dg/gomp/pr79154-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/pr79154-2.f90
@@ -3,14 +3,14 @@

  pure real function foo (a, b)
    real, intent(in) :: a, b
-!$omp taskwait                               ! { dg-error "may not appear in PURE 
or ELEMENTAL" }
+!$omp taskwait                               ! { dg-error "may not appear in 
PURE" }
    foo = a + b
  end function foo
  pure function bar (a, b)
    real, intent(in) :: a(8), b(8)
    real :: bar(8)
    integer :: i
-!$omp do simd                                ! { dg-error "may not appear in PURE 
or ELEMENTAL" }
+!$omp do simd                                ! { dg-error "may not appear in 
PURE" }
    do i = 1, 8
      bar(i) = a(i) + b(i)
    end do
@@ -19,26 +19,38 @@ pure function baz (a, b)
    real, intent(in) :: a(8), b(8)
    real :: baz(8)
    integer :: i
-!$omp do                             ! { dg-error "may not appear in PURE or 
ELEMENTAL" }
+!$omp do                             ! { dg-error "may not appear in PURE" }
    do i = 1, 8
      baz(i) = a(i) + b(i)
    end do
-!$omp end do                         ! { dg-error "may not appear in PURE or 
ELEMENTAL" }
+!$omp end do                         ! { dg-error "may not appear in PURE" }
  end function baz
  pure real function baz2 (a, b)
    real, intent(in) :: a, b
-!$omp target map(from:baz2)          ! { dg-error "may not appear in PURE or 
ELEMENTAL" }
+!$omp target map(from:baz2)          ! { dg-error "may not appear in PURE" }
    baz2 = a + b
-!$omp end target                     ! { dg-error "may not appear in PURE or 
ELEMENTAL" }
+!$omp end target                     ! { dg-error "may not appear in PURE" }
  end function baz2
+! ELEMENTAL implies PURE
  elemental real function fooe (a, b)
    real, intent(in) :: a, b
-!$omp taskyield                              ! { dg-error "may not appear in PURE 
or ELEMENTAL" }
+!$omp taskyield                              ! { dg-error "may not appear in 
PURE" }
    fooe = a + b
  end function fooe
  elemental real function baze (a, b)
    real, intent(in) :: a, b
-!$omp target map(from:baz)           ! { dg-error "may not appear in PURE or 
ELEMENTAL" }
+!$omp target map(from:baz)           ! { dg-error "may not appear in PURE" }
    baze = a + b
-!$omp end target                     ! { dg-error "may not appear in PURE or 
ELEMENTAL" }
+!$omp end target                     ! { dg-error "may not appear in PURE" }
  end function baze
+elemental impure real function fooei (a, b)
+  real, intent(in) :: a, b
+!$omp taskyield                              ! { dg-bogus "may not appear in 
PURE" }
+  fooe = a + b
+end function fooei
+elemental impure real function bazei (a, b)
+  real, intent(in) :: a, b
+!$omp target map(from:baz)           ! { dg-bogus "may not appear in PURE" }
+  baze = a + b
Similar.

+!$omp end target                     ! { dg-bogus "may not appear in PURE" }
+end function bazei

Grüße
  Thomas
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter
-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter
OpenMP/Fortran: Permit impure ELEMENTAL in omp directives

OpenMP since 4.5 permits IMPURE ELEMENTAL in directives and
the code already only checked for PURE. – Followup for
-fopenmp-simd.

gcc/fortran/ChangeLog:

	* parse.c (decode_omp_directive): Remove "or ELEMENTAL"
	from "in PURE" error message also for -fopenmp-simd.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/pr79154-simd.f90: New test.

 gcc/fortran/parse.c                             |  3 +--
 gcc/testsuite/gfortran.dg/gomp/pr79154-simd.f90 | 16 ++++++++++++++++
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 9d90e501bf6..46e1e1b2698 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -1078,8 +1078,7 @@ decode_omp_directive (void)
       if (!flag_openmp && gfc_pure (NULL))
 	{
 	  gfc_error_now ("OpenMP directives other than SIMD or DECLARE TARGET "
-			 "at %C may not appear in PURE or ELEMENTAL "
-			 "procedures");
+			 "at %C may not appear in PURE procedures");
 	  reject_statement ();
 	  gfc_error_recovery ();
 	  return ST_NONE;
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr79154-simd.f90 b/gcc/testsuite/gfortran.dg/gomp/pr79154-simd.f90
new file mode 100644
index 00000000000..d6b72d6f3da
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr79154-simd.f90
@@ -0,0 +1,16 @@
+! { dg-options "-fno-openmp -fopenmp-simd" }
+!
+pure subroutine bar(a)
+  integer, intent(in) :: a(:)
+  !$omp target enter data map(to:a)   ! Ignored with -fopenmp-simd otherwise invalid in PURE
+end
+
+pure subroutine foo(a,b)
+  integer, intent(out) :: a(5)
+  integer, intent(in) :: b(5)
+  !$omp target teams distribute simd ! { dg-error "may not appear in PURE procedures" }
+  do i=1, 5
+    a(i) = b(i)
+  end do
+  !$omp end target teams distribute
+end subroutine

Reply via email to