]> granicus.if.org Git - clang/commitdiff
Refine collection of BlockDeclRefExprs. WIP.
authorMike Stump <mrs@apple.com>
Wed, 21 Oct 2009 22:01:24 +0000 (22:01 +0000)
committerMike Stump <mrs@apple.com>
Wed, 21 Oct 2009 22:01:24 +0000 (22:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84787 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/CodeGen/CGBlocks.cpp

index 4a0df6bf027736915e4e2c633544e21ca7085d6f..42a6704d8aab73f44361022c7377f3df6cd5827e 100644 (file)
@@ -2757,8 +2757,8 @@ QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) {
   //    struct __Block_byref_1_X *__forwarding;
   //    unsigned int __flags;
   //    unsigned int __size;
-  //    void *__copy_helper;
-  //    void *__destroy_helper;
+  //    void *__copy_helper;           // as needed
+  //    void *__destroy_help           // as needed
   //    int X;
   //  } *
 
index af64fd5546de978338911705120ffaec2df38e0b..08c45874a392e2a0b7ff40a0df740a1df83d5ff7 100644 (file)
@@ -73,24 +73,29 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
   return NSConcreteStackBlock;
 }
 
-static void CollectBlockDeclRefInfo(const Stmt *S,
-                                    CodeGenFunction::BlockInfo &Info) {
+static void CollectBlockDeclRefInfo(
+  const Stmt *S, CodeGenFunction::BlockInfo &Info,
+  llvm::SmallSet<const DeclContext *, 16> &InnerContexts) {
   for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
        I != E; ++I)
     if (*I)
-      CollectBlockDeclRefInfo(*I, Info);
+      CollectBlockDeclRefInfo(*I, Info, InnerContexts);
 
   // We want to ensure we walk down into block literals so we can find
   // all nested BlockDeclRefExprs.
-  if (const BlockExpr *BE = dyn_cast<BlockExpr>(S))
-    CollectBlockDeclRefInfo(BE->getBody(), Info);
+  if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
+    InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl()));
+    CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
+  }
 
-  if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
+  if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
     // FIXME: Handle enums.
-    if (isa<FunctionDecl>(DE->getDecl()))
+    if (isa<FunctionDecl>(BDRE->getDecl()))
       return;
 
-    Info.DeclRefs.push_back(DE);
+    // Only Decls that escape are added.
+    if (!InnerContexts.count(BDRE->getDecl()->getDeclContext()))
+      Info.DeclRefs.push_back(BDRE);
   }
 }
 
@@ -130,7 +135,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
 
   std::string Name = CurFn->getName();
   CodeGenFunction::BlockInfo Info(0, Name.c_str());
-  CollectBlockDeclRefInfo(BE->getBody(), Info);
+  llvm::SmallSet<const DeclContext *, 16> InnerContexts;
+  InnerContexts.insert(BE->getBlockDecl());
+  CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
 
   // Check if the block can be global.
   // FIXME: This test doesn't work for nested blocks yet.  Longer term, I'd like