Skip to content

Commit b5aea32

Browse files
authored
[flang] Improve error recovery for bad statement after CONTAINS (#109698)
After a CONTAINS statement in a program unit, a statement that cannot begin a subprogram will trigger catastrophic error recovery. But the compiler is presently emitting multiple errors for the same location about expected variations of END statements. Emit fewer messages. Fixes #109609.
1 parent 1094ee7 commit b5aea32

File tree

3 files changed

+77
-12
lines changed

3 files changed

+77
-12
lines changed

flang/lib/Parser/program-parsers.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,9 @@ TYPE_CONTEXT_PARSER("PROGRAM statement"_en_US,
249249

250250
// R1403 end-program-stmt -> END [PROGRAM [program-name]]
251251
TYPE_CONTEXT_PARSER("END PROGRAM statement"_en_US,
252-
construct<EndProgramStmt>(recovery(
253-
"END PROGRAM" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
252+
construct<EndProgramStmt>(
253+
recovery("END" >> defaulted("PROGRAM" >> maybe(name)) / atEndOfStmt,
254+
progUnitEndStmtErrorRecovery)))
254255

255256
// R1404 module ->
256257
// module-stmt [specification-part] [module-subprogram-part]
@@ -266,8 +267,9 @@ TYPE_CONTEXT_PARSER(
266267

267268
// R1406 end-module-stmt -> END [MODULE [module-name]]
268269
TYPE_CONTEXT_PARSER("END MODULE statement"_en_US,
269-
construct<EndModuleStmt>(recovery(
270-
"END MODULE" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
270+
construct<EndModuleStmt>(
271+
recovery("END" >> defaulted("MODULE" >> maybe(name)) / atEndOfStmt,
272+
progUnitEndStmtErrorRecovery)))
271273

272274
// R1407 module-subprogram-part -> contains-stmt [module-subprogram]...
273275
TYPE_CONTEXT_PARSER("module subprogram part"_en_US,
@@ -334,7 +336,7 @@ TYPE_PARSER(construct<ParentIdentifier>(name, maybe(":" >> name)))
334336
// R1419 end-submodule-stmt -> END [SUBMODULE [submodule-name]]
335337
TYPE_CONTEXT_PARSER("END SUBMODULE statement"_en_US,
336338
construct<EndSubmoduleStmt>(
337-
recovery("END SUBMODULE" >> maybe(name) || bareEnd,
339+
recovery("END" >> defaulted("SUBMODULE" >> maybe(name)) / atEndOfStmt,
338340
progUnitEndStmtErrorRecovery)))
339341

340342
// R1420 block-data -> block-data-stmt [specification-part] end-block-data-stmt
@@ -350,7 +352,7 @@ TYPE_CONTEXT_PARSER("BLOCK DATA statement"_en_US,
350352
// R1422 end-block-data-stmt -> END [BLOCK DATA [block-data-name]]
351353
TYPE_CONTEXT_PARSER("END BLOCK DATA statement"_en_US,
352354
construct<EndBlockDataStmt>(
353-
recovery("END BLOCK DATA" >> maybe(name) || bareEnd,
355+
recovery("END" >> defaulted("BLOCK DATA" >> maybe(name)) / atEndOfStmt,
354356
progUnitEndStmtErrorRecovery)))
355357

356358
// R1501 interface-block ->
@@ -564,8 +566,9 @@ TYPE_PARSER(construct<Suffix>(
564566
"RESULT" >> parenthesized(name), maybe(languageBindingSpec)))
565567

566568
// R1533 end-function-stmt -> END [FUNCTION [function-name]]
567-
TYPE_PARSER(construct<EndFunctionStmt>(recovery(
568-
"END FUNCTION" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
569+
TYPE_PARSER(construct<EndFunctionStmt>(
570+
recovery("END" >> defaulted("FUNCTION" >> maybe(name)) / atEndOfStmt,
571+
progUnitEndStmtErrorRecovery)))
569572

570573
// R1534 subroutine-subprogram ->
571574
// subroutine-stmt [specification-part] [execution-part]
@@ -591,8 +594,9 @@ TYPE_PARSER(
591594
TYPE_PARSER(construct<DummyArg>(name) || construct<DummyArg>(star))
592595
593596
// R1537 end-subroutine-stmt -> END [SUBROUTINE [subroutine-name]]
594-
TYPE_PARSER(construct<EndSubroutineStmt>(recovery(
595-
"END SUBROUTINE" >> maybe(name) || bareEnd, progUnitEndStmtErrorRecovery)))
597+
TYPE_PARSER(construct<EndSubroutineStmt>(
598+
recovery("END" >> defaulted("SUBROUTINE" >> maybe(name)) / atEndOfStmt,
599+
progUnitEndStmtErrorRecovery)))
596600
597601
// R1538 separate-module-subprogram ->
598602
// mp-subprogram-stmt [specification-part] [execution-part]
@@ -609,7 +613,7 @@ TYPE_CONTEXT_PARSER("MODULE PROCEDURE statement"_en_US,
609613
// R1540 end-mp-subprogram-stmt -> END [PROCEDURE [procedure-name]]
610614
TYPE_CONTEXT_PARSER("END PROCEDURE statement"_en_US,
611615
construct<EndMpSubprogramStmt>(
612-
recovery("END PROCEDURE" >> maybe(name) || bareEnd,
616+
recovery("END" >> defaulted("PROCEDURE" >> maybe(name)) / atEndOfStmt,
613617
progUnitEndStmtErrorRecovery)))
614618
615619
// R1541 entry-stmt -> ENTRY entry-name [( [dummy-arg-list] ) [suffix]]

flang/lib/Parser/stmt-parser.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ constexpr auto executionPartErrorRecovery{stmtErrorRecoveryStart >>
9090
// END statement error recovery
9191
constexpr auto missingOptionalName{pure<std::optional<Name>>()};
9292
constexpr auto noNameEnd{"END" >> missingOptionalName};
93-
constexpr auto bareEnd{noNameEnd / recovery(atEndOfStmt, SkipTo<'\n'>{})};
9493

9594
// For unrecognizable construct END statements. Be sure to not consume
9695
// a program unit's END statement.

flang/test/Parser/recovery06.f90

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
2+
program p
3+
contains
4+
! CHECK: error: expected 'END'
5+
! CHECK: in the context: END PROGRAM statement
6+
continue
7+
end
8+
9+
subroutine s
10+
contains
11+
! CHECK: error: expected 'END'
12+
! CHECK: in the context: SUBROUTINE subprogram
13+
continue
14+
end
15+
16+
function f()
17+
contains
18+
! CHECK: error: expected 'END'
19+
! CHECK: in the context: FUNCTION subprogram
20+
continue
21+
end
22+
23+
module m
24+
interface
25+
module subroutine ms
26+
end
27+
end interface
28+
contains
29+
! CHECK: error: expected 'END'
30+
! CHECK: in the context: END MODULE statement
31+
continue
32+
end
33+
34+
module m2
35+
contains
36+
subroutine m2s
37+
contains
38+
! CHECK: error: expected 'END'
39+
! CHECK: in the context: SUBROUTINE subprogram
40+
continue
41+
end
42+
end
43+
44+
submodule(m) s1
45+
contains
46+
! CHECK: error: expected 'END'
47+
! CHECK: in the context: END SUBMODULE statement
48+
continue
49+
end
50+
51+
submodule(m) s2
52+
contains
53+
module procedure ms
54+
contains
55+
! CHECK: error: expected 'END'
56+
! CHECK: in the context: END PROCEDURE statement
57+
continue
58+
end
59+
end
60+
61+
! Ensure no error cascade
62+
! CHECK-NOT: error:

0 commit comments

Comments
 (0)