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/104756.diff 2 Files Affected: - (modified) clang/lib/AST/ByteCode/MemberPointer.cpp (+29-14) - (modified) clang/test/AST/ByteCode/memberpointers.cpp (+17) ``````````diff diff --git a/clang/lib/AST/ByteCode/MemberPointer.cpp b/clang/lib/AST/ByteCode/MemberPointer.cpp index 0c1b6edc5f7e10..1cc4800e5195d5 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,40 @@ 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); - + const RecordDecl *FieldParent = nullptr; unsigned Offset = 0; - Offset += FieldRecord->getField(FD)->Offset; Offset += CastedBase.block()->getDescriptor()->getMetadataSize(); + if (const auto *FD = dyn_cast<FieldDecl>(Dcl)) { + if (FD->getParent() == BaseRecord->getDecl()) + return CastedBase.atField(BaseRecord->getField(FD)->Offset); + + 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); + FieldParent = F->getParent(); + const Record *FieldRecord = Ctx.getRecord(FieldParent); + Offset += FieldRecord->getField(F)->Offset; + } + } + + assert(FieldParent); + assert(BaseRecord); if (Offset > CastedBase.block()->getSize()) return std::nullopt; - if (const RecordDecl *BaseDecl = Base.getDeclPtr().getRecord()->getDecl(); - BaseDecl != FieldParent) - Offset += Ctx.collectBaseOffset(FieldParent, BaseDecl); - 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..f73d09a6cf9e0a 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> + int ReadField(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); +} `````````` </details> https://github.com/llvm/llvm-project/pull/104756 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits