[clang] c6605a0 - [clang][bytecode] Fix member pointers to IndirectFieldDecls (#104756)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 19 06:28:16 PDT 2024
Author: Timm Baeder
Date: 2024-08-19T15:28:12+02:00
New Revision: c6605a08681309188fa260a409bf5d37400876a0
URL: https://github.com/llvm/llvm-project/commit/c6605a08681309188fa260a409bf5d37400876a0
DIFF: https://github.com/llvm/llvm-project/commit/c6605a08681309188fa260a409bf5d37400876a0.diff
LOG: [clang][bytecode] Fix member pointers to IndirectFieldDecls (#104756)
Added:
Modified:
clang/lib/AST/ByteCode/MemberPointer.cpp
clang/test/AST/ByteCode/memberpointers.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/MemberPointer.cpp b/clang/lib/AST/ByteCode/MemberPointer.cpp
index 0c1b6edc5f7e10..0fe94db97a3c40 100644
--- a/clang/lib/AST/ByteCode/MemberPointer.cpp
+++ b/clang/lib/AST/ByteCode/MemberPointer.cpp
@@ -18,8 +18,7 @@ namespace interp {
std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
if (!Dcl || isa<FunctionDecl>(Dcl))
return Base;
- const FieldDecl *FD = cast<FieldDecl>(Dcl);
- assert(FD);
+ assert((isa<FieldDecl, IndirectFieldDecl>(Dcl)));
if (!Base.isBlockPointer())
return std::nullopt;
@@ -31,24 +30,36 @@ std::optional<Pointer> MemberPointer::toPointer(const Context &Ctx) const {
if (!BaseRecord)
return std::nullopt;
- assert(BaseRecord);
- if (FD->getParent() == BaseRecord->getDecl())
- return CastedBase.atField(BaseRecord->getField(FD)->Offset);
-
- const RecordDecl *FieldParent = FD->getParent();
- const Record *FieldRecord = Ctx.getRecord(FieldParent);
-
unsigned Offset = 0;
- Offset += FieldRecord->getField(FD)->Offset;
Offset += CastedBase.block()->getDescriptor()->getMetadataSize();
- if (Offset > CastedBase.block()->getSize())
- return std::nullopt;
+ if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) {
+ if (FD->getParent() == BaseRecord->getDecl())
+ return CastedBase.atField(BaseRecord->getField(FD)->Offset);
- if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();
- BaseDecl != FieldParent)
- Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);
+ const RecordDecl *FieldParent = FD->getParent();
+ const Record *FieldRecord = Ctx.getRecord(FieldParent);
+ Offset += FieldRecord->getField(FD)->Offset;
+ if (Offset > CastedBase.block()->getSize())
+ return std::nullopt;
+
+ if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl();
+ BaseDecl != FieldParent)
+ Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl);
+
+ } else {
+ const auto *IFD = cast<IndirectFieldDecl>(Dcl);
+
+ for (const NamedDecl *ND : IFD->chain()) {
+ const FieldDecl *F = cast<FieldDecl>(ND);
+ const RecordDecl *FieldParent = F->getParent();
+ const Record *FieldRecord = Ctx.getRecord(FieldParent);
+ Offset += FieldRecord->getField(F)->Offset;
+ }
+ }
+
+ assert(BaseRecord);
if (Offset > CastedBase.block()->getSize())
return std::nullopt;
diff --git a/clang/test/AST/ByteCode/memberpointers.cpp b/clang/test/AST/ByteCode/memberpointers.cpp
index f38e9486386315..ea4a725d3fd0df 100644
--- a/clang/test/AST/ByteCode/memberpointers.cpp
+++ b/clang/test/AST/ByteCode/memberpointers.cpp
@@ -209,3 +209,20 @@ namespace MemPtrTemporary {
static_assert(apply(A(), &A::f) == 5, "");
}
+
+namespace IndirectFields {
+ struct I { union { struct { int a, b; }; }; };
+
+ template <typename T, int T::*F>
+ constexpr int ReadField(const T &o) {
+ return F ? o.*F : 0;
+ }
+ void ReadFields() {
+ I i;
+ ReadField<I, &I::a>(i);
+ ReadField<I, &I::b>(i);
+ }
+
+ constexpr I i{12};
+ static_assert(ReadField<I, &I::a>(i) == 12, "");
+}
More information about the cfe-commits
mailing list