Skip to content

Infinite loop in parser due to using tok::annot_repl_input_end instead of tok::eof #541

@gnrv

Description

@gnrv
  • [X ] Checked for duplicates

Describe the bug

$ bin/cling 

****************** CLING ******************
* Type C++ code and press enter to run it *
*             Type .q to exit             *
*******************************************
[cling]$ void (*test)() = [](){ if }
input_line_3:2:28: error: expected '(' after 'if'
 void (*test)() = [](){ if }
                           ^
input_line_3:4:2: error: expected ';' at end of declaration
}
 ^
 ;
<<< cling interactive line includer >>>:1:1: error: expected expression

^
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
<<< cling interactive line includer >>>:1:1: error: expected expression
fatal error: too many errors emitted, stopping now [-ferror-limit=]

The Parser is stuck in
StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr)

because there's a while loop that expects eof, but we're at annot_repl_input_end

  while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
         Tok.isNot(tok::eof)) {
    if (Tok.is(tok::annot_pragma_unused)) {
      HandlePragmaUnused();
      continue;
    }
    ....

This turns into an infinite loop because it never encounters eof. I wonder if you guys are planning a general pattern to handle this thing without invasive modifications to llvm, or if there is some other general strategy. I'm a bit at a loss how to fix the bug in the optimal way, perhaps you guys can explain the best way to proceed.

This is not a bug in current released version of root, so I report it here instead of root repo.

Grepping through llvm, I see a lot of these kind of lines that don't seem to take annot_repl_input_end into account:

$ git grep isNot\(tok\:\:eof\)
...
clang/lib/Parse/ParseCXXInlineMethods.cpp:        if (Tok.isNot(tok::eof) || Tok.getEofData() != Param) {
clang/lib/Parse/ParseCXXInlineMethods.cpp:      while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseCXXInlineMethods.cpp:    if (Tok.isNot(tok::eof) || Tok.getEofData() != LM.Method)
clang/lib/Parse/ParseCXXInlineMethods.cpp:    while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseCXXInlineMethods.cpp:    while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseCXXInlineMethods.cpp:      while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseCXXInlineMethods.cpp:  while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseCXXInlineMethods.cpp:  if (Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseCXXInlineMethods.cpp:    while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseCXXInlineMethods.cpp:  while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseDecl.cpp:         Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseDecl.cpp:      (Tok.isNot(tok::eof) || Tok.getEofData() != TypeStr.data())) {
clang/lib/Parse/ParseDecl.cpp:  while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseDeclCXX.cpp:           Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseDeclCXX.cpp:         Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseDeclCXX.cpp:           Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseExprCXX.cpp:    while (Tok.isNot(tok::eof))
clang/lib/Parse/ParseHLSL.cpp:  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseObjc.cpp:      while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
clang/lib/Parse/ParseOpenMP.cpp:      while (Cnt && Tok.isNot(tok::eof)) {
clang/lib/Parse/ParsePragma.cpp:    while (Tok.isNot(tok::eof))
clang/lib/Parse/ParsePragma.cpp:  if (Tok.isNot(tok::eof)) {
clang/lib/Parse/ParsePragma.cpp:  if (Tok.isNot(tok::eof)) {
clang/lib/Parse/ParsePragma.cpp:        while (Tok.isNot(tok::eof))
clang/lib/Parse/ParsePragma.cpp:      if (Tok.isNot(tok::eof)) {
clang/lib/Parse/ParsePragma.cpp:        while (Tok.isNot(tok::eof))
clang/lib/Parse/ParsePragma.cpp:    if (Tok.isNot(tok::eof)) {
clang/lib/Parse/ParsePragma.cpp:      while (Tok.isNot(tok::eof))
clang/lib/Parse/ParsePragma.cpp:  if (Tok.isNot(tok::eof)) {
clang/lib/Parse/ParsePragma.cpp:  while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
clang/lib/Parse/ParseStmt.cpp:         Tok.isNot(tok::eof)) {
clang/lib/Parse/Parser.cpp:      while (Tok.isNot(tok::eof))
...

Expected behavior

Not hang in infinite loop

To Reproduce

See description

Setup

Latest cling in GitHub: commit 1d49255 (tag: __internal-root-4bcc5846f4e5c29d70e8f72029ec308c460671b7, upstream/master)

cling-latest llvm: commit 72c4df7523d41a5502e4a53b0999a6844ceb16e8 (HEAD, tag: cling-llvm18-20250117-01, origin/cling-llvm18, origin/cling-latest)

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions