[clang] [clang][bytecode] Apply path when visiting `MemberPointer` APValues (PR #194652)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 08:03:47 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/194652.diff
6 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+13-2)
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+18)
- (modified) clang/lib/AST/ByteCode/Interp.h (+2)
- (modified) clang/lib/AST/ByteCode/MemberPointer.h (+6)
- (modified) clang/lib/AST/ByteCode/Opcodes.td (+3)
- (modified) clang/test/CodeGenCXX/template-arguments.cpp (+3)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 6850956d5347e..98d092554e129 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -5312,8 +5312,19 @@ bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
}
if (Val.isMemberPointer()) {
- if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
- return this->emitGetMemberPtr(MemberDecl, E);
+ if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl()) {
+ if (!this->emitGetMemberPtr(MemberDecl, E))
+ return false;
+
+ bool IsDerived = Val.isMemberPointerToDerivedMember();
+ // Apply the member pointer path.
+ for (const CXXRecordDecl *PathEntry : Val.getMemberPointerPath()) {
+ if (!this->emitCopyMemberPtrPath(PathEntry, IsDerived, E))
+ return false;
+ }
+
+ return true;
+ }
return this->emitNullMemberPtr(0, nullptr, E);
}
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index c8b805e85c189..6e93c6e88f261 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2744,6 +2744,24 @@ bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
return true;
}
+/// Just append the given Entry to the MemberPointer's path.
+/// This is used to re-inject APValues into the bytecode interpreter.
+bool CopyMemberPtrPath(InterpState &S, CodePtr OpPC, const RecordDecl *Entry,
+ bool IsDerived) {
+ const auto &MemberPtr = S.Stk.pop<MemberPointer>();
+
+ unsigned OldPathLength = MemberPtr.getPathLength();
+ unsigned NewPathLength = OldPathLength + 1;
+
+ auto NewPath = S.allocMemberPointerPath(NewPathLength);
+ std::copy_n(MemberPtr.path(), OldPathLength, NewPath);
+ NewPath[OldPathLength] = cast<CXXRecordDecl>(Entry);
+
+ S.Stk.push<MemberPointer>(
+ MemberPtr.withPath(NewPathLength, NewPath, IsDerived));
+ 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 5979afbc28844..426d26be0169c 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3507,6 +3507,8 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D);
bool GetMemberPtrBase(InterpState &S, CodePtr OpPC);
bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC);
+bool CopyMemberPtrPath(InterpState &S, CodePtr OpPC, const RecordDecl *Entry,
+ bool IsDerived);
/// 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 e5079653ffdcf..dbbf1fe85bada 100644
--- a/clang/lib/AST/ByteCode/MemberPointer.h
+++ b/clang/lib/AST/ByteCode/MemberPointer.h
@@ -151,6 +151,12 @@ class MemberPointer final {
DeclAndIsDerivedMember.getInt());
}
+ MemberPointer withPath(uint8_t PathLength, const CXXRecordDecl **Path,
+ bool IsDerived) const {
+ return MemberPointer(this->Base, DeclAndIsDerivedMember.getPointer(),
+ PtrOffset, PathLength, Path, IsDerived);
+ }
+
APValue toAPValue(const ASTContext &) const;
void print(llvm::raw_ostream &OS) const {
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 78f33672b7be0..ba2414590eacb 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -870,6 +870,9 @@ def GetMemberPtr : Opcode {
}
def GetMemberPtrBase : Opcode;
def GetMemberPtrDecl : Opcode;
+def CopyMemberPtrPath : Opcode {
+ let Args = [ArgRecordDecl, ArgBool];
+}
//===----------------------------------------------------------------------===//
// Debugging.
diff --git a/clang/test/CodeGenCXX/template-arguments.cpp b/clang/test/CodeGenCXX/template-arguments.cpp
index 14a454937122a..e62833ac40e1e 100644
--- a/clang/test/CodeGenCXX/template-arguments.cpp
+++ b/clang/test/CodeGenCXX/template-arguments.cpp
@@ -1,6 +1,9 @@
// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR= | FileCheck %s
// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR=constexpr | FileCheck %s --check-prefix=CONST
+// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR= -fexperimental-new-constant-interpreter | FileCheck %s
+// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - -triple x86_64-linux -DCONSTEXPR=constexpr -fexperimental-new-constant-interpreter | FileCheck %s --check-prefix=CONST
+
template<typename T> CONSTEXPR T id(T v) { return v; }
template<auto V> auto value = id(V);
``````````
</details>
https://github.com/llvm/llvm-project/pull/194652
More information about the cfe-commits
mailing list