]> granicus.if.org Git - clang/commitdiff
Block C++ code gen. Adds support for block reference argument
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 2 Jun 2010 21:35:17 +0000 (21:35 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 2 Jun 2010 21:35:17 +0000 (21:35 +0000)
types. Executable test will be added to LLVM test suite.
(radar 8041962).

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

lib/CodeGen/CGBlocks.cpp
test/CodeGenCXX/reference-in-block-args.cpp [new file with mode: 0644]

index de58597e298ddf592bbb8305dace9dadeb9b13be..850c77c4b7d365b1eef5af59311545e076ccd88b 100644 (file)
@@ -296,8 +296,11 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
       const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
       QualType Ty = E->getType();
       if (BDRE && BDRE->isByRef()) {
-        Types[i+BlockFields] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
-      } else
+        Types[i+BlockFields] = 
+          llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
+      } else if (BDRE && BDRE->getDecl()->getType()->isReferenceType()) {
+         Types[i+BlockFields] = llvm::PointerType::get(ConvertType(Ty), 0);
+      } else 
         Types[i+BlockFields] = ConvertType(Ty);
     }
 
@@ -359,8 +362,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
           continue;
         } else {
           E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD),
-                                             VD->getType(),
-                                             SourceLocation());
+                                            VD->getType().getNonReferenceType(),
+                                            SourceLocation());
+          if (VD->getType()->isReferenceType())
+            E = new (getContext())
+              UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf,
+                          getContext().getPointerType(E->getType()),
+                          SourceLocation());
         }
       }
 
@@ -629,6 +637,8 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const ValueDecl *VD,
 
     Ty = llvm::PointerType::get(Ty, 0);
     V = Builder.CreateBitCast(V, Ty);
+    if (VD->getType()->isReferenceType())
+      V = Builder.CreateLoad(V, "tmp");
   }
   return V;
 }
diff --git a/test/CodeGenCXX/reference-in-block-args.cpp b/test/CodeGenCXX/reference-in-block-args.cpp
new file mode 100644 (file)
index 0000000..1ff1ae2
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fblocks %s -emit-llvm -o %t
+// rdar: // 8041962
+
+extern "C" int printf(const char*, ...);
+
+struct ST {
+     int filler; 
+     int referrer;
+};
+
+void OUTER_BLOCK(void (^fixer)(ST& ref)) {
+    ST ref = {2, 100};
+    fixer(ref);
+}
+  
+void INNER_BLOCK(int (^largeDo) ()) {
+       printf("%d\n", largeDo());
+}
+
+void scan() {
+            OUTER_BLOCK(^(ST &ref) {
+                INNER_BLOCK(^() { return ref.referrer + ref.filler; });
+            });
+
+}
+
+int main() {
+    scan();
+}