Skip to content

Commit ad26cde

Browse files
klauslerjeanPerier
authored andcommitted
[flang] Catch errors with intrinsic array inquiry functions
The intrinsic inquiry functions SIZE and UBOUND -- but not LBOUND -- require a DIM= argument if their first argument is an assumed-size array. The intrinsic SHAPE must not be used with an assumed-size array. Differential Revision: https://reviews.llvm.org/D109912
1 parent ed1a555 commit ad26cde

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,9 @@ ENUM_CLASS(Rank,
189189
shaped, // rank is length of SHAPE vector
190190
)
191191

192-
ENUM_CLASS(Optionality, required, optional, missing,
192+
ENUM_CLASS(Optionality, required,
193+
optional, // unless DIM= for SIZE(assumedSize)
194+
missing, // for DIM= cases like FINDLOC
193195
defaultsToSameKind, // for MatchingDefaultKIND
194196
defaultsToDefaultForResult, // for DefaultingKIND
195197
defaultsToSizeKind, // for SizeDefaultKIND
@@ -722,7 +724,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
722724
{"sind", {{"x", SameFloating}}, SameFloating},
723725
{"sinh", {{"x", SameFloating}}, SameFloating},
724726
{"size",
725-
{{"array", AnyData, Rank::anyOrAssumedRank}, OptionalDIM,
727+
{{"array", AnyData, Rank::anyOrAssumedRank},
728+
OptionalDIM, // unless array is assumed-size
726729
SizeDefaultKIND},
727730
KINDInt, Rank::scalar, IntrinsicClass::inquiryFunction},
728731
{"sizeof", {{"a", AnyData, Rank::anyOrAssumedRank}}, SubscriptInt,
@@ -1372,7 +1375,8 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
13721375
for (std::size_t j{0}; j < dummies; ++j) {
13731376
const IntrinsicDummyArgument &d{dummy[std::min(j, dummyArgPatterns - 1)]};
13741377
if (const ActualArgument * arg{actualForDummy[j]}) {
1375-
if (IsAssumedRank(*arg) && d.rank != Rank::anyOrAssumedRank) {
1378+
bool isAssumedRank{IsAssumedRank(*arg)};
1379+
if (isAssumedRank && d.rank != Rank::anyOrAssumedRank) {
13761380
messages.Say("Assumed-rank array cannot be forwarded to "
13771381
"'%s=' argument"_err_en_US,
13781382
d.keyword);
@@ -1443,14 +1447,39 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
14431447
argOk = rank == knownArg->Rank();
14441448
break;
14451449
case Rank::anyOrAssumedRank:
1450+
if (!hasDimArg && rank > 0 && !isAssumedRank &&
1451+
(std::strcmp(name, "shape") == 0 ||
1452+
std::strcmp(name, "size") == 0 ||
1453+
std::strcmp(name, "ubound") == 0)) {
1454+
// Check for an assumed-size array argument.
1455+
// These are disallowed for SHAPE, and require DIM= for
1456+
// SIZE and UBOUND.
1457+
// (A previous error message for UBOUND will take precedence
1458+
// over this one, as this error is caught by the second entry
1459+
// for UBOUND.)
1460+
if (std::optional<Shape> shape{GetShape(context, *arg)}) {
1461+
if (!shape->empty() && !shape->back().has_value()) {
1462+
if (strcmp(name, "shape") == 0) {
1463+
messages.Say(
1464+
"The '%s=' argument to the intrinsic function '%s' may not be assumed-size"_err_en_US,
1465+
d.keyword, name);
1466+
} else {
1467+
messages.Say(
1468+
"A dim= argument is required for '%s' when the array is assumed-size"_err_en_US,
1469+
name);
1470+
}
1471+
return std::nullopt;
1472+
}
1473+
}
1474+
}
14461475
argOk = true;
14471476
break;
14481477
case Rank::conformable: // arg must be conformable with previous arrayArg
14491478
CHECK(arrayArg);
14501479
CHECK(arrayArgName);
14511480
if (const std::optional<Shape> &arrayArgShape{
14521481
GetShape(context, *arrayArg)}) {
1453-
if (const std::optional<Shape> &argShape{GetShape(context, *arg)}) {
1482+
if (std::optional<Shape> argShape{GetShape(context, *arg)}) {
14541483
std::string arrayArgMsg{"'"};
14551484
arrayArgMsg = arrayArgMsg + arrayArgName + "='" + " argument";
14561485
std::string argMsg{"'"};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
! Miscellaneous constraint and requirement checking on intrinsics
3+
program test_size
4+
real, dimension(5, 5) :: array
5+
call test(array)
6+
contains
7+
subroutine test(arg)
8+
real, dimension(5, *) :: arg
9+
!ERROR: A dim= argument is required for 'size' when the array is assumed-size
10+
print *, size(arg)
11+
!ERROR: missing mandatory 'dim=' argument
12+
print *, ubound(arg)
13+
!ERROR: The 'source=' argument to the intrinsic function 'shape' may not be assumed-size
14+
print *, shape(arg)
15+
! But these cases are fine:
16+
print *, size(arg, dim=1)
17+
print *, ubound(arg, dim=1)
18+
print *, lbound(arg)
19+
print *, size(array)
20+
print *, ubound(array)
21+
print *, lbound(array)
22+
end subroutine
23+
end

0 commit comments

Comments
 (0)