Skip to content

Commit

Permalink
[flang] Don't emit false errors on LBOUND/UBOUND of assumed-rank arrays
Browse files Browse the repository at this point in the history
Folding of LBOUND/UBOUND on assumed-rank arrays could lead to bogus errors
later.  This is a regression from a recent change intended to ensure that
patently bad DIM= arguments were caught even in the case of assumed-rank.
Rearrange the order of checks so that those bad DIM= argument values are
caught but otherwise defer LBOUND/UBOUND of assumed-rank arguments to
run time.  (It was tempting to always fold LBOUND(ar,DIM=n) to 1, but
that would obscure the run time error required when 'n' is out of bounds,
including the case of a scalar 'ar'.)

Differential Revision: https://reviews.llvm.org/D156755
  • Loading branch information
klausler committed Aug 1, 2023
1 parent 05d613e commit f9fdd4f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 22 deletions.
45 changes: 25 additions & 20 deletions flang/lib/Evaluate/fold-integer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,21 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
using T = Type<TypeCategory::Integer, KIND>;
ActualArguments &args{funcRef.arguments()};
if (const auto *array{UnwrapExpr<Expr<SomeType>>(args[0])}) {
if (int rank{array->Rank()}; rank > 0 || IsAssumedRank(*array)) {
std::optional<int> dim;
if (funcRef.Rank() == 0) {
// Optional DIM= argument is present: result is scalar.
if (!CheckDimArg(args[1], *array, context.messages(), true, dim)) {
return MakeInvalidIntrinsic<T>(std::move(funcRef));
} else if (!dim) {
// DIM= is present but not constant, or error
return Expr<T>{std::move(funcRef)};
}
std::optional<int> dim;
if (funcRef.Rank() == 0) {
// Optional DIM= argument is present: result is scalar.
if (!CheckDimArg(args[1], *array, context.messages(), true, dim)) {
return MakeInvalidIntrinsic<T>(std::move(funcRef));
} else if (!dim) {
// DIM= is present but not constant, or error
return Expr<T>{std::move(funcRef)};
}
}
if (IsAssumedRank(*array)) {
// Would like to return 1 if DIM=.. is present, but that would be
// hiding a runtime error if the DIM= were too large (including
// the case of an assumed-rank argument that's scalar).
} else if (int rank{array->Rank()}; rank > 0) {
bool lowerBoundsAreOne{true};
if (auto named{ExtractNamedEntity(*array)}) {
const Symbol &symbol{named->GetLastSymbol()};
Expand Down Expand Up @@ -203,17 +207,18 @@ Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
using T = Type<TypeCategory::Integer, KIND>;
ActualArguments &args{funcRef.arguments()};
if (auto *array{UnwrapExpr<Expr<SomeType>>(args[0])}) {
if (int rank{array->Rank()}; rank > 0 || IsAssumedRank(*array)) {
std::optional<int> dim;
if (funcRef.Rank() == 0) {
// Optional DIM= argument is present: result is scalar.
if (!CheckDimArg(args[1], *array, context.messages(), false, dim)) {
return MakeInvalidIntrinsic<T>(std::move(funcRef));
} else if (!dim) {
// DIM= is present but not constant
return Expr<T>{std::move(funcRef)};
}
std::optional<int> dim;
if (funcRef.Rank() == 0) {
// Optional DIM= argument is present: result is scalar.
if (!CheckDimArg(args[1], *array, context.messages(), false, dim)) {
return MakeInvalidIntrinsic<T>(std::move(funcRef));
} else if (!dim) {
// DIM= is present but not constant, or error
return Expr<T>{std::move(funcRef)};
}
}
if (IsAssumedRank(*array)) {
} else if (int rank{array->Rank()}; rank > 0) {
bool takeBoundsFromShape{true};
if (auto named{ExtractNamedEntity(*array)}) {
const Symbol &symbol{named->GetLastSymbol()};
Expand Down
8 changes: 6 additions & 2 deletions flang/test/Evaluate/errors01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ module m
real x
end type t
contains
subroutine s1(a,b)
real :: a(*), b(:)
subroutine s1(a,b,c)
real :: a(*), b(:), c(..)
!CHECK: error: DIM=1 dimension is out of range for rank-1 assumed-size array
integer :: ub1(ubound(a,1))
!CHECK-NOT: error: DIM=1 dimension is out of range for rank-1 assumed-size array
Expand All @@ -20,6 +20,10 @@ subroutine s1(a,b)
integer :: lb2(lbound(b,0))
!CHECK: error: DIM=2 dimension is out of range for rank-1 array
integer :: lb3(lbound(b,2))
!CHECK: error: DIM=0 dimension must be positive
integer :: lb4(lbound(c,0))
!CHECK: error: DIM=666 dimension is too large for any array (maximum rank 15)
integer :: lb4(lbound(c,666))
end subroutine
subroutine s2
integer, parameter :: array(2,3) = reshape([(j, j=1, 6)], shape(array))
Expand Down

0 comments on commit f9fdd4f

Please sign in to comment.