[CodeGen] Emit destructor calls to destruct compound literals
Fix a bug in IRGen where it wasn't destructing compound literals in C
that are ObjC pointer arrays or non-trivial structs. Also diagnose jumps
that enter or exit the lifetime of the compound literals.
rdar://problem/51867864
Differential Revision: https://reviews.llvm.org/D64464
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 9ec3738..9097e51 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -860,13 +860,13 @@
}
/// Enter a full-expression with a non-trivial number of objects to
-/// clean up. This is in this file because, at the moment, the only
-/// kind of cleanup object is a BlockDecl*.
+/// clean up.
void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) {
if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) {
assert(EWC->getNumObjects() != 0);
for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects())
- enterBlockScope(*this, C);
+ if (auto *BD = C.dyn_cast<BlockDecl *>())
+ enterBlockScope(*this, BD);
}
}
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 356d768..a3399af 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4268,6 +4268,14 @@
EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(),
/*Init*/ true);
+ // Block-scope compound literals are destroyed at the end of the enclosing
+ // scope in C.
+ if (!getLangOpts().CPlusPlus)
+ if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
+ pushLifetimeExtendedDestroy(getCleanupKind(DtorKind), DeclPtr,
+ E->getType(), getDestroyer(DtorKind),
+ DtorKind & EHCleanup);
+
return Result;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 8de609a..9881d28 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -659,7 +659,21 @@
}
AggValueSlot Slot = EnsureSlot(E->getType());
+
+ // Block-scope compound literals are destroyed at the end of the enclosing
+ // scope in C.
+ bool Destruct =
+ !CGF.getLangOpts().CPlusPlus && !Slot.isExternallyDestructed();
+ if (Destruct)
+ Slot.setExternallyDestructed();
+
CGF.EmitAggExpr(E->getInitializer(), Slot);
+
+ if (Destruct)
+ if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
+ CGF.pushLifetimeExtendedDestroy(
+ CGF.getCleanupKind(DtorKind), Slot.getAddress(), E->getType(),
+ CGF.getDestroyer(DtorKind), DtorKind & EHCleanup);
}
/// Attempt to look through various unimportant expressions to find a
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 8d9bf17..a0d1fe2 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -556,6 +556,11 @@
Value *VisitMemberExpr(MemberExpr *E);
Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); }
Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ // Strictly speaking, we shouldn't be calling EmitLoadOfLValue, which
+ // transitively calls EmitCompoundLiteralLValue, here in C++ since compound
+ // literals aren't l-values in C++. We do so simply because that's the
+ // cleanest way to handle compound literals in C++.
+ // See the discussion here: https://reviews.llvm.org/D64464
return EmitLoadOfLValue(E);
}