diff options
Diffstat (limited to 'clang/lib/AST/ByteCode/Interp.cpp')
-rw-r--r-- | clang/lib/AST/ByteCode/Interp.cpp | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index e454d9e..a8286dd 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1699,20 +1699,38 @@ bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, return Call(S, OpPC, F, VarArgSize); } +static void startLifetimeRecurse(const Pointer &Ptr) { + if (const Record *R = Ptr.getRecord()) { + Ptr.startLifetime(); + for (const Record::Field &Fi : R->fields()) + startLifetimeRecurse(Ptr.atField(Fi.Offset)); + return; + } + + if (const Descriptor *FieldDesc = Ptr.getFieldDesc(); + FieldDesc->isCompositeArray()) { + assert(Ptr.getLifetime() == Lifetime::Started); + for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I) + startLifetimeRecurse(Ptr.atIndex(I).narrow()); + return; + } + + Ptr.startLifetime(); +} + bool StartLifetime(InterpState &S, CodePtr OpPC) { const auto &Ptr = S.Stk.peek<Pointer>(); if (!CheckDummy(S, OpPC, Ptr, AK_Destroy)) return false; - - Ptr.startLifetime(); + startLifetimeRecurse(Ptr.narrow()); return true; } // FIXME: It might be better to the recursing as part of the generated code for // a destructor? static void endLifetimeRecurse(const Pointer &Ptr) { - Ptr.endLifetime(); if (const Record *R = Ptr.getRecord()) { + Ptr.endLifetime(); for (const Record::Field &Fi : R->fields()) endLifetimeRecurse(Ptr.atField(Fi.Offset)); return; @@ -1720,9 +1738,14 @@ static void endLifetimeRecurse(const Pointer &Ptr) { if (const Descriptor *FieldDesc = Ptr.getFieldDesc(); FieldDesc->isCompositeArray()) { + // No endLifetime() for array roots. + assert(Ptr.getLifetime() == Lifetime::Started); for (unsigned I = 0; I != FieldDesc->getNumElems(); ++I) endLifetimeRecurse(Ptr.atIndex(I).narrow()); + return; } + + Ptr.endLifetime(); } /// Ends the lifetime of the peek'd pointer. @@ -1730,7 +1753,7 @@ bool EndLifetime(InterpState &S, CodePtr OpPC) { const auto &Ptr = S.Stk.peek<Pointer>(); if (!CheckDummy(S, OpPC, Ptr, AK_Destroy)) return false; - endLifetimeRecurse(Ptr); + endLifetimeRecurse(Ptr.narrow()); return true; } @@ -1739,7 +1762,7 @@ bool EndLifetimePop(InterpState &S, CodePtr OpPC) { const auto &Ptr = S.Stk.pop<Pointer>(); if (!CheckDummy(S, OpPC, Ptr, AK_Destroy)) return false; - endLifetimeRecurse(Ptr); + endLifetimeRecurse(Ptr.narrow()); return true; } @@ -1758,9 +1781,9 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E, // CheckLifetime for this and all base pointers. for (Pointer P = Ptr;;) { - if (!CheckLifetime(S, OpPC, P, AK_Construct)) { + if (!CheckLifetime(S, OpPC, P, AK_Construct)) return false; - } + if (P.isRoot()) break; P = P.getBase(); |