When computing the shape of an expression at compilation time as part of
folding an intrinsic function like SIZE(), don't create an expression that
increases a dependence on the presence of an optional dummy argument.
Differential Revision: https://reviews.llvm.org/D151737
if (call.Rank() == 0) {
return ScalarShape();
} else if (call.IsElemental()) {
- for (const auto &arg : call.arguments()) {
- if (arg && arg->Rank() > 0) {
- return (*this)(*arg);
+ // Use the shape of an actual array argument associated with a
+ // non-OPTIONAL dummy object argument.
+ if (context_) {
+ if (auto chars{characteristics::Procedure::FromActuals(
+ call.proc(), call.arguments(), *context_)}) {
+ std::size_t j{0};
+ for (const auto &arg : call.arguments()) {
+ if (arg && arg->Rank() > 0 && j < chars->dummyArguments.size() &&
+ !chars->dummyArguments[j].IsOptional()) {
+ return (*this)(*arg);
+ }
+ ++j;
+ }
}
}
return ScalarShape();
--- /dev/null
+! RUN: %flang_fc1 -fdebug-unparse %s 2>&1 | FileCheck %s
+! Ensure that optional arguments aren't used to fold SIZE() or SHAPE()
+module m
+ contains
+ subroutine sub(x,y)
+ real :: x(:), y(:)
+ optional x
+ !CHECK: PRINT *, int(size(y,dim=1,kind=8),kind=4)
+ print *, size(f(x,y))
+ end
+ elemental function f(x,y)
+ real, intent(in) :: x, y
+ optional x
+ f = y
+ end
+end