protected:
// Apply the implicit type rules to this symbol.
void ApplyImplicitRules(Symbol &);
+ void AcquireIntrinsicProcedureFlags(Symbol &);
const DeclTypeSpec *GetImplicitType(Symbol &, const Scope &);
bool ConvertToObjectEntity(Symbol &);
bool ConvertToProcEntity(Symbol &);
}
if (IsIntrinsic(symbol.name(), functionOrSubroutineFlag)) {
// type will be determined in expression semantics
- symbol.attrs().set(Attr::INTRINSIC);
+ AcquireIntrinsicProcedureFlags(symbol);
return;
}
}
}
}
+// Ensure that the symbol for an intrinsic procedure is marked with
+// the INTRINSIC attribute. Also set PURE &/or ELEMENTAL as
+// appropriate.
+void ScopeHandler::AcquireIntrinsicProcedureFlags(Symbol &symbol) {
+ symbol.attrs().set(Attr::INTRINSIC);
+ switch (context().intrinsics().GetIntrinsicClass(symbol.name().ToString())) {
+ case evaluate::IntrinsicClass::elementalFunction:
+ case evaluate::IntrinsicClass::elementalSubroutine:
+ symbol.attrs().set(Attr::ELEMENTAL);
+ symbol.attrs().set(Attr::PURE);
+ break;
+ case evaluate::IntrinsicClass::impureSubroutine:
+ break;
+ default:
+ symbol.attrs().set(Attr::PURE);
+ }
+}
+
const DeclTypeSpec *ScopeHandler::GetImplicitType(
Symbol &symbol, const Scope &scope) {
const auto *type{implicitRulesMap_->at(&scope).GetType(symbol.name())};
bool DeclarationVisitor::Pre(const parser::IntrinsicStmt &x) {
HandleAttributeStmt(Attr::INTRINSIC, x.v);
for (const auto &name : x.v) {
- auto *symbol{FindSymbol(name)};
- if (!ConvertToProcEntity(*symbol)) {
+ auto &symbol{DEREF(FindSymbol(name))};
+ if (!ConvertToProcEntity(symbol)) {
SayWithDecl(
- name, *symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US);
- } else if (symbol->attrs().test(Attr::EXTERNAL)) { // C840
- Say(symbol->name(),
+ name, symbol, "INTRINSIC attribute not allowed on '%s'"_err_en_US);
+ } else if (symbol.attrs().test(Attr::EXTERNAL)) { // C840
+ Say(symbol.name(),
"Symbol '%s' cannot have both EXTERNAL and INTRINSIC attributes"_err_en_US,
- symbol->name());
+ symbol.name());
}
}
return false;
// are acceptable as procedure interfaces.
Symbol &symbol{
MakeSymbol(InclusiveScope(), name.source, Attrs{Attr::INTRINSIC})};
+ symbol.set_details(ProcEntityDetails{});
+ symbol.set(Symbol::Flag::Function);
if (interface->IsElemental()) {
symbol.attrs().set(Attr::ELEMENTAL);
}
- symbol.set_details(ProcEntityDetails{});
+ if (interface->IsPure()) {
+ symbol.attrs().set(Attr::PURE);
+ }
Resolve(name, symbol);
return true;
} else {
bool convertedToProcEntity{ConvertToProcEntity(*symbol)};
if (convertedToProcEntity && !symbol->attrs().test(Attr::EXTERNAL) &&
IsIntrinsic(symbol->name(), flag) && !IsDummy(*symbol)) {
- symbol->attrs().set(Attr::INTRINSIC);
// 8.2(3): ignore type from intrinsic in type-declaration-stmt
symbol->get<ProcEntityDetails>().set_interface(ProcInterface{});
+ AcquireIntrinsicProcedureFlags(*symbol);
}
if (!SetProcFlag(name, *symbol, flag)) {
return; // reported error
if (flag == Symbol::Flag::Function) {
ApplyImplicitRules(symbol);
}
+ if (symbol.attrs().test(Attr::INTRINSIC)) {
+ AcquireIntrinsicProcedureFlags(symbol);
+ }
} else if (symbol.GetType() && flag == Symbol::Flag::Subroutine) {
SayWithDecl(
name, symbol, "Cannot call function '%s' like a subroutine"_err_en_US);
+ } else if (symbol.attrs().test(Attr::INTRINSIC)) {
+ AcquireIntrinsicProcedureFlags(symbol);
}
return true;
}
end forall
end subroutine
+ subroutine test4(ch)
+ type :: t
+ real, allocatable :: x
+ end type
+ type(t) :: a(1), b(1)
+ character(*), intent(in) :: ch
+ allocate (b(1)%x)
+ ! Intrinsic functions and a couple subroutines are pure; do not emit errors
+ do concurrent (j=1:1)
+ b(j)%x = cos(1.) + len(ch)
+ call move_alloc(from=b(j)%x, to=a(j)%x)
+ end do
+ end subroutine
+
end module
end do
! Call to MOVE_ALLOC of a coarray outside a DO CONCURRENT. This is OK.
-call move_alloc(ca, cb)
-
-! Note that the errors below relating to MOVE_ALLOC() bing impure are bogus.
-! They're the result of the fact that access to the move_alloc() instrinsic
-! is not yet possible.
+ call move_alloc(ca, cb)
+! Call to MOVE_ALLOC with non-coarray arguments in a DO CONCURRENT. This is OK.
allocate(aa)
do concurrent (i = 1:10)
-!ERROR: Call to an impure procedure is not allowed in DO CONCURRENT
call move_alloc(aa, ab)
end do
-! Call to MOVE_ALLOC with non-coarray arguments in a DO CONCURRENT. This is OK.
-
do concurrent (i = 1:10)
-!ERROR: Call to an impure procedure is not allowed in DO CONCURRENT
!ERROR: An image control statement is not allowed in DO CONCURRENT
call move_alloc(ca, cb)
end do
do concurrent (i = 1:10)
-!ERROR: Call to an impure procedure is not allowed in DO CONCURRENT
!ERROR: An image control statement is not allowed in DO CONCURRENT
call move_alloc(pvar%type1_field%coarray_type0_field, qvar%type1_field%coarray_type0_field)
end do
!$omp parallel do reduction(+:sum)
!DEF: /dotprod/Block1/Block1/Block1/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
!REF: /dotprod/Block1/Block1/Block1/i0
- !DEF: /dotprod/min INTRINSIC (Function) ProcEntity
+ !DEF: /dotprod/min ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity
!REF: /dotprod/block_size
!REF: /dotprod/n
do i=i0,min(i0+block_size, n)
!DEF: /module1/derived1/p5 NOPASS, POINTER (Function) ProcEntity COMPLEX(4)
!DEF: /module1/nested4 PUBLIC (Function) Subprogram COMPLEX(4)
procedure(complex), pointer, nopass :: p5 => nested4
- !DEF: /module1/sin ELEMENTAL, INTRINSIC, PUBLIC ProcEntity
- !DEF: /module1/derived1/p6 NOPASS, POINTER ProcEntity
+ !DEF: /module1/sin ELEMENTAL, INTRINSIC, PUBLIC, PURE (Function) ProcEntity
+ !DEF: /module1/derived1/p6 NOPASS, POINTER (Function) ProcEntity
!REF: /module1/nested1
procedure(sin), pointer, nopass :: p6 => nested1
!REF: /module1/sin
- !DEF: /module1/derived1/p7 NOPASS, POINTER ProcEntity
- !DEF: /module1/cos ELEMENTAL, INTRINSIC, PUBLIC ProcEntity
+ !DEF: /module1/derived1/p7 NOPASS, POINTER (Function) ProcEntity
+ !DEF: /module1/cos ELEMENTAL, INTRINSIC, PUBLIC, PURE (Function) ProcEntity
procedure(sin), pointer, nopass :: p7 => cos
!REF: /module1/tan
!DEF: /module1/derived1/p8 NOPASS, POINTER (Function) ProcEntity CHARACTER(1_4,1)
!REF: /module1/nested4/x
real, intent(in) :: x
!DEF: /module1/nested4/nested4 ObjectEntity COMPLEX(4)
- !DEF: /module1/nested4/cmplx INTRINSIC (Function) ProcEntity
+ !DEF: /module1/nested4/cmplx ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity
!REF: /module1/nested4/x
nested4 = cmplx(x+4., 6.)
end function nested4
!REF: /f1/n
!REF: /f1/x1
!REF: /f1/x2
- !DEF: /f1/len INTRINSIC (Function) ProcEntity
+ !DEF: /f1/len ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity
character*(n), intent(in) :: x1, x2*(len(x1)+1)
!DEF: /f1/t DerivedType
type :: t
!REF: /MainProgram1/t1/k
real :: b(k)
!DEF: /MainProgram1/t2/c ObjectEntity REAL(4)
- !DEF: /MainProgram1/size INTRINSIC (Function) ProcEntity
+ !DEF: /MainProgram1/size INTRINSIC, PURE (Function) ProcEntity
!REF: /MainProgram1/t1/a
real :: c(size(a))
!REF: /MainProgram1/t1
!DEF: /m/op1 POINTER, PUBLIC ObjectEntity REAL(4)
real, pointer :: op1
!DEF: /m/op2 POINTER, PUBLIC ObjectEntity REAL(4)
- !DEF: /m/null INTRINSIC, PUBLIC (Function) ProcEntity
+ !DEF: /m/null INTRINSIC, PUBLIC, PURE (Function) ProcEntity
real, pointer :: op2 => null()
!DEF: /m/op3 POINTER, PUBLIC ObjectEntity REAL(4)
!DEF: /m/x PUBLIC, TARGET ObjectEntity REAL(4)
q1%n = 1
end subroutine
!DEF: /f2/fwdpdt DerivedType
-!DEF: /f2/kind INTRINSIC (Function) ProcEntity
+!DEF: /f2/kind INTRINSIC, PURE (Function) ProcEntity
!DEF: /f2 (Function) Subprogram TYPE(fwdpdt(k=4_4))
!DEF: /f2/n (Implicit) ObjectEntity INTEGER(4)
type(fwdpdt(kind(0))) function f2(n)
!DEF: /s2/q1 (Implicit) ObjectEntity TYPE(fwdpdt(k=4_4))
subroutine s2 (q1)
!DEF: /s2/fwdpdt DerivedType
- !DEF: /s2/kind INTRINSIC (Function) ProcEntity
+ !DEF: /s2/kind INTRINSIC, PURE (Function) ProcEntity
implicit type(fwdpdt(kind(0)))(q)
!REF: /s2/fwdpdt
!DEF: /s2/fwdpdt/k TypeParam INTEGER(4)
!DEF: /p1 MainProgram
program p1
- !DEF: /p1/cos INTRINSIC (Function) ProcEntity
+ !DEF: /p1/cos ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity
integer cos
!DEF: /p1/y (Implicit) ObjectEntity REAL(4)
!REF: /p1/cos
!DEF: /p1/x (Implicit) ObjectEntity REAL(4)
y = cos(x)
!REF: /p1/y
- !DEF: /p1/sin INTRINSIC (Function) ProcEntity
+ !DEF: /p1/sin ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity
!REF: /p1/x
y = sin(x)
!REF: /p1/y
!DEF: /expect_intrinsic (Subroutine) Subprogram
subroutine expect_intrinsic
!DEF: /expect_intrinsic/y (Implicit) ObjectEntity REAL(4)
- !DEF: /expect_intrinsic/acos INTRINSIC (Function) ProcEntity
+ !DEF: /expect_intrinsic/acos ELEMENTAL, INTRINSIC, PURE (Function) ProcEntity
!DEF: /expect_intrinsic/x (Implicit) ObjectEntity REAL(4)
y = acos(x)
!DEF: /expect_intrinsic/system_clock INTRINSIC (Subroutine) ProcEntity