goto do_spec_only; \
if (match_word_omp_simd (keyword, subr, &old_locus, \
&simd_matched) == MATCH_YES) \
- return st; \
+ { \
+ ret = st; \
+ goto finish; \
+ } \
else \
undo_new_statement (); \
} while (0);
goto do_spec_only; \
else if (match_word (keyword, subr, &old_locus) \
== MATCH_YES) \
- return st; \
+ { \
+ ret = st; \
+ goto finish; \
+ } \
else \
undo_new_statement (); \
} while (0);
do { \
if (match_word_omp_simd (keyword, subr, &old_locus, \
&simd_matched) == MATCH_YES) \
- return st; \
+ { \
+ ret = st; \
+ goto finish; \
+ } \
else \
undo_new_statement (); \
} while (0);
; \
else if (match_word (keyword, subr, &old_locus) \
== MATCH_YES) \
- return st; \
+ { \
+ ret = st; \
+ goto finish; \
+ } \
else \
undo_new_statement (); \
} while (0);
char c;
bool simd_matched = false;
bool spec_only = false;
+ gfc_statement ret = ST_NONE;
+ bool pure_ok = true;
gfc_enforce_clean_symbol_state ();
gfc_clear_error (); /* Clear any pending errors. */
gfc_clear_warning (); /* Clear any pending warnings. */
- if (gfc_pure (NULL))
- {
- gfc_error_now ("OpenMP directives at %C may not appear in PURE "
- "or ELEMENTAL procedures");
- gfc_error_recovery ();
- return ST_NONE;
- }
-
if (gfc_current_state () == COMP_FUNCTION
&& gfc_current_block ()->result->ts.kind == -1)
spec_only = true;
- gfc_unset_implicit_pure (NULL);
-
old_locus = gfc_current_locus;
/* General OpenMP directive matching: Instead of testing every possible
c = gfc_peek_ascii_char ();
+ /* 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
+ first (those also shall not turn off implicit pure). */
+ switch (c)
+ {
+ case 'd':
+ matchds ("declare simd", gfc_match_omp_declare_simd,
+ ST_OMP_DECLARE_SIMD);
+ matchdo ("declare target", gfc_match_omp_declare_target,
+ ST_OMP_DECLARE_TARGET);
+ break;
+ case 's':
+ matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
+ break;
+ }
+
+ pure_ok = false;
+ 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");
+ gfc_error_recovery ();
+ return ST_NONE;
+ }
+
/* match is for directives that should be recognized only if
-fopenmp, matchs for directives that should be recognized
if either -fopenmp or -fopenmp-simd. */
case 'd':
matchds ("declare reduction", gfc_match_omp_declare_reduction,
ST_OMP_DECLARE_REDUCTION);
- matchds ("declare simd", gfc_match_omp_declare_simd,
- ST_OMP_DECLARE_SIMD);
- matchdo ("declare target", gfc_match_omp_declare_target,
- ST_OMP_DECLARE_TARGET);
matchs ("distribute parallel do simd",
gfc_match_omp_distribute_parallel_do_simd,
ST_OMP_DISTRIBUTE_PARALLEL_DO_SIMD);
case 's':
matcho ("sections", gfc_match_omp_sections, ST_OMP_SECTIONS);
matcho ("section", gfc_match_omp_eos, ST_OMP_SECTION);
- matchs ("simd", gfc_match_omp_simd, ST_OMP_SIMD);
matcho ("single", gfc_match_omp_single, ST_OMP_SINGLE);
break;
case 't':
return ST_NONE;
+ 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;
+
do_spec_only:
reject_statement ();
gfc_clear_error ();
--- /dev/null
+! PR fortran/79154
+! { dg-do compile }
+
+pure real function foo (a, b)
+!$omp declare simd(foo) ! { dg-bogus "may not appear in PURE or ELEMENTAL" }
+ real, intent(in) :: a, b
+ foo = a + b
+end function foo
+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" }
+ 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" }
+ real, intent(in) :: a, b
+ baz = a + b
+end function baz
+elemental real function fooe (a, b)
+!$omp declare simd(fooe) ! { dg-bogus "may not appear in PURE or ELEMENTAL" }
+ 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" }
+ real, intent(in) :: a, b
+ baze = a + b
+end function baze
--- /dev/null
+! PR fortran/79154
+! { dg-do compile }
+
+pure real function foo (a, b)
+ real, intent(in) :: a, b
+!$omp taskwait ! { dg-error "may not appear in PURE or ELEMENTAL" }
+ 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" }
+ do i = 1, 8
+ bar(i) = a(i) + b(i)
+ end do
+end function bar
+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" }
+ do i = 1, 8
+ baz(i) = a(i) + b(i)
+ end do
+!$omp end do ! { dg-error "may not appear in PURE or ELEMENTAL" }
+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" }
+ baz2 = a + b
+!$omp end target ! { dg-error "may not appear in PURE or ELEMENTAL" }
+end function baz2
+elemental real function fooe (a, b)
+ real, intent(in) :: a, b
+!$omp taskyield ! { dg-error "may not appear in PURE or ELEMENTAL" }
+ 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" }
+ baze = a + b
+!$omp end target ! { dg-error "may not appear in PURE or ELEMENTAL" }
+end function baze