Skip to content

Commit fffbabf

Browse files
authored
[flang][parser] Better error recovery for misplaced declaration (#100482)
When a declaration construct appears in the execution part of a block or subprogram body, report it as such rather than as a misleading syntax error on the executable statement that it somehow matched the most.
1 parent 1e5334b commit fffbabf

File tree

3 files changed

+44
-35
lines changed

3 files changed

+44
-35
lines changed

flang/lib/Parser/executable-parsers.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,19 @@ constexpr auto obsoleteExecutionPartConstruct{recovery(ignoredStatementPrefix >>
6767
parenthesized(nonemptyList(Parser<AllocateShapeSpec>{}))))))};
6868

6969
TYPE_PARSER(recovery(
70-
withMessage("expected execution part construct"_err_en_US,
71-
CONTEXT_PARSER("execution part construct"_en_US,
72-
first(construct<ExecutionPartConstruct>(executableConstruct),
70+
CONTEXT_PARSER("execution part construct"_en_US,
71+
first(construct<ExecutionPartConstruct>(executableConstruct),
72+
construct<ExecutionPartConstruct>(statement(indirect(formatStmt))),
73+
construct<ExecutionPartConstruct>(statement(indirect(entryStmt))),
74+
construct<ExecutionPartConstruct>(statement(indirect(dataStmt))),
75+
extension<LanguageFeature::ExecutionPartNamelist>(
76+
"nonstandard usage: NAMELIST in execution part"_port_en_US,
7377
construct<ExecutionPartConstruct>(
74-
statement(indirect(formatStmt))),
75-
construct<ExecutionPartConstruct>(
76-
statement(indirect(entryStmt))),
77-
construct<ExecutionPartConstruct>(
78-
statement(indirect(dataStmt))),
79-
extension<LanguageFeature::ExecutionPartNamelist>(
80-
"nonstandard usage: NAMELIST in execution part"_port_en_US,
81-
construct<ExecutionPartConstruct>(
82-
statement(indirect(Parser<NamelistStmt>{})))),
83-
obsoleteExecutionPartConstruct))),
78+
statement(indirect(Parser<NamelistStmt>{})))),
79+
obsoleteExecutionPartConstruct,
80+
lookAhead(declarationConstruct) >> SkipTo<'\n'>{} >>
81+
fail<ExecutionPartConstruct>(
82+
"misplaced declaration in the execution part"_err_en_US))),
8483
construct<ExecutionPartConstruct>(executionPartErrorRecovery)))
8584

8685
// R509 execution-part -> executable-construct [execution-part-construct]...

flang/lib/Parser/program-parsers.cpp

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,6 @@ TYPE_PARSER(
6666
normalProgramUnit) /
6767
skipStuffBeforeStatement))
6868

69-
// R504 specification-part ->
70-
// [use-stmt]... [import-stmt]... [implicit-part]
71-
// [declaration-construct]...
72-
TYPE_CONTEXT_PARSER("specification part"_en_US,
73-
construct<SpecificationPart>(many(openaccDeclarativeConstruct),
74-
many(openmpDeclarativeConstruct), many(indirect(compilerDirective)),
75-
many(statement(indirect(Parser<UseStmt>{}))),
76-
many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
77-
implicitPart, many(declarationConstruct)))
78-
7969
// R507 declaration-construct ->
8070
// specification-construct | data-stmt | format-stmt |
8171
// entry-stmt | stmt-function-stmt
@@ -106,18 +96,29 @@ constexpr auto misplacedSpecificationStmt{Parser<UseStmt>{} >>
10696
fail<DeclarationConstruct>(
10797
"IMPLICIT statements must follow USE and IMPORT and precede all other declarations"_err_en_US)};
10898

109-
TYPE_PARSER(recovery(
110-
withMessage("expected declaration construct"_err_en_US,
111-
CONTEXT_PARSER("declaration construct"_en_US,
112-
first(construct<DeclarationConstruct>(specificationConstruct),
113-
construct<DeclarationConstruct>(statement(indirect(dataStmt))),
114-
construct<DeclarationConstruct>(
115-
statement(indirect(formatStmt))),
116-
construct<DeclarationConstruct>(statement(indirect(entryStmt))),
117-
construct<DeclarationConstruct>(
118-
statement(indirect(Parser<StmtFunctionStmt>{}))),
119-
misplacedSpecificationStmt))),
120-
construct<DeclarationConstruct>(declErrorRecovery)))
99+
TYPE_CONTEXT_PARSER("declaration construct"_en_US,
100+
first(construct<DeclarationConstruct>(specificationConstruct),
101+
construct<DeclarationConstruct>(statement(indirect(dataStmt))),
102+
construct<DeclarationConstruct>(statement(indirect(formatStmt))),
103+
construct<DeclarationConstruct>(statement(indirect(entryStmt))),
104+
construct<DeclarationConstruct>(
105+
statement(indirect(Parser<StmtFunctionStmt>{}))),
106+
misplacedSpecificationStmt))
107+
108+
constexpr auto recoveredDeclarationConstruct{
109+
recovery(withMessage("expected declaration construct"_err_en_US,
110+
declarationConstruct),
111+
construct<DeclarationConstruct>(declErrorRecovery))};
112+
113+
// R504 specification-part ->
114+
// [use-stmt]... [import-stmt]... [implicit-part]
115+
// [declaration-construct]...
116+
TYPE_CONTEXT_PARSER("specification part"_en_US,
117+
construct<SpecificationPart>(many(openaccDeclarativeConstruct),
118+
many(openmpDeclarativeConstruct), many(indirect(compilerDirective)),
119+
many(statement(indirect(Parser<UseStmt>{}))),
120+
many(unambiguousStatement(indirect(Parser<ImportStmt>{}))),
121+
implicitPart, many(recoveredDeclarationConstruct)))
121122

122123
// R507 variant of declaration-construct for use in limitedSpecificationPart.
123124
constexpr auto invalidDeclarationStmt{formatStmt >>

flang/test/Parser/recovery03.f90

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
2+
! CHECK: error: misplaced declaration in the execution part
3+
! CHECK: real, pointer :: p2(:,:)
4+
! CHECK: in the context: execution part construct
5+
real, allocatable, target :: a2(:,:)
6+
allocate(a2(2:11,0:9))
7+
real, pointer :: p2(:,:)
8+
p2 => a2(2:3,1:2)
9+
end

0 commit comments

Comments
 (0)