summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-04-28 02:15:35 +0000
committerJohn McCall <rjmccall@apple.com>2011-04-28 02:15:35 +0000
commita85af56e66b90ae287f8c6d7aa6a11af0887d71d (patch)
treea28e143904944ae6fc02425794ece42040c3cbe1
parentd35222283949b883a407dba843bd1f9ae7f21002 (diff)
downloadbcm5719-llvm-a85af56e66b90ae287f8c6d7aa6a11af0887d71d.tar.gz
bcm5719-llvm-a85af56e66b90ae287f8c6d7aa6a11af0887d71d.zip
When block-capturing a variable with a non-trivial destructor,
make sure to mark the destructor. This normally isn't required, because the destructor should have been marked as part of the declaration of the local, but it's necessary when the variable is a parameter because it's the call sites that are responsible for those destructors. llvm-svn: 130372
-rw-r--r--clang/lib/CodeGen/CGClass.cpp1
-rw-r--r--clang/lib/Sema/SemaExpr.cpp14
-rw-r--r--clang/test/CodeGenCXX/blocks.cpp17
3 files changed, 30 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 2789bb2c9d4..2cb554902e1 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 73fe0003f02..c4ec8dc1162 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/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/clang/test/CodeGenCXX/blocks.cpp b/clang/test/CodeGenCXX/blocks.cpp
index d66debea2b9..a4d5b86565e 100644
--- a/clang/test/CodeGenCXX/blocks.cpp
+++ b/clang/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; });
+ }
+}
OpenPOWER on IntegriCloud