diff mbox series

OpenMP/Fortran: Permit impure ELEMENTAL in omp directives

Message ID 9cd0b179-63fb-ba5d-9c31-3d3d0358b300@codesourcery.com
State New
Headers show
Series OpenMP/Fortran: Permit impure ELEMENTAL in omp directives | expand

Commit Message

Tobias Burnus June 16, 2020, 11:27 a.m. UTC
Hi all,

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."

OK for the trunk?

Tobias

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander Walter

Comments

Jakub Jelinek June 16, 2020, 11:42 a.m. UTC | #1
On Tue, Jun 16, 2020 at 01:27:43PM +0200, Tobias Burnus 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."
> 
> OK for the trunk?

Ok.

	Jakub
Thomas Schwinge June 16, 2020, 2:41 p.m. UTC | #2
Hi!

On 2020-06-16T13:27:43+0200, Tobias Burnus <tobias@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
Tobias Burnus June 16, 2020, 3:33 p.m. UTC | #3
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 <tobias@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
diff mbox series

Patch

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.

gcc/fortran/ChangeLog:

	* parse.c (decode_omp_directive): Remove "or ELEMENTAL"
	from "in PURE" error message.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/pr79154-1.f90: Update dg-*;
	add an impure elemental example.
	* gfortran.dg/gomp/pr79154-2.f90: Likewise.

 gcc/fortran/parse.c                          |  4 ++--
 gcc/testsuite/gfortran.dg/gomp/pr79154-1.f90 | 15 +++++++++-----
 gcc/testsuite/gfortran.dg/gomp/pr79154-2.f90 | 30 +++++++++++++++++++---------
 3 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index f71a95dd871..9d90e501bf6 100644
--- 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;
     }
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr79154-1.f90 b/gcc/testsuite/gfortran.dg/gomp/pr79154-1.f90
index 69a0009e13c..ea147bfa78e 100644
--- 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
+end function bazei
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr79154-2.f90 b/gcc/testsuite/gfortran.dg/gomp/pr79154-2.f90
index 67344f0c028..38d3fe5c384 100644
--- 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
+!$omp end target			! { dg-bogus "may not appear in PURE" }
+end function bazei