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