LEN(f(...)), where "f" is a non-intrinsic function, should not be folded
to anything else unless the result is a known constant value. While there
are conceivable cases in which we could do better (e.g., an internal function
whose length is a host-associated INTENT(IN) dummy argument), there are
other cases that we're getting wrong.
Differential Revision: https://reviews.llvm.org/D128759
A recent fix beefed up semantics checking to catch the case of a call
to an external assumed-length character function; this check has false
positives in the case of an assumed-length character function that is
a dummy procedure. These do have a length that is passed in extra
compiler-created arguments. This patch refines the check and undoes some
changes to tests.
Differential Revision: https://reviews.llvm.org/D126390
Semantics was allowing calls to CHARACTER(*) functions, which are odd
things -- they can be declared, and passed around, but can never actually
be called as such. They must be redeclared with an explicit length that
ends up being passed as a hidden argument. So check for these calls
and diagnose them, add tests, and clean up some existing tests that
were in error and now get caught.
Possible TODO for lowering: there were some test cases that used
bad calls to assumed-length CHARACTER*(*) functions and validated
their implementations. I've removed some, and adjusted another,
but the code that somehow implemented these calls may need to be
removed and replaced with an assert about bad semantics.
Differential Revision: https://reviews.llvm.org/D126148
When a procedure pointer or procedure dummy argument has a
defined interface, the rank of the pointer (or dummy) is the
rank of the interface.
Also tweak code discovered in shape analysis when investigating
this problam so that it returns a vector of emptied extents rather
than std::nullopt when the extents are not scope-invariant, so that
the rank can at least be known.
Differential Revision: https://reviews.llvm.org/D123727
GetLowerBoundHelper rewrite in https://reviews.llvm.org/D121488 was
incorrect with POINTER/ALLOCATABLE components. The rewrite created a
descriptor inquiry to the component symbol only instead of the whole
named entity. The base information was lost, and not retrievable.
LBOUND(a(10)%p) became LBOUND(p).
Fix this regression, and also update DescriptorInquiry unparsing to
carry the kind information. DescriptorInquiries are KIND 8 expressions,
while LBOUND/SIZE/RANK, %LEN are default kind expressions.
This caused `print *,lbound(x,kind=8)` to unparse as `print*,lbound(x)` which is not
semantically the same (this unparsing issue was not an issue for
lowering, but I noticed it while writing my regression test).
Differential Revision: https://reviews.llvm.org/D122406
Similarly to LBOUND in https://reviews.llvm.org/D121488, UBOUND must
return zero for an empty dimension, no matter the specification
expression.
Add a GetUBOUND method to be used in expression rewrite that prevents
folding UBOUND to a bound specification expression if the extent is
not a compile time constant.
Fold the case where the extents is known to be zero (and also deal with
this case in LBOUND since we can and should to comply with constant
expression requirements).
Differential Revision: https://reviews.llvm.org/D122242
arguments even in situations where the arguments are required to compute
the LEN value at runtime.
Add tests.
Differential Revision: https://reviews.llvm.org/D119373
UBOUND, SIZE, and SHAPE folding was still creating expressions that are
invalid on the caller side without the call expression context.
A previous patch intended to deal with this situation (https://reviews.llvm.org/D116933)
but it assumed the return expression would be a descriptor inquiry to
the result symbol, which is not the case if the extent expression is
"scope invariant" inside the called subroutine (e.g., referring to
intent(in) dummy arguments). Simply prevent folding from inlining non
constant extent expression on the caller side.
Folding could be later improved by having ad-hoc folding for UBOUND, SIZE, and
SHAPE on function references where it could try replacing the dummy symbols
by the actual expression, but this is left as a possible later improvement.
Differential Revision: https://reviews.llvm.org/D117686
Currently, something like `print *, size(foo(n,m))` was rewritten
to `print *, size(foo_result_symbol)` when foo result is a non constant
shape array. This cannot be processed by lowering or reprocessed by a
Fortran compiler since the syntax is wrong (`foo_result_symbol` is
unknown on the caller side) and the arguments are lost when they might
be required to compute the result shape.
It is not possible (and probably not desired) to make GetShape fail in
general in such case since returning nullopt seems only expected for
scalars or assumed rank (see GetRank usage in lib/Semantics/check-call.cpp),
and returning a vector with nullopt extent may trigger some checks to
believe they are facing an assumed size (like here in intrinsic argument
checks: 196204c72c/flang/lib/Evaluate/intrinsics.cpp (L1530)).
Hence, I went for a solution that limits the rewrite change to folding
(where the original expression is returned if the shape depends on a non
constant shape from a call).
I added a non default option to GetShapeHelper that prevents the rewrite
of shape inquiry on calls to descriptor inquiries. At first I wanted to
avoid touching GetShapeHelper, but it would require to re-implement all
its logic to determine if the shape comes from a function call or not
(the expression could be `size(1+foo(n,m))`). So added an alternate
entry point to GetShapeHelper seemed the cleanest solution to me.
Differential Revision: https://reviews.llvm.org/D116933