[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