diff options
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 14 | ||||
-rw-r--r-- | test/CodeGenCXX/blocks.cpp | 17 |
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; }); + } +} |