Skip to content

Commit 9ca98f4

Browse files
authored
Merge pull request #23368 from akyrtzi/comment-parsestmt-isstartofstmt
[parser] Add comments that parseStmt() and isStartOfStmt() must be kept in sync, and assertion the parseStmt() makes progress
2 parents e8d474a + 5b58d71 commit 9ca98f4

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

include/swift/Parse/Parser.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,22 @@ class Parser {
230230
// Cut off parsing by acting as if we reached the end-of-file.
231231
Tok.setKind(tok::eof);
232232
}
233-
233+
234+
/// Use this to assert that the parser has advanced the lexing location, e.g.
235+
/// before a specific parser function has returned.
236+
class AssertParserMadeProgressBeforeLeavingScopeRAII {
237+
Parser &P;
238+
SourceLoc InitialLoc;
239+
public:
240+
AssertParserMadeProgressBeforeLeavingScopeRAII(Parser &parser) : P(parser) {
241+
InitialLoc = P.Tok.getLoc();
242+
}
243+
~AssertParserMadeProgressBeforeLeavingScopeRAII() {
244+
assert(InitialLoc != P.Tok.getLoc() &&
245+
"parser did not make progress, this can result in infinite loop");
246+
}
247+
};
248+
234249
/// A RAII object for temporarily changing CurDeclContext.
235250
class ContextChange {
236251
protected:

lib/Parse/ParseStmt.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ using namespace swift::syntax;
3636
/// isStartOfStmt - Return true if the current token starts a statement.
3737
///
3838
bool Parser::isStartOfStmt() {
39+
// This needs to be kept in sync with `Parser::parseStmt()`. If a new token
40+
// kind is accepted here as start of statement, it should also be handled in
41+
// `Parser::parseStmt()`.
3942
switch (Tok.getKind()) {
4043
default: return false;
4144
case tok::kw_return:
@@ -565,6 +568,8 @@ static ParserResult<Stmt> recoverFromInvalidCase(Parser &P) {
565568
}
566569

567570
ParserResult<Stmt> Parser::parseStmt() {
571+
AssertParserMadeProgressBeforeLeavingScopeRAII apmp(*this);
572+
568573
SyntaxParsingContext LocalContext(SyntaxContext, SyntaxContextKind::Stmt);
569574

570575
// Note that we're parsing a statement.
@@ -588,7 +593,9 @@ ParserResult<Stmt> Parser::parseStmt() {
588593
if (isContextualYieldKeyword()) {
589594
Tok.setKind(tok::kw_yield);
590595
}
591-
596+
597+
// This needs to handle everything that `Parser::isStartOfStmt()` accepts as
598+
// start of statement.
592599
switch (Tok.getKind()) {
593600
case tok::pound_line:
594601
case tok::pound_sourceLocation:

0 commit comments

Comments
 (0)