@@ -2196,6 +2196,53 @@ static unsigned computeFullDescSize(const ASTContext &ASTCtx,
21962196 return 0 ;
21972197}
21982198
2199+ static unsigned computePointerOffset (const ASTContext &ASTCtx,
2200+ const Pointer &Ptr) {
2201+ unsigned Result = 0 ;
2202+
2203+ Pointer P = Ptr;
2204+ while (P.isArrayElement () || P.isField ()) {
2205+ P = P.expand ();
2206+ const Descriptor *D = P.getFieldDesc ();
2207+
2208+ if (P.isArrayElement ()) {
2209+ unsigned ElemSize =
2210+ ASTCtx.getTypeSizeInChars (D->getElemQualType ()).getQuantity ();
2211+ if (P.isOnePastEnd ())
2212+ Result += ElemSize * P.getNumElems ();
2213+ else
2214+ Result += ElemSize * P.getIndex ();
2215+ P = P.expand ().getArray ();
2216+ } else if (P.isBaseClass ()) {
2217+
2218+ const auto *RD = cast<CXXRecordDecl>(D->asDecl ());
2219+ bool IsVirtual = Ptr.isVirtualBaseClass ();
2220+ P = P.getBase ();
2221+ const Record *BaseRecord = P.getRecord ();
2222+
2223+ const ASTRecordLayout &Layout =
2224+ ASTCtx.getASTRecordLayout (cast<CXXRecordDecl>(BaseRecord->getDecl ()));
2225+ if (IsVirtual)
2226+ Result += Layout.getVBaseClassOffset (RD).getQuantity ();
2227+ else
2228+ Result += Layout.getBaseClassOffset (RD).getQuantity ();
2229+ } else if (P.isField ()) {
2230+ const FieldDecl *FD = P.getField ();
2231+ const ASTRecordLayout &Layout =
2232+ ASTCtx.getASTRecordLayout (FD->getParent ());
2233+ unsigned FieldIndex = FD->getFieldIndex ();
2234+ uint64_t FieldOffset =
2235+ ASTCtx.toCharUnitsFromBits (Layout.getFieldOffset (FieldIndex))
2236+ .getQuantity ();
2237+ Result += FieldOffset;
2238+ P = P.getBase ();
2239+ } else
2240+ llvm_unreachable (" Unhandled descriptor type" );
2241+ }
2242+
2243+ return Result;
2244+ }
2245+
21992246static bool interp__builtin_object_size (InterpState &S, CodePtr OpPC,
22002247 const InterpFrame *Frame,
22012248 const Function *Func,
@@ -2217,7 +2264,7 @@ static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
22172264
22182265 const ASTContext &ASTCtx = S.getASTContext ();
22192266
2220- unsigned ByteOffset = 0 ;
2267+ unsigned ByteOffset = computePointerOffset (ASTCtx, Ptr) ;
22212268 unsigned FullSize = computeFullDescSize (ASTCtx, DeclDesc);
22222269
22232270 pushInteger (S, FullSize - ByteOffset, Call->getType ());
0 commit comments