Infinite Loop During Parser Error Recovery in `clang-repl` After Malformed Statement Inside Brace Scope, related to Issue #206670
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
# Infinite Loop During Parser Error Recovery in `clang-repl` After Malformed Statement Inside Brace Scope
## Summary
While investigating and fixing **Issue #206670**, an unrelated parser recovery bug was uncovered in `clang-repl`.
Once the original assertion failure is fixed, malformed statements inside any brace-enclosed scope no longer crash the interpreter. Instead, the parser enters an infinite recovery loop, consuming 100% CPU and never terminating.
This issue appears to be independent of namespaces and affects general parser error recovery.
---
# Reproducer
Start `clang-repl` and enter either of the following:
```cpp
namespace v1 {
int x = }
```
or
```cpp
{
int x = }
```
The same behavior can also be reproduced in non-interactive mode:
```bash
./build/bin/clang-repl "namespace v1 { int x = }"
```
---
# Expected Behavior
The interpreter should:
1. Emit the appropriate syntax diagnostics.
2. Recover from the malformed declaration.
3. Return control to the REPL (or terminate normally in non-interactive mode).
---
# Actual Behavior
Instead:
- syntax diagnostics are emitted,
- the parser never finishes recovering,
- the process enters an infinite loop,
- CPU usage reaches 100%,
- the process must be terminated manually (e.g. via `Ctrl+C`).
Eventually, Clang's diagnostic engine reaches the configured error limit and suppresses further diagnostics, but parsing continues indefinitely.
---
# Root Cause Analysis
The parser enters error recovery after encountering the malformed declaration.
During recovery, it attempts to skip tokens until reaching a synchronization point (typically a semicolon).
In this scenario, recovery appears to consume past the closing brace (`}`) of the active scope.
Once that happens:
- the parser loses track of the compound statement,
- it believes it is still inside an unfinished block,
- the current token stream is never advanced to a valid recovery point,
- and the same recovery path is repeatedly executed.
As a result, the parser loops forever without making forward progress.
---
# Observed Call Stack
Using `gdb`, the execution repeatedly remained in the same parser recovery path:
```text
(gdb) bt
#0 clang::Sema::DiscardCleanupsInEvaluationContext()
#1 clang::Sema::ActOnExprStmtError()
#2 clang::Parser::ParseExprStatement()
#3 clang::Parser::ParseCompoundStatementBody()
#4 clang::Parser::ParseStatementOrDeclaration()
```
The stack remains effectively identical across multiple iterations, suggesting the parser is repeatedly re-entering the same recovery logic without consuming additional tokens.
---
# Additional Notes
This issue was discovered while validating the fix for **Issue #206670**.
The original assertion masked this behavior by aborting before parser recovery could begin.
Once the assertion was removed, the parser progressed further and exposed this independent recovery bug.
---
# Impact
This issue also prevents adding a regression test for the original fix.
For example, a test such as:
```text
// RUN: not clang-repl "namespace v1 { int x = }"
```
never completes because the parser does not exit the recovery loop.
As a result:
- `clang-repl` never returns,
- `llvm-lit` hangs indefinitely,
- and the test suite stalls.
---
# Environment
- LLVM: current `main`
- Component: `clang-repl`
- Platform: Ubuntu (reproduced locally)
- Build: Debug
```
Contributor guide
Research direction
Reproduce the hang with clang-repl using the namespace or brace-scope malformed statement shown in the issue, then inspect the parser recovery path named in the call stack: ParseExprStatement, ParseCompoundStatementBody, and ParseStatementOrDeclaration. Trace whether recovery advances past the closing brace and identify a way to restore forward progress; done means diagnostics are emitted and clang-repl returns normally in both interactive and non-interactive modes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- cli, compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100