[clang] [clang-tools-extra] [clang][bytecode] Don't evaluate bound member function expressions in new constant interpreter (PR #194851)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 29 06:12:48 PDT 2026
https://github.com/cakgok updated https://github.com/llvm/llvm-project/pull/194851
>From 00d9cd705c499621d1c3118b43bf777afd7fd2d9 Mon Sep 17 00:00:00 2001
From: Cem <cemakgok at gmail.com>
Date: Wed, 29 Apr 2026 15:24:20 +0300
Subject: [PATCH] [clang][bytecode] Don't evaluate bound member function
expressions in new constant interpreter
---
.../clangd/unittests/HoverTests.cpp | 12 +++++
clang/lib/AST/ByteCode/Compiler.cpp | 8 +++
clang/unittests/AST/EvaluateAsRValueTest.cpp | 51 +++++++++++++++++++
3 files changed, 71 insertions(+)
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 7b168b0bdca60..9ce244e05a024 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -5245,6 +5245,18 @@ TEST(Hover, FunctionParameters) {
}
}
+TEST(Hover, NoCrashOnBoundMemberFunctionWithNewInterpreter) {
+ Annotations Code(R"cpp(
+ struct S { void f(); };
+ void g() { S s; s.^f(); }
+ )cpp");
+ TestTU TU = TestTU::withCode(Code.code());
+ TU.ExtraArgs.push_back("-std=c++23");
+ TU.ExtraArgs.push_back("-fexperimental-new-constant-interpreter");
+ auto AST = TU.build();
+ getHover(AST, Code.point(), format::getLLVMStyle(), nullptr);
+}
+
} // namespace
} // namespace clangd
} // namespace clang
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index d4bbb8d3a8a3e..ca2a408c0eceb 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2643,6 +2643,14 @@ bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
if (!this->discard(Base) && !this->emitSideEffect(E))
return false;
+ // Bound member functions (non-static CXXMethodDecls) cannot be
+ // constant-evaluated. visitDeclRef would blindly push a FnPtr,
+ // but the caller expects a MemberPointer, causing a stack mismatch.
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(Member)) {
+ if (!MD->isStatic())
+ return false;
+ }
+
return this->visitDeclRef(Member, E);
}
diff --git a/clang/unittests/AST/EvaluateAsRValueTest.cpp b/clang/unittests/AST/EvaluateAsRValueTest.cpp
index 1e17330863f26..d98c1d09d5bd4 100644
--- a/clang/unittests/AST/EvaluateAsRValueTest.cpp
+++ b/clang/unittests/AST/EvaluateAsRValueTest.cpp
@@ -154,3 +154,54 @@ TEST(EvaluateAsRValue, LValueToRValueConversionWorks) {
Args));
}
}
+
+class EvaluateBoundMemberFunctionVisitor
+ : public clang::DynamicRecursiveASTVisitor {
+public:
+ explicit EvaluateBoundMemberFunctionVisitor(clang::ASTContext &Ctx)
+ : Ctx(Ctx) {}
+
+ bool VisitMemberExpr(clang::MemberExpr *E) override {
+ if (llvm::isa<clang::CXXMethodDecl>(E->getMemberDecl())) {
+ clang::Expr::EvalResult Result;
+ bool EvalSucceeded = E->EvaluateAsRValue(Result, Ctx, true);
+ EXPECT_FALSE(EvalSucceeded);
+ }
+ return true;
+ }
+
+private:
+ clang::ASTContext &Ctx;
+};
+
+class EvaluateBoundMemberFunctionAction : public clang::ASTFrontendAction {
+public:
+ std::unique_ptr<clang::ASTConsumer>
+ CreateASTConsumer(clang::CompilerInstance &Compiler,
+ llvm::StringRef FilePath) override {
+ return std::make_unique<Consumer>();
+ }
+
+private:
+ class Consumer : public clang::ASTConsumer {
+ public:
+ ~Consumer() override {}
+ void HandleTranslationUnit(clang::ASTContext &Ctx) override {
+ EvaluateBoundMemberFunctionVisitor Evaluator(Ctx);
+ Evaluator.TraverseDecl(Ctx.getTranslationUnitDecl());
+ }
+ };
+};
+
+TEST(EvaluateAsRValue, FailsGracefullyOnBoundMemberExpr) {
+ std::string ModesToTest[] = {"", "-fexperimental-new-constant-interpreter"};
+ for (std::string const &Mode : ModesToTest) {
+ std::vector<std::string> Args(1, Mode);
+ Args.push_back("-std=c++23");
+ ASSERT_TRUE(runToolOnCodeWithArgs(
+ std::make_unique<EvaluateBoundMemberFunctionAction>(),
+ "struct S { void f(); };\n"
+ "void g() { S s; s.f(); }\n",
+ Args));
+ }
+}
More information about the cfe-commits
mailing list