gfc_do_concurrent_flag = 0 when the check for an impure function
occurs. Check the stack to see if the source code has a nested
BLOCK construct. */
+
for (stack = cs_base; stack; stack = stack->prev)
{
- if (stack->current->op == EXEC_BLOCK) saw_block = true;
+ if (!saw_block && stack->current->op == EXEC_BLOCK)
+ {
+ saw_block = true;
+ continue;
+ }
+
if (saw_block && stack->current->op == EXEC_DO_CONCURRENT)
{
- gfc_error ("Reference to impure function at %L inside a "
- "DO CONCURRENT", &e->where);
- return false;
+ bool is_pure;
+ is_pure = (e->value.function.isym
+ && (e->value.function.isym->pure
+ || e->value.function.isym->elemental))
+ || (e->value.function.esym
+ && (e->value.function.esym->attr.pure
+ || e->value.function.esym->attr.elemental));
+ if (!is_pure)
+ {
+ gfc_error ("Reference to impure function at %L inside a "
+ "DO CONCURRENT", &e->where);
+ return false;
+ }
}
}
/* A BLOCK construct within a DO CONCURRENT construct leads to
gfc_do_concurrent_flag = 0 when the check for an impure subroutine
- occurs. Check the stack to see if the source code has a nested
- BLOCK construct. */
+ occurs. Walk up the stack to see if the source code has a nested
+ construct. */
+
for (stack = cs_base; stack; stack = stack->prev)
{
- if (stack->current->op == EXEC_BLOCK) saw_block = true;
+ if (stack->current->op == EXEC_BLOCK)
+ {
+ saw_block = true;
+ continue;
+ }
+
if (saw_block && stack->current->op == EXEC_DO_CONCURRENT)
{
- gfc_error ("Subroutine call at %L in a DO CONCURRENT block "
- "is not PURE", loc);
- return false;
+
+ bool is_pure = true;
+ is_pure = sym->attr.pure || sym->attr.elemental;
+
+ if (!is_pure)
+ {
+ gfc_error ("Subroutine call at %L in a DO CONCURRENT block "
+ "is not PURE", loc);
+ return false;
+ }
}
}
squared = i * i
arr(i) = temp2 + squared
sum = sum + arr(i)
- max_val = max(max_val, arr(i)) ! { dg-error "Reference to impure function" }
+ max_val = max(max_val, arr(i))
end block
end do
print *, arr, sum, max_val
--- /dev/null
+!
+! { dg-do run }
+!
+! PR fortran/119836
+!
+program p
+ implicit none
+ integer, parameter :: n = 4
+ integer :: i
+ integer :: y(n), x(n)
+ do concurrent (i=1:n)
+ x(i) = shiftl (i,1) ! accepted
+ block
+ y(i) = shiftl (i,1) ! wrongly rejected
+ end block
+ end do
+ if (any(x /= y)) stop 1
+end program p
--- /dev/null
+!
+! { dg-do compile }
+!
+! PR fortran/119836
+!
+! Although intrinsic functions contained within the Fortran standard
+! are pure procedures, many of the additional intrinsic functions
+! supplied in libgfortran are impure. RAND() is one such function.
+!
+program foo
+ implicit none
+ integer i
+ real x(4)
+ do concurrent (i=1:4)
+ x = rand() ! { dg-error "Reference to impure function" }
+ block
+ x = rand() ! { dg-error "Reference to impure function" }
+ end block
+ end do
+ print *, x
+end program foo
--- /dev/null
+!
+! { dg-do run }
+!
+! PR fortran/119836
+!
+program p
+ implicit none
+ integer, parameter :: n = 4
+ integer :: i
+ integer :: y(n), x(n)
+ x = [(i,i=1,n)]
+ do concurrent (i=1:n)
+ call bar(x, y)
+ end do
+ if (any(x /= y)) stop 1
+ x = 2 * x
+ do concurrent (i=1:n)
+ block
+ call bar(x, y)
+ end block
+ end do
+ if (any(x /= y)) stop 1
+
+ contains
+ elemental subroutine bar(x, y)
+ integer, intent(in) :: x
+ integer, intent(out) :: y
+ y = x
+ end subroutine
+end program p
--- /dev/null
+!
+! { dg-do compile }
+!
+! PR fortran/119836
+!
+program p
+ implicit none
+ integer, parameter :: n = 4
+ integer :: i
+ integer :: y(n), x(n)
+ x = [(i,i=1,n)]
+ do concurrent (i=1:n)
+ call bar(x, y) ! { dg-error "Subroutine call" }
+ end do
+ if (any(x /= y)) stop 1
+ x = 2 * x
+ do concurrent (i=1:n)
+ block
+ call bar(x, y) ! { dg-error "Subroutine call" }
+ end block
+ end do
+ if (any(x /= y)) stop 1
+
+ contains
+ subroutine bar(x, y)
+ integer, intent(in) :: x(:)
+ integer, intent(out) :: y(:)
+ y = x
+ end subroutine
+end program p