aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Interp.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-05-28 16:16:00 +0200
committerGitHub <noreply@github.com>2025-05-28 16:16:00 +0200
commit857ffa19156695a36798660326922a3537ab828a (patch)
treece2d51450e78032247d035b8461df5ca333d15d6 /clang/lib/AST/ByteCode/Interp.cpp
parent7fa365843d9f99e75c38a6107e8511b324950e74 (diff)
downloadllvm-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.cpp37
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();