Skip to content

Commit e513412

Browse files
committed
[flang] Better recovery from errors in a loop control
When there's an error in a DO statement loop control, error recovery isn't great. A bare "DO" is a valid statement, so a failure to parse its loop control doesn't fail on the whole statement. Its partial parse ends after the keyword, and as some other statement parsers can get further into the input before failing, errors in the loop control can lead to confusing error messages about bad pointer assignment statements and others. So just check that a bare "DO" is followed by the end of the statement.
1 parent 6e48214 commit e513412

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

flang/lib/Parser/executable-parsers.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// Per-type parsers for executable statements
1010

1111
#include "basic-parsers.h"
12-
#include "debug-parser.h"
1312
#include "expr-parsers.h"
1413
#include "misc-parsers.h"
1514
#include "stmt-parser.h"
@@ -282,18 +281,26 @@ TYPE_CONTEXT_PARSER("loop control"_en_US,
282281
"CONCURRENT" >> concurrentHeader,
283282
many(Parser<LocalitySpec>{})))))
284283

284+
// "DO" is a valid statement, so the loop control is optional; but for
285+
// better recovery from errors in the loop control, don't parse a
286+
// DO statement with a bad loop control as a DO statement that has
287+
// no loop control and is followed by garbage.
288+
static constexpr auto loopControlOrEndOfStmt{
289+
construct<std::optional<LoopControl>>(Parser<LoopControl>{}) ||
290+
lookAhead(":\n"_ch) >> construct<std::optional<LoopControl>>()};
291+
285292
// R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control]
286293
// A label-do-stmt with a do-construct-name is parsed as a nonlabel-do-stmt
287294
// with an optional label.
288295
TYPE_CONTEXT_PARSER("label DO statement"_en_US,
289-
construct<LabelDoStmt>("DO" >> label, maybe(loopControl)))
296+
construct<LabelDoStmt>("DO" >> label, loopControlOrEndOfStmt))
290297

291298
// R1122 nonlabel-do-stmt -> [do-construct-name :] DO [loop-control]
292299
TYPE_CONTEXT_PARSER("nonlabel DO statement"_en_US,
293300
construct<NonLabelDoStmt>(
294-
name / ":", "DO" >> maybe(label), maybe(loopControl)) ||
301+
name / ":", "DO" >> maybe(label), loopControlOrEndOfStmt) ||
295302
construct<NonLabelDoStmt>(construct<std::optional<Name>>(),
296-
construct<std::optional<Label>>(), "DO" >> maybe(loopControl)))
303+
construct<std::optional<Label>>(), "DO" >> loopControlOrEndOfStmt))
297304

298305
// R1132 end-do-stmt -> END DO [do-construct-name]
299306
TYPE_CONTEXT_PARSER("END DO statement"_en_US,

flang/lib/Parser/type-parsers.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ constexpr Parser<ForallAssignmentStmt> forallAssignmentStmt; // R1053
102102
constexpr Parser<ForallStmt> forallStmt; // R1055
103103
constexpr Parser<Selector> selector; // R1105
104104
constexpr Parser<EndSelectStmt> endSelectStmt; // R1143 & R1151 & R1155
105-
constexpr Parser<LoopControl> loopControl; // R1123
106105
constexpr Parser<ConcurrentHeader> concurrentHeader; // R1125
107106
constexpr Parser<IoUnit> ioUnit; // R1201, R1203
108107
constexpr Parser<FileUnitNumber> fileUnitNumber; // R1202

flang/test/Parser/recovery07.f90

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
2+
! CHECK: error: expected ':'
3+
! CHECK: in the context: loop control
4+
do concurrent(I = 1, N)
5+
end do
6+
end

0 commit comments

Comments
 (0)