]> granicus.if.org Git - clang/commitdiff
When we're flagging a protected scope to prevent jumps into the
authorJohn McCall <rjmccall@apple.com>
Fri, 13 Apr 2012 01:08:17 +0000 (01:08 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 13 Apr 2012 01:08:17 +0000 (01:08 +0000)
shadow of a block expression with non-trivial destructed cleanups,
we should flag that in the enclosing function, not in the block
that we're about to pop.

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

lib/Sema/SemaExpr.cpp
test/SemaCXX/goto.cpp
test/SemaObjC/arc-jump-block.m

index 2333e32e85fb7a7ad01db692db06f4d8e494abf8..0d0f2f5b99a4f7cc19d6a5bbde4ca050d11e4680 100644 (file)
@@ -9111,15 +9111,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
 
   BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
 
-  for (BlockDecl::capture_const_iterator ci = BSI->TheDecl->capture_begin(),
-       ce = BSI->TheDecl->capture_end(); ci != ce; ++ci) {
-    const VarDecl *variable = ci->getVariable();
-    QualType T = variable->getType();
-    QualType::DestructionKind destructKind = T.isDestructedType();
-    if (destructKind != QualType::DK_none)
-      getCurFunction()->setHasBranchProtectedScope();
-  }
-
   computeNRVO(Body, getCurBlock());
   
   BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
@@ -9127,10 +9118,23 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
   PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
 
   // If the block isn't obviously global, i.e. it captures anything at
-  // all, mark this full-expression as needing a cleanup.
+  // all, then we need to do a few things in the surrounding context:
   if (Result->getBlockDecl()->hasCaptures()) {
+    // First, this expression has a new cleanup object.
     ExprCleanupObjects.push_back(Result->getBlockDecl());
     ExprNeedsCleanups = true;
+
+    // It also gets a branch-protected scope if any of the captured
+    // variables needs destruction.
+    for (BlockDecl::capture_const_iterator
+           ci = Result->getBlockDecl()->capture_begin(),
+           ce = Result->getBlockDecl()->capture_end(); ci != ce; ++ci) {
+      const VarDecl *var = ci->getVariable();
+      if (var->getType().isDestructedType() != QualType::DK_none) {
+        getCurFunction()->setHasBranchProtectedScope();
+        break;
+      }
+    }
   }
 
   return Owned(Result);
index e55e8807239ecf0d10501fabd46ecbf024d1bff5..24bcb7c5167383479addfcfb0a2849c423460403 100644 (file)
@@ -115,3 +115,13 @@ namespace PR10620 {
     ;
   }
 }
+
+namespace test12 {
+  struct A { A(); A(const A&); ~A(); };
+  void test(A a) { // expected-note {{jump enters lifetime of block}} FIXME: wierd location
+    goto lbl; // expected-error {{goto into protected scope}}
+    (void) ^{ (void) a; };
+  lbl:
+    return;
+  }
+}
index fdd2dbff00a7cf31f0c666ffe4fac63570df114e..26a1fc839d73650f7e33011c888aa859816f4af3 100644 (file)
@@ -82,3 +82,16 @@ extern __attribute__((visibility("default"))) struct dispatch_queue_s _dispatch_
 - (void)pageLeft {}
 - (void)pageRight {}
 @end
+
+// Test 2.  rdar://problem/11150919
+int test2(id obj, int state) { // expected-note {{jump enters lifetime of block}} FIXME: wierd location
+  switch (state) {
+  case 0:
+    (void) ^{ (void) obj; };
+    return 0;
+
+  default: // expected-error {{switch case is in protected scope}}
+    return 1;
+  }
+}
+