diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-05-28 16:16:00 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-28 16:16:00 +0200 |
commit | 857ffa19156695a36798660326922a3537ab828a (patch) | |
tree | ce2d51450e78032247d035b8461df5ca333d15d6 /clang/lib/AST/ByteCode/Interp.cpp | |
parent | 7fa365843d9f99e75c38a6107e8511b324950e74 (diff) | |
download | llvm-857ffa19156695a36798660326922a3537ab828a.zip llvm-857ffa19156695a36798660326922a3537ab828a.tar.gz llvm-857ffa19156695a36798660326922a3537ab828a.tar.bz2 |
[clang][bytecode] Recursively start lifetimes as well (#141742)
The constructor starts the lifetime of all the subobjects.
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(); |