[flang] Accept sparse argument keyword names for MAX/MIN

Accept any keyword argument names of the form "An" for
values of n >= 3 in calls to the intrinsic functions MAX, MIN,
and their variants, so long as "n" has no leading zero and
all the keywords are distinct.  Previously, f18 was needlessly
requiring the names to be contiguous.  When synthesizing keywords
to characterize the procedure's interface, don't conflict with
the program's keywords.

Differential Revision: https://reviews.llvm.org/D117701
This commit is contained in:
Peter Klausler 2022-01-11 12:28:35 -08:00
parent e084679f96
commit bddfb81a31
2 changed files with 19 additions and 6 deletions

View file

@ -1183,7 +1183,7 @@ static DynamicType GetBuiltinDerivedType(
}
// Ensure that the keywords of arguments to MAX/MIN and their variants
// are of the form A123 with no duplicates.
// are of the form A123 with no duplicates or leading zeroes.
static bool CheckMaxMinArgument(std::optional<parser::CharBlock> keyword,
std::set<parser::CharBlock> &set, const char *intrinsicName,
parser::ContextualMessages &messages) {
@ -1191,7 +1191,7 @@ static bool CheckMaxMinArgument(std::optional<parser::CharBlock> keyword,
std::size_t j{1};
for (; j < keyword->size(); ++j) {
char ch{(*keyword)[j]};
if (ch < '0' || ch > '9') {
if (ch < (j == 1 ? '1' : '0') || ch > '9') {
break;
}
}
@ -1808,8 +1808,19 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (const auto &arg{rearranged[j]}) {
if (const Expr<SomeType> *expr{arg->UnwrapExpr()}) {
std::string kw{d.keyword};
if (isMaxMin) {
kw = "a"s + std::to_string(j + 1);
if (arg->keyword()) {
kw = arg->keyword()->ToString();
} else if (isMaxMin) {
for (std::size_t k{j + 1};; ++k) {
kw = "a"s + std::to_string(k);
auto iter{std::find_if(dummyArgs.begin(), dummyArgs.end(),
[&kw](const characteristics::DummyArgument &prev) {
return prev.name == kw;
})};
if (iter == dummyArgs.end()) {
break;
}
}
}
auto dc{characteristics::DummyArgument::FromActual(
std::move(kw), *expr, context)};

View file

@ -5,6 +5,8 @@ real :: x = 0.0 ! prevent folding
print *, max(a1=x,a1=1)
!ERROR: Keyword argument 'a1=' has already been specified positionally (#1) in this procedure reference
print *, max(x,a1=1)
!ERROR: Argument keyword 'a6=' is not recognized for this procedure reference
print *, max(a1=x,a2=0,a3=0,a4=0,a6=0)
print *, max(a1=x,a2=0,a4=0) ! ok
print *, max(x,0,a99=0) ! ok
!ERROR: Argument keyword 'a06=' is not known in call to 'max'
print *, max(a1=x,a2=0,a06=0)
end