return std::visit(
common::visitors{
[&](const parser::Name &n) -> std::optional<CallAndArguments> {
- if (n.symbol == nullptr) {
+ const Symbol *symbol{n.symbol};
+ if (symbol == nullptr) {
Say("TODO INTERNAL no symbol for procedure designator name '%s'"_err_en_US,
n.ToString().data());
return std::nullopt;
}
- const Symbol &ultimate{n.symbol->GetUltimate()};
- if (const auto *proc{
- ultimate.detailsIf<semantics::ProcEntityDetails>()}) {
- if (proc->HasExplicitInterface()) {
+ if (IsProcedure(*symbol)) {
+ if (symbol->HasExplicitInterface()) {
// TODO: check actual arguments vs. interface
} else {
CallCharacteristics cc{n.source};
}
}
return {CallAndArguments{
- ProcedureDesignator{*n.symbol}, std::move(arguments)}};
+ ProcedureDesignator{*symbol}, std::move(arguments)}};
} else {
Say(n.source, "not a procedure"_err_en_US);
return std::nullopt;
[](const EntityDetails &x) { return x.type(); },
[](const ObjectEntityDetails &x) { return x.type(); },
[](const AssocEntityDetails &x) { return x.type(); },
+ [](const SubprogramDetails &x) {
+ return x.isFunction() ? x.result().GetType() : nullptr;
+ },
[](const ProcEntityDetails &x) { return x.interface().type(); },
[](const TypeParamDetails &x) { return x.type(); },
[](const UseDetails &x) { return x.symbol().GetType(); },
}
bool IsFunction(const Symbol &symbol) {
- if (const auto *procDetails{symbol.detailsIf<ProcEntityDetails>()}) {
- return procDetails->interface().type() != nullptr ||
- (procDetails->interface().symbol() != nullptr &&
- IsFunction(*procDetails->interface().symbol()));
- } else if (const auto *subprogram{symbol.detailsIf<SubprogramDetails>()}) {
- return subprogram->isFunction();
- } else {
- return false;
- }
+ return std::visit(
+ common::visitors{
+ [](const SubprogramDetails &x) { return x.isFunction(); },
+ [&](const SubprogramNameDetails &x) {
+ return symbol.test(Symbol::Flag::Function);
+ },
+ [](const ProcEntityDetails &x) {
+ const auto &ifc{x.interface()};
+ return ifc.type() || (ifc.symbol() && IsFunction(*ifc.symbol()));
+ },
+ [](const UseDetails &x) { return IsFunction(x.symbol()); },
+ [](const auto &) { return false; },
+ },
+ symbol.details());
}
bool IsPureFunction(const Symbol &symbol) {
}
}
+bool IsProcedure(const Symbol &symbol) {
+ return std::visit(
+ common::visitors{
+ [](const SubprogramDetails &) { return true; },
+ [](const SubprogramNameDetails &) { return true; },
+ [](const ProcEntityDetails &x) { return true; },
+ [](const UseDetails &x) { return IsProcedure(x.symbol()); },
+ [](const auto &) { return false; },
+ },
+ symbol.details());
+}
+
static const Symbol *FindPointerComponent(
const Scope &scope, std::set<const Scope *> &visited) {
if (scope.kind() != Scope::Kind::DerivedType) {
bool IsFunction(const Symbol &);
bool IsPureFunction(const Symbol &);
bool IsPureFunction(const Scope &);
+bool IsProcedure(const Symbol &);
bool IsProcName(const Symbol &symbol); // proc-name
bool IsVariableName(const Symbol &symbol); // variable-name
bool IsAllocatable(const Symbol &);
a = 14
end if
+if (f()) then
+ a = 15
+end if
+
+contains
+ logical function f()
+ f = .true.
+ end
end
a = 14
end if
+!ERROR: Must have LOGICAL type, but is REAL(4)
+if (f()) then
+ a = 15
+end if
+
+contains
+ real function f()
+ f = 1.0
+ end
end
!DEF: /module1/derived1 PUBLIC DerivedType
type :: derived1
- !DEF: /module1/abstract1 ELEMENTAL, PUBLIC Subprogram
+ !DEF: /module1/abstract1 ELEMENTAL, PUBLIC Subprogram REAL(4)
!DEF: /module1/derived1/p1 NOPASS, POINTER ProcEntity
- !DEF: /module1/nested1 ELEMENTAL, PUBLIC Subprogram
+ !DEF: /module1/nested1 ELEMENTAL, PUBLIC Subprogram REAL(4)
procedure(abstract1), pointer, nopass :: p1 => nested1
- !DEF: /module1/explicit1 ELEMENTAL, EXTERNAL, PUBLIC Subprogram
+ !DEF: /module1/explicit1 ELEMENTAL, EXTERNAL, PUBLIC Subprogram REAL(4)
!DEF: /module1/derived1/p2 NOPASS, POINTER ProcEntity
!REF: /module1/nested1
procedure(explicit1), pointer, nopass :: p2 => nested1
- !DEF: /module1/logical EXTERNAL, PUBLIC Subprogram
+ !DEF: /module1/logical EXTERNAL, PUBLIC Subprogram INTEGER(4)
!DEF: /module1/derived1/p3 NOPASS, POINTER ProcEntity
- !DEF: /module1/nested2 PUBLIC Subprogram
+ !DEF: /module1/nested2 PUBLIC Subprogram INTEGER(4)
procedure(logical), pointer, nopass :: p3 => nested2
!DEF: /module1/derived1/p4 NOPASS, POINTER ProcEntity LOGICAL(4)
- !DEF: /module1/nested3 PUBLIC Subprogram
+ !DEF: /module1/nested3 PUBLIC Subprogram LOGICAL(4)
procedure(type(logical(kind=4))), pointer, nopass :: p4 => nested3
!DEF: /module1/derived1/p5 NOPASS, POINTER ProcEntity COMPLEX(4)
- !DEF: /module1/nested4 PUBLIC Subprogram
+ !DEF: /module1/nested4 PUBLIC Subprogram COMPLEX(4)
procedure(type(complex)), pointer, nopass :: p5 => nested4
!DEF: /module1/derived1/p6 NOPASS, POINTER ProcEntity
!REF: /module1/nested1
procedure(sin), pointer, nopass :: p6 => nested1
!DEF: /module1/derived1/p7 NOPASS, POINTER ProcEntity
procedure(sin), pointer, nopass :: p7 => cos
- !DEF: /module1/tan EXTERNAL, PUBLIC Subprogram
+ !DEF: /module1/tan EXTERNAL, PUBLIC Subprogram CHARACTER(1_4,1)
!DEF: /module1/derived1/p8 NOPASS, POINTER ProcEntity
- !DEF: /module1/nested5 PUBLIC Subprogram
+ !DEF: /module1/nested5 PUBLIC Subprogram CHARACTER(1_8,1)
procedure(tan), pointer, nopass :: p8 => nested5
end type derived1
-! Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
+! Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
!
! Licensed under the Apache License, Version 2.0 (the "License");
! you may not use this file except in compliance with the License.
!DEF: /m Module
module m
- !DEF: /m/f PRIVATE, PURE, RECURSIVE Subprogram
+ !DEF: /m/f PRIVATE, PURE, RECURSIVE Subprogram REAL(4)
private :: f
contains
!DEF: /m/s BIND(C), PUBLIC, PURE Subprogram