]> granicus.if.org Git - clang/commitdiff
When block-capturing a variable with a non-trivial destructor,
authorJohn McCall <rjmccall@apple.com>
Thu, 28 Apr 2011 02:15:35 +0000 (02:15 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 28 Apr 2011 02:15:35 +0000 (02:15 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130372 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
lib/Sema/SemaExpr.cpp
test/CodeGenCXX/blocks.cpp

index 2789bb2c9d42088ba370c3915b8c5f393508ba27..2cb554902e1dab61db6c97723ad40a7ad0ad914a 100644 (file)
@@ -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);
 }
 
index 73fe0003f024acb201ee1db3668f811de190d8fb..c4ec8dc1162f9f6c0fe96746466f303600f5ae63 100644 (file)
@@ -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.
index d66debea2b9a21a47a8b5ea5335ed18f932ede26..a4d5b86565e2c9b7d2bcfcbce874881af99a945f 100644 (file)
@@ -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; });
+  }
+}