[clang] [clang][bytecode] Check method accessibility in `GetMemberPtrDecl` (PR #194560)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 00:21:03 PDT 2026
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/194560
The decl saved in the `MemberPointer` needs to be accessible from its Base.
>From d1c2051f05e44cf1599d22d8651d0e1cab6f3bab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 28 Apr 2026 09:06:35 +0200
Subject: [PATCH] asdf
---
clang/lib/AST/ByteCode/Interp.cpp | 40 ++++++++++++++++++++++++++
clang/lib/AST/ByteCode/Interp.h | 27 ++---------------
clang/lib/AST/ByteCode/MemberPointer.h | 3 +-
clang/test/AST/ByteCode/cxx11.cpp | 8 +++---
4 files changed, 49 insertions(+), 29 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 729c0cc4ab541..428d7637a7b17 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2680,6 +2680,46 @@ bool CastMemberPtrDerivedPop(InterpState &S, CodePtr OpPC, int32_t Off,
return castBackMemberPointer(S, Ptr, Off, BaseDecl);
}
+bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
+ S.Stk.push<MemberPointer>(D);
+ return true;
+}
+
+bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
+ const auto &MP = S.Stk.pop<MemberPointer>();
+
+ if (!MP.isBaseCastPossible())
+ return false;
+
+ S.Stk.push<Pointer>(MP.getBase());
+ return true;
+}
+
+bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
+ const auto &MP = S.Stk.pop<MemberPointer>();
+
+ const ValueDecl *D = MP.getDecl();
+ const auto *FD = dyn_cast_if_present<FunctionDecl>(D);
+ if (!FD)
+ return false;
+
+ const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+ if (!Method)
+ return false;
+
+ const Pointer &Base = MP.getBase();
+ // The method must be accessible via the base of the MemberPointer.
+ const CXXRecordDecl *MethodParent = Method->getParent();
+ if (!Base.getRecord() || Base.getRecord()->getDecl() != MethodParent)
+ return false;
+
+ const auto *Func = S.getContext().getOrCreateFunction(FD);
+ if (!Func)
+ return false;
+ S.Stk.push<Pointer>(Func);
+ return true;
+}
+
// FIXME: Would be nice to generate this instead of hardcoding it here.
constexpr bool OpReturns(Opcode Op) {
return Op == OP_RetVoid || Op == OP_RetValue || Op == OP_NoRet ||
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 0f1c81fe300e6..00ed86c4618dd 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3503,30 +3503,9 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
return true;
}
-inline bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
- S.Stk.push<MemberPointer>(D);
- return true;
-}
-
-inline bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
- const auto &MP = S.Stk.pop<MemberPointer>();
-
- if (!MP.isBaseCastPossible())
- return false;
-
- S.Stk.push<Pointer>(MP.getBase());
- return true;
-}
-
-inline bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
- const auto &MP = S.Stk.pop<MemberPointer>();
-
- const auto *FD = cast<FunctionDecl>(MP.getDecl());
- const auto *Func = S.getContext().getOrCreateFunction(FD);
-
- S.Stk.push<Pointer>(Func);
- return true;
-}
+bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D);
+bool GetMemberPtrBase(InterpState &S, CodePtr OpPC);
+bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC);
/// Just emit a diagnostic. The expression that caused emission of this
/// op is not valid in a constant context.
diff --git a/clang/lib/AST/ByteCode/MemberPointer.h b/clang/lib/AST/ByteCode/MemberPointer.h
index 7bef2accd39e5..e5079653ffdcf 100644
--- a/clang/lib/AST/ByteCode/MemberPointer.h
+++ b/clang/lib/AST/ByteCode/MemberPointer.h
@@ -147,7 +147,8 @@ class MemberPointer final {
MemberPointer takeInstance(Pointer Instance) const {
assert(this->Base.isZero());
return MemberPointer(Instance, DeclAndIsDerivedMember.getPointer(),
- this->PtrOffset);
+ this->PtrOffset, PathLength, Path,
+ DeclAndIsDerivedMember.getInt());
}
APValue toAPValue(const ASTContext &) const;
diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp
index a4c4be14775b3..3acfe50627713 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -377,13 +377,13 @@ namespace GH150709 {
static_assert((c1.*mp)() == 1, ""); // both-error {{constant expression}}
static_assert((d1.*mp)() == 1, "");
static_assert((f.*mp)() == 1, "");
- static_assert((c2[0].*mp)() == 1, ""); // ref-error {{constant expression}}
+ static_assert((c2[0].*mp)() == 1, ""); // both-error {{constant expression}}
static_assert((d2[0].*mp)() == 1, "");
// incorrectly undiagnosed before fix of GH150709
- static_assert((e1.*mp)() == 1, ""); // ref-error {{constant expression}}
- static_assert((e2[0].*mp)() == 1, ""); // ref-error {{constant expression}}
- static_assert((g.*mp)() == 1, ""); // ref-error {{constant expression}}
+ static_assert((e1.*mp)() == 1, ""); // both-error {{constant expression}}
+ static_assert((e2[0].*mp)() == 1, ""); // both-error {{constant expression}}
+ static_assert((g.*mp)() == 1, ""); // both-error {{constant expression}}
}
namespace DiscardedAddrLabel {
More information about the cfe-commits
mailing list