template<typename T> Result operator()(const FunctionRef<T> &x) const {
if (const auto *symbol{x.proc().GetSymbol()}) {
- if (!symbol->attrs().test(semantics::Attr::PURE)) {
+ if (!semantics::IsPureProcedure(*symbol)) {
return "reference to impure function '"s + symbol->name().ToString() +
"'";
}
// procedure component with a PURE interface
return IsPureProcedure(*procInterface);
}
+ } else if (const auto *details{symbol.detailsIf<ProcBindingDetails>()}) {
+ return IsPureProcedure(details->symbol());
+ } else if (!IsProcedure(symbol)) {
+ return false;
}
- return symbol.attrs().test(Attr::PURE) && IsProcedure(symbol);
+ return symbol.attrs().test(Attr::PURE);
}
bool IsPureProcedure(const Scope &scope) {
type :: t
contains
- procedure, nopass :: tbp => pure
+ procedure, nopass :: tbp_pure => pure
+ procedure, nopass :: tbp_impure => impure
end type
type, extends(t) :: t2
contains
!ERROR: An overridden PURE type-bound procedure binding must also be PURE
- procedure, nopass :: tbp => impure ! 7.5.7.3
+ procedure, nopass :: tbp_pure => impure ! 7.5.7.3
end type
contains
a(j) = impure(j) ! C1139
end do
end subroutine
+ subroutine test2
+ type(t) :: x
+ real :: a(x%tbp_pure(1)) ! ok
+ !ERROR: Invalid specification expression: reference to impure function 'tbp_impure'
+ real :: b(x%tbp_impure(1))
+ forall (j=1:1)
+ a(j) = x%tbp_pure(j) ! ok
+ end forall
+ forall (j=1:1)
+ !ERROR: Impure procedure 'tbp_impure' may not be referenced in a FORALL
+ a(j) = x%tbp_impure(j) ! C1037
+ end forall
+ do concurrent (j=1:1, x%tbp_pure(j) /= 0) ! ok
+ a(j) = x%tbp_pure(j) ! ok
+ end do
+ !ERROR: Concurrent-header mask expression cannot reference an impure procedure
+ do concurrent (j=1:1, x%tbp_impure(j) /= 0) ! C1121
+ !ERROR: Call to an impure procedure component is not allowed in DO CONCURRENT
+ a(j) = x%tbp_impure(j) ! C1139
+ end do
+ end subroutine
end module