@@ -1699,38 +1699,61 @@ bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
16991699 return Call (S, OpPC, F, VarArgSize);
17001700}
17011701
1702+ static void startLifetimeRecurse (const Pointer &Ptr) {
1703+ if (const Record *R = Ptr.getRecord ()) {
1704+ Ptr.startLifetime ();
1705+ for (const Record::Field &Fi : R->fields ())
1706+ startLifetimeRecurse (Ptr.atField (Fi.Offset ));
1707+ return ;
1708+ }
1709+
1710+ if (const Descriptor *FieldDesc = Ptr.getFieldDesc ();
1711+ FieldDesc->isCompositeArray ()) {
1712+ assert (Ptr.getLifetime () == Lifetime::Started);
1713+ for (unsigned I = 0 ; I != FieldDesc->getNumElems (); ++I)
1714+ startLifetimeRecurse (Ptr.atIndex (I).narrow ());
1715+ return ;
1716+ }
1717+
1718+ Ptr.startLifetime ();
1719+ }
1720+
17021721bool StartLifetime (InterpState &S, CodePtr OpPC) {
17031722 const auto &Ptr = S.Stk .peek <Pointer>();
17041723 if (!CheckDummy (S, OpPC, Ptr, AK_Destroy))
17051724 return false ;
1706-
1707- Ptr.startLifetime ();
1725+ startLifetimeRecurse (Ptr.narrow ());
17081726 return true ;
17091727}
17101728
17111729// FIXME: It might be better to the recursing as part of the generated code for
17121730// a destructor?
17131731static void endLifetimeRecurse (const Pointer &Ptr) {
1714- Ptr.endLifetime ();
17151732 if (const Record *R = Ptr.getRecord ()) {
1733+ Ptr.endLifetime ();
17161734 for (const Record::Field &Fi : R->fields ())
17171735 endLifetimeRecurse (Ptr.atField (Fi.Offset ));
17181736 return ;
17191737 }
17201738
17211739 if (const Descriptor *FieldDesc = Ptr.getFieldDesc ();
17221740 FieldDesc->isCompositeArray ()) {
1741+ // No endLifetime() for array roots.
1742+ assert (Ptr.getLifetime () == Lifetime::Started);
17231743 for (unsigned I = 0 ; I != FieldDesc->getNumElems (); ++I)
17241744 endLifetimeRecurse (Ptr.atIndex (I).narrow ());
1745+ return ;
17251746 }
1747+
1748+ Ptr.endLifetime ();
17261749}
17271750
17281751// / Ends the lifetime of the peek'd pointer.
17291752bool EndLifetime (InterpState &S, CodePtr OpPC) {
17301753 const auto &Ptr = S.Stk .peek <Pointer>();
17311754 if (!CheckDummy (S, OpPC, Ptr, AK_Destroy))
17321755 return false ;
1733- endLifetimeRecurse (Ptr);
1756+ endLifetimeRecurse (Ptr. narrow () );
17341757 return true ;
17351758}
17361759
@@ -1739,7 +1762,7 @@ bool EndLifetimePop(InterpState &S, CodePtr OpPC) {
17391762 const auto &Ptr = S.Stk .pop <Pointer>();
17401763 if (!CheckDummy (S, OpPC, Ptr, AK_Destroy))
17411764 return false ;
1742- endLifetimeRecurse (Ptr);
1765+ endLifetimeRecurse (Ptr. narrow () );
17431766 return true ;
17441767}
17451768
@@ -1758,9 +1781,9 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
17581781
17591782 // CheckLifetime for this and all base pointers.
17601783 for (Pointer P = Ptr;;) {
1761- if (!CheckLifetime (S, OpPC, P, AK_Construct)) {
1784+ if (!CheckLifetime (S, OpPC, P, AK_Construct))
17621785 return false ;
1763- }
1786+
17641787 if (P.isRoot ())
17651788 break ;
17661789 P = P.getBase ();
0 commit comments