diff --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h --- a/flang/include/flang/Evaluate/call.h +++ b/flang/include/flang/Evaluate/call.h @@ -198,6 +198,7 @@ std::string GetName() const; std::optional GetType() const; + const Symbol *GetResult() const; int Rank() const; bool IsElemental() const; bool IsPure() const; @@ -228,6 +229,7 @@ int Rank() const; bool IsElemental() const { return proc_.IsElemental(); } bool hasAlternateReturns() const { return hasAlternateReturns_; } + const Symbol *GetResult() const { return proc_.GetResult(); } Expr *UnwrapArgExpr(int n) { if (static_cast(n) < arguments_.size() && arguments_[n]) { diff --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp --- a/flang/lib/Evaluate/call.cpp +++ b/flang/lib/Evaluate/call.cpp @@ -98,6 +98,18 @@ return std::nullopt; } +const Symbol *ProcedureDesignator::GetResult() const { + if (const Symbol * procSym{GetSymbol()}) { + if (const auto *subprogram{ + std::get_if(&procSym->details())}) { + if (subprogram->isFunction()) { + return &subprogram->result(); + } + } + } + return nullptr; +} + int ProcedureDesignator::Rank() const { if (const Symbol * symbol{GetSymbol()}) { // Subtle: will be zero for functions returning procedure pointers diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1168,6 +1168,11 @@ sym{UnwrapWholeSymbolOrComponentOrCoarrayRef(expr)}) { return semantics::IsAllocatable(sym->GetUltimate()); } + if (const ProcedureRef * proc{GetProcedureRef(expr)}) { + if (const semantics::Symbol * sym{proc->GetResult()}) { + return semantics::IsAllocatable(*sym); + } + } return false; } diff --git a/flang/test/Semantics/allocated.f90 b/flang/test/Semantics/allocated.f90 --- a/flang/test/Semantics/allocated.f90 +++ b/flang/test/Semantics/allocated.f90 @@ -42,6 +42,7 @@ print *, allocated(coarray_alloc[2,3]) print *, allocated(t2_not_alloc%coarray_alloc) print *, allocated(t2_not_alloc%coarray_alloc[2]) + print *, allocated(return_allocatable()) !ERROR: Argument of ALLOCATED() must be an ALLOCATABLE object or component print *, allocated(not_alloc) @@ -61,6 +62,4 @@ print *, allocated(t2_not_alloc%coarray_alloc_array(1)) !ERROR: Argument of ALLOCATED() must be an ALLOCATABLE object or component print *, allocated(t2_not_alloc%coarray_alloc_array(1)[2]) - !ERROR: Argument of ALLOCATED() must be an ALLOCATABLE object or component - print *, allocated(return_allocatable()) end subroutine diff --git a/flang/test/Semantics/call06.f90 b/flang/test/Semantics/call06.f90 --- a/flang/test/Semantics/call06.f90 +++ b/flang/test/Semantics/call06.f90 @@ -37,8 +37,7 @@ call s01(scalar) !ERROR: ALLOCATABLE dummy argument 'x=' must be associated with an ALLOCATABLE actual argument call s01(1.) - !ERROR: ALLOCATABLE dummy argument 'x=' must be associated with an ALLOCATABLE actual argument - call s01(allofunc()) ! subtle: ALLOCATABLE function result isn't + call s01(allofunc()) ! ok call s02(cov) ! ok call s03(com) ! ok !ERROR: ALLOCATABLE dummy argument 'x=' has corank 1 but actual argument has corank 2