[clang] [clang-repl] Address error recovery fixing infinite loop while parsing (PR #127569)
Anutosh Bhat via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 11 01:15:35 PST 2026
https://github.com/anutosh491 updated https://github.com/llvm/llvm-project/pull/127569
>From 5bda5cb946e8056a43e487e66487632729d37aee Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Tue, 18 Feb 2025 11:23:30 +0530
Subject: [PATCH 1/4] Address error recovery fixing infinite loop while parsing
---
clang/lib/Parse/ParseStmt.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index cd4504630f871..a044c8acab927 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1253,7 +1253,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
bool LastIsError = false;
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
- Tok.isNot(tok::eof)) {
+ Tok.isNot(tok::eof) && Tok.isNot(tok::annot_repl_input_end)) {
if (Tok.is(tok::annot_pragma_unused)) {
HandlePragmaUnused();
continue;
>From 51ab206b0859363fd5d6c30932bc01c7a551f687 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Wed, 11 Feb 2026 13:34:05 +0530
Subject: [PATCH 2/4] Apply discussed change
---
clang/include/clang/Parse/Parser.h | 9 ++++++++
clang/lib/Parse/ParseCXXInlineMethods.cpp | 16 +++++++-------
clang/lib/Parse/ParseDecl.cpp | 8 +++----
clang/lib/Parse/ParseDeclCXX.cpp | 8 +++----
clang/lib/Parse/ParseExprCXX.cpp | 2 +-
clang/lib/Parse/ParseHLSL.cpp | 2 +-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/lib/Parse/ParseOpenMP.cpp | 2 +-
clang/lib/Parse/ParsePragma.cpp | 26 ++++++++++++++---------
clang/lib/Parse/ParseStmt.cpp | 2 +-
clang/lib/Parse/Parser.cpp | 2 +-
11 files changed, 47 insertions(+), 32 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 5ae02e2b4e8ad..647ec8b0299ad 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -721,6 +721,15 @@ class Parser : public CodeCompletionHandler {
Kind == tok::annot_repl_input_end;
}
+ /// Determine if the given token marks the end of the current parsing unit.
+ /// In incremental (REPL) mode, this checks for annot_repl_input_end.
+ /// In normal compilation, this checks for EOF.
+ bool isAtInputEnd(const Token &T) const {
+ if (getLangOpts().IncrementalExtensions)
+ return T.is(tok::annot_repl_input_end);
+ return T.is(tok::eof);
+ }
+
static void setTypeAnnotation(Token &Tok, TypeResult T) {
assert((T.isInvalid() || T.get()) &&
"produced a valid-but-null type annotation?");
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index bc18881e89110..a83568be93056 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -426,7 +426,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,
/*DefaultArg=*/nullptr);
} else {
- if (Tok.isNot(tok::eof) || Tok.getEofData() != Param) {
+ if (!isAtInputEnd(Tok) || Tok.getEofData() != Param) {
// The last two tokens are the terminator and the saved value of
// Tok; the last token in the default argument is the one before
// those.
@@ -441,7 +441,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// There could be leftover tokens (e.g. because of an error).
// Skip through until we reach the 'end of default argument' token.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
if (Tok.is(tok::eof) && Tok.getEofData() == Param)
@@ -534,7 +534,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
DynamicExceptionRanges, NoexceptExpr,
ExceptionSpecTokens);
- if (Tok.isNot(tok::eof) || Tok.getEofData() != LM.Method)
+ if (!isAtInputEnd(Tok) || Tok.getEofData() != LM.Method)
Diag(Tok.getLocation(), diag::err_except_spec_unparsed);
// Attach the exception-specification to the method.
@@ -547,7 +547,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// There could be leftover tokens (e.g. because of an error).
// Skip through until we reach the original token position.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
// Clean up the remaining EOF token.
@@ -604,7 +604,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
llvm::scope_exit _([&]() {
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
if (Tok.is(tok::eof) && Tok.getEofData() == LM.D)
@@ -691,7 +691,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc, Init);
// The next token should be our artificial terminating EOF token.
- if (Tok.isNot(tok::eof)) {
+ if (!isAtInputEnd(Tok)) {
if (!Init.isInvalid()) {
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
if (!EndLoc.isValid())
@@ -701,7 +701,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
}
// Consume tokens until we hit the artificial EOF.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
}
// Make sure this is *our* artificial EOF token.
@@ -797,7 +797,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
// Due to a parsing error, we either went over the cached tokens or
// there are still cached tokens left, so we skip the leftover tokens.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index df9e3878bffc0..8bea74976e312 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4832,7 +4832,7 @@ void Parser::ParseLexedCAttribute(LateParsedAttribute &LA, bool EnterScope,
// Due to a parsing error, we either went over the cached tokens or
// there are still cached tokens left, so we skip the leftover tokens.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
// Consume the fake EOF token if it's there
@@ -4864,7 +4864,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// While we still have something to read, read the declarations in the struct.
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
- Tok.isNot(tok::eof)) {
+ !isAtInputEnd(Tok)) {
// Each iteration of this loop reads one struct-declaration.
// Check for extraneous top-level semicolon.
@@ -8161,13 +8161,13 @@ TypeResult Parser::ParseTypeFromString(StringRef TypeStr, StringRef Context,
// Check if we parsed the whole thing.
if (Result.isUsable() &&
- (Tok.isNot(tok::eof) || Tok.getEofData() != TypeStr.data())) {
+ (!isAtInputEnd(Tok) || Tok.getEofData() != TypeStr.data())) {
Diag(Tok.getLocation(), diag::err_type_unparsed);
}
// There could be leftover tokens (e.g. because of an error).
// Skip through until we reach the 'end of directive' token.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
// Consume the end token.
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 9117a725843d9..749d13d7e81a0 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -229,7 +229,7 @@ void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
BalancedDelimiterTracker &Tracker) {
if (index == InnerNSs.size()) {
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
- Tok.isNot(tok::eof)) {
+ !isAtInputEnd(Tok)) {
ParsedAttributes DeclAttrs(AttrFactory);
MaybeParseCXX11Attributes(DeclAttrs);
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
@@ -428,7 +428,7 @@ Decl *Parser::ParseExportDeclaration() {
T.consumeOpen();
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
- Tok.isNot(tok::eof)) {
+ !isAtInputEnd(Tok)) {
ParsedAttributes DeclAttrs(AttrFactory);
MaybeParseCXX11Attributes(DeclAttrs);
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
@@ -3671,7 +3671,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (TagDecl) {
// While we still have something to read, read the member-declarations.
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
- Tok.isNot(tok::eof)) {
+ !isAtInputEnd(Tok)) {
// Each iteration of this loop reads one member-declaration.
ParseCXXClassMemberDeclarationWithPragmas(
CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl);
@@ -4441,7 +4441,7 @@ bool Parser::ParseCXX11AttributeArgs(
if (LO.CPlusPlus) {
TentativeParsingAction TPA(*this);
bool HasInvalidArgument = false;
- while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_paren) && !isAtInputEnd(Tok)) {
if (Tok.isOneOf(tok::hash, tok::hashhash)) {
Diag(Tok.getLocation(), diag::ext_invalid_attribute_argument)
<< PP.getSpelling(Tok);
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 842b52375eb14..2d2d8e1dcac81 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3698,7 +3698,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// Match the ')'.
if (Result.isInvalid()) {
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
assert(Tok.getEofData() == AttrEnd.getEofData());
ConsumeAnyToken();
diff --git a/clang/lib/Parse/ParseHLSL.cpp b/clang/lib/Parse/ParseHLSL.cpp
index c727ee3a1f1a6..a4a948ee10f9b 100644
--- a/clang/lib/Parse/ParseHLSL.cpp
+++ b/clang/lib/Parse/ParseHLSL.cpp
@@ -77,7 +77,7 @@ Decl *Parser::ParseHLSLBuffer(SourceLocation &DeclEnd,
T.getOpenLocation());
Actions.ProcessDeclAttributeList(Actions.CurScope, D, Attrs);
- while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+ while (Tok.isNot(tok::r_brace) && !isAtInputEnd(Tok)) {
// FIXME: support attribute on constants inside cbuffer/tbuffer.
ParsedAttributes DeclAttrs(AttrFactory);
ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 0b9f113d9edc7..b59db1cb1f920 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -3324,7 +3324,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
// expensive isBeforeInTranslationUnit call.
if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
OrigLoc))
- while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
+ while (Tok.getLocation() != OrigLoc && !isAtInputEnd(Tok))
ConsumeAnyToken();
}
// Clean up the remaining EOF token, only if it's inserted by us. Otherwise
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index b41803d23cb25..08237e69524ff 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1973,7 +1973,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
CachedTokens Toks;
unsigned Cnt = 1;
Toks.push_back(Tok);
- while (Cnt && Tok.isNot(tok::eof)) {
+ while (Cnt && !isAtInputEnd(Tok)) {
(void)ConsumeAnyToken();
if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
++Cnt;
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index def2817c930b2..f84f43b0e7c40 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -1063,7 +1063,7 @@ void Parser::HandlePragmaMSPragma() {
if (!(this->*Handler)(PragmaName, PragmaLocation)) {
// Pragma handling failed, and has been diagnosed. Slurp up the tokens
// until eof (really end of line) to prevent follow-on errors.
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
PP.Lex(Tok);
PP.Lex(Tok);
}
@@ -1140,7 +1140,7 @@ bool Parser::HandlePragmaMSSection(StringRef PragmaName,
return false;
}
PP.Lex(Tok); // )
- if (Tok.isNot(tok::eof)) {
+ if (!isAtInputEnd(Tok)) {
PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
<< PragmaName;
return false;
@@ -1222,7 +1222,7 @@ bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
return false;
}
PP.Lex(Tok); // )
- if (Tok.isNot(tok::eof)) {
+ if (!isAtInputEnd(Tok)) {
PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
<< PragmaName;
return false;
@@ -1596,7 +1596,7 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
if (Toks.size() > 2) {
Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< PragmaLoopHintString(Info->PragmaName, Info->Option);
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
}
@@ -1631,10 +1631,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
// Tokens following an error in an ill-formed constant expression will
// remain in the token stream and must be removed.
- if (Tok.isNot(tok::eof)) {
+ if (!isAtInputEnd(Tok)) {
Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< PragmaLoopHintString(Info->PragmaName, Info->Option);
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
}
@@ -1657,10 +1657,10 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
// Tokens following an error in an ill-formed constant expression will
// remain in the token stream and must be removed.
- if (Tok.isNot(tok::eof)) {
+ if (!isAtInputEnd(Tok)) {
Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< PragmaLoopHintString(Info->PragmaName, Info->Option);
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
}
@@ -2113,7 +2113,7 @@ void Parser::HandlePragmaAttribute() {
// Tokens following an ill-formed attribute will remain in the token stream
// and must be removed.
- if (Tok.isNot(tok::eof)) {
+ if (!isAtInputEnd(Tok)) {
Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
SkipToEnd();
return;
@@ -2823,7 +2823,13 @@ void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(
Tok.setKind(StartTok);
Tok.setLocation(Introducer.Loc);
- while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
+ auto IsAtInputEnd = [&PP](const Token &T) {
+ if (PP.getLangOpts().IncrementalExtensions)
+ return T.is(tok::annot_repl_input_end);
+ return T.is(tok::eof);
+ };
+
+ while (Tok.isNot(tok::eod) && !IsAtInputEnd(Tok)) {
Pragma.push_back(Tok);
PP.Lex(Tok);
if (Tok.is(StartTok)) {
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 1f0f927053e51..2a3906fd5ca5e 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -1159,7 +1159,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
bool LastIsError = false;
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
- Tok.isNot(tok::eof) && Tok.isNot(tok::annot_repl_input_end)) {
+ !isAtInputEnd(Tok)) {
if (Tok.is(tok::annot_pragma_unused)) {
HandlePragmaUnused();
continue;
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index be9e0a39a3781..4f5aed482e552 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -310,7 +310,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
if (Toks.size() == 1 && Toks[0] == tok::eof &&
!HasFlagsSet(Flags, StopAtSemi) &&
!HasFlagsSet(Flags, StopAtCodeCompletion)) {
- while (Tok.isNot(tok::eof))
+ while (!isAtInputEnd(Tok))
ConsumeAnyToken();
return true;
}
>From 67a331276978583c1a196888988b33d1cdbfd734 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Wed, 11 Feb 2026 14:38:58 +0530
Subject: [PATCH 3/4] Fix failing tests and add some tests
---
clang/include/clang/Parse/Parser.h | 7 +++---
.../Interpreter/repl-input-end-recovery.cpp | 22 +++++++++++++++++++
2 files changed, 26 insertions(+), 3 deletions(-)
create mode 100644 clang/test/Interpreter/repl-input-end-recovery.cpp
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 647ec8b0299ad..27fba6161eecb 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -725,9 +725,10 @@ class Parser : public CodeCompletionHandler {
/// In incremental (REPL) mode, this checks for annot_repl_input_end.
/// In normal compilation, this checks for EOF.
bool isAtInputEnd(const Token &T) const {
- if (getLangOpts().IncrementalExtensions)
- return T.is(tok::annot_repl_input_end);
- return T.is(tok::eof);
+ if (T.is(tok::eof))
+ return true;
+ return getLangOpts().IncrementalExtensions &&
+ T.is(tok::annot_repl_input_end);
}
static void setTypeAnnotation(Token &Tok, TypeResult T) {
diff --git a/clang/test/Interpreter/repl-input-end-recovery.cpp b/clang/test/Interpreter/repl-input-end-recovery.cpp
new file mode 100644
index 0000000000000..a06cfad85a0c8
--- /dev/null
+++ b/clang/test/Interpreter/repl-input-end-recovery.cpp
@@ -0,0 +1,22 @@
+// REQUIRES: host-supports-jit
+// RUN: cat %s | clang-repl -Xcc -Xclang -Xcc -verify -Xcc -Xclang -Xcc -verify-ignore-unexpected | FileCheck %s
+
+extern "C" int printf(const char *, ...);
+
+void foo() { int x = 5; // expected-error {{expected '}'}}
+int g1 = 0; void foo() { g1 = 5; } foo(); printf("g1 = %d\n", g1);
+// CHECK: g1 = 5
+
+void (*test)() = [](){ if } // expected-error {{expected '(' after 'if'}}
+int g2 = 0; void (*test)() = [](){ if (1) g2 = 7; }; test(); printf("g2 = %d\n", g2);
+// CHECK: g2 = 7
+
+namespace myspace { // expected-error {{expected '}'}}
+namespace myspace { int v = 11; } printf("v = %d\n", myspace::v);
+// CHECK: v = 11
+
+struct X { using type = int }; // expected-error {{expected ';' after alias declaration}}
+struct X { using type = int; }; X::type t = 3; printf("t = %d\n", t);
+// CHECK: t = 3
+
+%quit
\ No newline at end of file
>From ab6d0d899f8a01ed7e8b1023f235bf567dce8ae0 Mon Sep 17 00:00:00 2001
From: anutosh491 <andersonbhat491 at gmail.com>
Date: Wed, 11 Feb 2026 14:45:15 +0530
Subject: [PATCH 4/4] Improve the lambda too
---
clang/lib/Parse/ParsePragma.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index f84f43b0e7c40..268452133af62 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -2824,9 +2824,10 @@ void PragmaSupportHandler<StartTok, EndTok, UnexpectedDiag>::HandlePragma(
Tok.setLocation(Introducer.Loc);
auto IsAtInputEnd = [&PP](const Token &T) {
- if (PP.getLangOpts().IncrementalExtensions)
- return T.is(tok::annot_repl_input_end);
- return T.is(tok::eof);
+ if (T.is(tok::eof))
+ return true;
+ return getLangOpts().IncrementalExtensions &&
+ T.is(tok::annot_repl_input_end);
};
while (Tok.isNot(tok::eod) && !IsAtInputEnd(Tok)) {
More information about the cfe-commits
mailing list