[all-commits] [llvm/llvm-project] f5c52a: [clang][bytecode] Don't evaluate bound member func...
cakgok via All-commits
all-commits at lists.llvm.org
Tue May 5 03:39:08 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: f5c52a03063ba379746152e981581989ecac3215
https://github.com/llvm/llvm-project/commit/f5c52a03063ba379746152e981581989ecac3215
Author: cakgok <cemakgok at gmail.com>
Date: 2026-05-05 (Tue, 05 May 2026)
Changed paths:
M clang/lib/AST/ByteCode/Compiler.cpp
M clang/unittests/AST/EvaluateAsRValueTest.cpp
Log Message:
-----------
[clang][bytecode] Don't evaluate bound member function expressions in new constant interpreter (#194851)
**Problem:**
A crash is triggered by clangd's hover feature when using C++23 and the
new bytecode interpreter, which calls `Expr::EvaluateAsRValue()` to
attempt constant folding on an expression under the cursor, even when it
is not a valid constant expression.
Tested versions: 22.1.3, Trunk (x86_64-pc-linux-gnu)
**How to reproduce:**
```cpp
struct S { void f(); };
void g() { S s; s.f(); }
```
Running `clangd --check=repro.cpp`
(with `compile_flags.txt` containing `-std=c++23
-fexperimental-new-constant-interpreter`)
will crash.
`Assertion ItemTypes.back() == toPrimType<T>() failed.`
You can observe the same crash by hovering over STL iterators like
`vec.begin()`.
**Relevant Stack Trace:**
```text
#8 clang::interp::InterpStack::pop<MemberPointer>()
#9 clang::interp::EvalEmitter::emitRet(PrimType, SourceInfo)
#10 clang::interp::Compiler<EvalEmitter>::visitExpr(Expr const*, bool)
#11 clang::interp::EvalEmitter::interpretExpr(Expr const*, bool, bool)
#12 clang::interp::Context::evaluateAsRValue(State&, Expr const*, APValue&)
#13 EvaluateAsRValue(EvalInfo&, Expr const*, APValue&)
#14 clang::Expr::EvaluateAsRValue(EvalResult&, ASTContext const&, bool) const
#15 clangd::(anon)::printExprValue(Expr const*, ASTContext const&)
#16 clangd::(anon)::printExprValue(SelectionTree::Node const*, ASTContext const&)
#17 clangd::getHover(...)
```
*Basically: `textDocument/hover` → `getHover` → `EvaluateAsRValue` → new
constant interpreter → `MemberPointer` type mismatch on stack pop.*
When `Compiler<Emitter>::VisitMemberExpr()` encounters a non-static
`CXXMethodDecl` member (a bound member function expression such as `s.f`
in `s.f()`), it falls through to `visitDeclRef()`. This pushes a `FnPtr`
onto the interpreter stack. However, the caller expects a
`MemberPointer`, causing an assertion failure in `InterpStack::pop()`:
**Fix:**
* In `VisitMemberExpr()`, bail out early (`return false`) when the
member is a non-static `CXXMethodDecl`, before reaching
`visitDeclRef()`. This causes `EvaluateAsRValue()` to report failure
gracefully rather than crashing. Bound member function expressions
(`s.f`) are not valid constant expressions, so returning `false` should
be semantically correct.
**Testing:**
* Added AST unit test
(`EvaluateAsRValue.FailsGracefullyOnBoundMemberExpr`) that directly
isolates a bound `MemberExpr` and passes it to `EvaluateAsRValue()`,
asserting it returns `false` without crashing.
* Added clangd hover test
(Hover.NoCrashOnBoundMemberFunctionWithNewInterpreter)
that reproduces the original crash scenario.
* *Note:* I could not add a Lit test because I believe this is
unreachable via normal `clang` invocations. `Sema` strictly catches
isolated bound member functions before constant evaluation. `clangd` has
a unique path to triggering this.
**Root cause:**
This is exposed by C++23 specifically due to (I think P2280R4 /
P2448R2):
- Relaxing the rules around "unknown" objects in constant evaluation,
allowing `s` in `s.f()` to proceed past the base object check even
though `s` is not constexpr and deferring failures to bytecode execution
rather than rejecting them structurally.
Assisted-by: gemini-cli
@tbaederr
---------
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list