aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/Interp.cpp
diff options
context:
space:
mode:
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();