From 81c66933292b8f7ea105122f39e0a06038744a88 Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Wed, 19 Jan 2022 19:12:12 +0100 Subject: [PATCH] [flang] Prevent any non constant result extent to be inlined on caller side 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 --- flang/lib/Evaluate/shape.cpp | 11 +++++------ flang/test/Evaluate/rewrite01.f90 | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp index 3411933..21db9a4 100644 --- a/flang/lib/Evaluate/shape.cpp +++ b/flang/lib/Evaluate/shape.cpp @@ -560,13 +560,12 @@ auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result { if (subp.isFunction()) { auto resultShape{(*this)(subp.result())}; if (resultShape && !useResultSymbolShape_) { - // Ensure the shape does not contain descriptor inquiries, they - // may refer to symbols belonging to the called subprogram scope - // that are meaningless on the caller side without the related - // call expression. + // Ensure the shape is constant. Otherwise, it may be referring + // to symbols that belong to the subroutine scope and are + // meaningless on the caller side without the related call + // expression. for (auto extent : *resultShape) { - if (extent && - std::holds_alternative(extent->u)) { + if (extent && !IsConstantExpr(*extent)) { return std::nullopt; } } diff --git a/flang/test/Evaluate/rewrite01.f90 b/flang/test/Evaluate/rewrite01.f90 index 5890d37..f5fc578 100644 --- a/flang/test/Evaluate/rewrite01.f90 +++ b/flang/test/Evaluate/rewrite01.f90 @@ -12,6 +12,17 @@ function returns_array(n, m) returns_array = 0 end function +function returns_array_2(n) + integer, intent(in) :: n + integer :: returns_array_2(n) + returns_array_2 = 0 +end function + +function returns_array_3() + integer :: returns_array_3(7:46+2) + returns_array_3 = 0 +end function + subroutine ubound_test(x, n, m) integer :: x(n, m) !CHECK: PRINT *, [INTEGER(4)::int(size(x,dim=1),kind=4),int(size(x,dim=2),kind=4)] @@ -20,6 +31,10 @@ subroutine ubound_test(x, n, m) print *, ubound(returns_array(n, m)) !CHECK: PRINT *, ubound(returns_array(n,m),dim=1_4) print *, ubound(returns_array(n, m), dim=1) + !CHECK: PRINT *, ubound(returns_array_2(m)) + print *, ubound(returns_array_2(m)) + !CHECK: PRINT *, 42_8 + print *, ubound(returns_array_3(), dim=1, kind=8) end subroutine subroutine size_test(x, n, m) @@ -30,6 +45,10 @@ subroutine size_test(x, n, m) print *, size(returns_array(n, m)) !CHECK: PRINT *, size(returns_array(n,m),dim=1_4) print *, size(returns_array(n, m), dim=1) + !CHECK: PRINT *, size(returns_array_2(m)) + print *, size(returns_array_2(m)) + !CHECK: PRINT *, 42_8 + print *, size(returns_array_3(), kind=8) end subroutine subroutine shape_test(x, n, m) @@ -38,6 +57,10 @@ subroutine shape_test(x, n, m) print *, shape(x) !CHECK: PRINT *, shape(returns_array(n,m)) print *, shape(returns_array(n, m)) + !CHECK: PRINT *, shape(returns_array_2(m)) + print *, shape(returns_array_2(m)) + !CHECK: PRINT *, [INTEGER(8)::42_8] + print *, shape(returns_array_3(), kind=8) end subroutine subroutine lbound_test(x, n, m) @@ -48,5 +71,9 @@ subroutine lbound_test(x, n, m) print *, lbound(returns_array(n, m)) !CHECK: PRINT *, 1_4 print *, lbound(returns_array(n, m), dim=1) + !CHECK: PRINT *, 1_4 + print *, lbound(returns_array_2(m), dim=1) + !CHECK: PRINT *, 1_4 + print *, lbound(returns_array_3(), dim=1) end subroutine end module -- 2.7.4