Skip to content

Commit e3b6b92

Browse files
committed
[flang] Emit error when a positional actual argument follows an argument with a keyword
A positional (non-keyword) actual argument or alternate return label is not allowed to follow an actual argument with a keyword. Differential Revision: https://reviews.llvm.org/D146575
1 parent 982614f commit e3b6b92

File tree

9 files changed

+46
-17
lines changed

9 files changed

+46
-17
lines changed

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,25 +1543,39 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
15431543
dummy[dummyArgPatterns - 1].optionality == Optionality::repeats};
15441544
std::vector<ActualArgument *> actualForDummy(
15451545
isMaxMin ? 0 : dummyArgPatterns, nullptr);
1546-
int missingActualArguments{0};
1546+
bool anyMissingActualArgument{false};
15471547
std::set<parser::CharBlock> maxMinKeywords;
1548+
bool anyKeyword{false};
1549+
int which{0};
15481550
for (std::optional<ActualArgument> &arg : arguments) {
1549-
if (!arg) {
1550-
++missingActualArguments;
1551-
} else if (arg->isAlternateReturn()) {
1552-
messages.Say(arg->sourceLocation(),
1553-
"alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
1554-
name);
1555-
return std::nullopt;
1556-
} else if (isMaxMin) {
1551+
++which;
1552+
if (arg) {
1553+
if (arg->isAlternateReturn()) {
1554+
messages.Say(arg->sourceLocation(),
1555+
"alternate return specifier not acceptable on call to intrinsic '%s'"_err_en_US,
1556+
name);
1557+
return std::nullopt;
1558+
}
1559+
if (arg->keyword()) {
1560+
anyKeyword = true;
1561+
} else if (anyKeyword) {
1562+
messages.Say(arg ? arg->sourceLocation() : std::nullopt,
1563+
"actual argument #%d without a keyword may not follow an actual argument with a keyword"_err_en_US,
1564+
which);
1565+
return std::nullopt;
1566+
}
1567+
} else {
1568+
anyMissingActualArgument = true;
1569+
continue;
1570+
}
1571+
if (isMaxMin) {
15571572
if (CheckMaxMinArgument(arg->keyword(), maxMinKeywords, name, messages)) {
15581573
actualForDummy.push_back(&*arg);
15591574
} else {
15601575
return std::nullopt;
15611576
}
15621577
} else {
15631578
bool found{false};
1564-
int slot{missingActualArguments};
15651579
for (std::size_t j{0}; j < dummyArgPatterns && !found; ++j) {
15661580
if (dummy[j].optionality == Optionality::missing) {
15671581
continue;
@@ -1584,7 +1598,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
15841598
}
15851599
}
15861600
} else {
1587-
found = !actualForDummy[j] && slot-- == 0;
1601+
found = !actualForDummy[j] && !anyMissingActualArgument;
15881602
}
15891603
if (found) {
15901604
actualForDummy[j] = &*arg;

flang/lib/Semantics/check-call.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,11 @@ static void RearrangeArguments(const characteristics::Procedure &proc,
873873
actuals.size(), proc.dummyArguments.size());
874874
}
875875
std::map<std::string, evaluate::ActualArgument> kwArgs;
876+
bool anyKeyword{false};
877+
int which{1};
876878
for (auto &x : actuals) {
877-
if (x && x->keyword()) {
879+
if (!x) {
880+
} else if (x->keyword()) {
878881
auto emplaced{
879882
kwArgs.try_emplace(x->keyword()->ToString(), std::move(*x))};
880883
if (!emplaced.second) {
@@ -883,7 +886,13 @@ static void RearrangeArguments(const characteristics::Procedure &proc,
883886
*x->keyword());
884887
}
885888
x.reset();
889+
anyKeyword = true;
890+
} else if (anyKeyword) {
891+
messages.Say(x ? x->sourceLocation() : std::nullopt,
892+
"Actual argument #%d without a keyword may not follow any actual argument with a keyword"_err_en_US,
893+
which);
886894
}
895+
++which;
887896
}
888897
if (!kwArgs.empty()) {
889898
int index{0};

flang/test/Evaluate/fold-ishftc.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
! RUN: %python %S/test_folding.py %s %flang_fc1
22
! Tests folding of ISHFTC
33
module m
4-
integer, parameter :: shift8s(*) = ishftc(257, shift = [(ict, ict = -8, 8)], 8)
4+
integer, parameter :: shift8s(*) = ishftc(257, shift = [(ict, ict = -8, 8)], size=8)
55
integer, parameter :: expect1(*) = 256 + [1, 2, 4, 8, 16, 32, 64, 128, &
66
1, 2, 4, 8, 16, 32, 64, 128, 1]
77
logical, parameter :: test_1 = all(shift8s == expect1)

flang/test/Semantics/collectives01.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ program test_co_sum
135135
!ERROR: 'errmsg=' argument has unacceptable rank 1
136136
call co_sum(d, errmsg=character_array)
137137

138-
!ERROR: too many actual arguments for intrinsic 'co_sum'
138+
!ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
139139
call co_sum(r, result_image=1, stat=status, errmsg=message, 3.4)
140140

141141
! keyword argument with incorrect name

flang/test/Semantics/collectives02.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ program test_co_min
120120
!ERROR: 'errmsg=' argument has unacceptable rank 1
121121
call co_min(d, errmsg=character_array)
122122

123-
!ERROR: too many actual arguments for intrinsic 'co_min'
123+
!ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
124124
call co_min(r, result_image=1, stat=status, errmsg=message, 3.4)
125125

126126
!ERROR: unknown keyword argument to intrinsic 'co_min'

flang/test/Semantics/collectives03.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ program test_co_max
120120
!ERROR: 'errmsg=' argument has unacceptable rank 1
121121
call co_max(d, errmsg=character_array)
122122

123-
!ERROR: too many actual arguments for intrinsic 'co_max'
123+
!ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
124124
call co_max(r, result_image=1, stat=status, errmsg=message, 3.4)
125125

126126
!ERROR: unknown keyword argument to intrinsic 'co_max'

flang/test/Semantics/collectives04.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ program test_co_broadcast
126126
!ERROR: 'errmsg=' argument has unacceptable rank 1
127127
call co_broadcast(d, errmsg=character_array, source_image=1)
128128

129-
!ERROR: too many actual arguments for intrinsic 'co_broadcast'
129+
!ERROR: actual argument #5 without a keyword may not follow an actual argument with a keyword
130130
call co_broadcast(r, source_image=1, stat=status, errmsg=message, 3.4)
131131

132132
!ERROR: unknown keyword argument to intrinsic 'co_broadcast'

flang/test/Semantics/lcobound.f90

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,11 @@ program lcobound_tests
104104
!ERROR: missing mandatory 'coarray=' argument
105105
n = lcobound(dim=i, kind=c_int32_t)
106106

107+
!ERROR: actual argument #2 without a keyword may not follow an actual argument with a keyword
107108
n = lcobound(coarray=scalar_coarray, i)
108109

110+
n = lcobound(coarray=scalar_coarray, dim=i)
111+
109112
!ERROR: missing mandatory 'coarray=' argument
110113
lcobounds = lcobound()
111114

flang/test/Semantics/ucobound.f90

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,11 @@ program ucobound_tests
104104
!ERROR: missing mandatory 'coarray=' argument
105105
n = ucobound(dim=i, kind=c_int32_t)
106106

107+
!ERROR: actual argument #2 without a keyword may not follow an actual argument with a keyword
107108
n = ucobound(coarray=scalar_coarray, i)
108109

110+
n = ucobound(coarray=scalar_coarray, dim=i)
111+
109112
!ERROR: missing mandatory 'coarray=' argument
110113
ucobounds = ucobound()
111114

0 commit comments

Comments
 (0)