aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGClass.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp14
-rw-r--r--test/CodeGenCXX/blocks.cpp17
3 files changed, 30 insertions, 2 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 2789bb2c9d..2cb554902e 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1305,6 +1305,7 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, llvm::Value *Addr) {
if (ClassDecl->hasTrivialDestructor()) return;
const CXXDestructorDecl *D = ClassDecl->getDestructor();
+ assert(D && D->isUsed() && "destructor not marked as used!");
PushDestructorCleanup(D, Addr);
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 73fe0003f0..c4ec8dc116 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1124,8 +1124,18 @@ static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc,
// Build a copy expression.
Expr *copyExpr = 0;
- if (!byRef && S.getLangOptions().CPlusPlus &&
- !type->isDependentType() && type->isStructureOrClassType()) {
+ const RecordType *rtype;
+ if (!byRef && S.getLangOptions().CPlusPlus && !type->isDependentType() &&
+ (rtype = type->getAs<RecordType>())) {
+
+ // The capture logic needs the destructor, so make sure we mark it.
+ // Usually this is unnecessary because most local variables have
+ // their destructors marked at declaration time, but parameters are
+ // an exception because it's technically only the call site that
+ // actually requires the destructor.
+ if (isa<ParmVarDecl>(var))
+ S.FinalizeVarWithDestructor(var, rtype);
+
// According to the blocks spec, the capture of a variable from
// the stack requires a const copy constructor. This is not true
// of the copy/move done to move a __block variable to the heap.
diff --git a/test/CodeGenCXX/blocks.cpp b/test/CodeGenCXX/blocks.cpp
index d66debea2b..a4d5b86565 100644
--- a/test/CodeGenCXX/blocks.cpp
+++ b/test/CodeGenCXX/blocks.cpp
@@ -87,3 +87,20 @@ namespace test2 {
// CHECK: define internal void @__Block_byref_object_dispose
// CHECK: call void @_ZN5test21BD1Ev(
}
+
+// rdar://problem/9334739
+// Make sure we mark destructors for parameters captured in blocks.
+namespace test3 {
+ struct A {
+ A(const A&);
+ ~A();
+ };
+
+ struct B : A {
+ };
+
+ void test(B b) {
+ extern void consume(void(^)());
+ consume(^{ (void) b; });
+ }
+}