]> granicus.if.org Git - clang/commitdiff
Emit errors about unsupported blocks features.
authorAnders Carlsson <andersca@mac.com>
Sun, 1 Mar 2009 01:45:25 +0000 (01:45 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 1 Mar 2009 01:45:25 +0000 (01:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65751 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBlocks.cpp
test/CodeGenObjC/blocks-unsupported.m [new file with mode: 0644]

index 93e1b57fc989232ea56ff1e22c8d6454c2e46568..ba9480fa0e4eaa952b5cec2ea7713a6c3230b96a 100644 (file)
@@ -132,6 +132,44 @@ static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info)
   return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
 }
 
+/// CanGenerateCodeForBlockExpr - Returns whether CodeGen for the block expr
+/// is supported. Will emit a diagnostic and return false if not.
+/// FIXME: Once we support everything this should of course be removed.
+static bool CanGenerateCodeForBlockExpr(CodeGenFunction &CGF, 
+                                        const BlockExpr* BE, 
+                                        const CodeGenFunction::BlockInfo &Info)
+{
+  if (!Info.ByRefDeclRefs.empty()) {
+    CGF.ErrorUnsupported(BE, "block expression with __block variables");
+    return false;
+  }
+  
+  for (size_t I = 0, E = Info.ByCopyDeclRefs.size(); I != E; ++I) {
+    const BlockDeclRefExpr *E = Info.ByCopyDeclRefs[I];
+    
+    E->getType()->dump();
+    
+    if (E->getType()->isBlockPointerType()) {
+      CGF.ErrorUnsupported(BE, "block expression with imported block");
+      return false;
+    }
+    
+    if (E->getDecl()->getAttr<ObjCNSObjectAttr>() || 
+        CGF.getContext().isObjCNSObjectType(E->getType())) {
+      CGF.ErrorUnsupported(BE, "block expression with __attribute__((NSObject))"
+                           " variable");
+      return false;
+    }
+    
+    if (CGF.getContext().isObjCObjectPointerType(E->getType())) {
+      CGF.ErrorUnsupported(BE, "block expression with Objective-C variable");
+      return false;
+    }
+  }
+  
+  return true;
+}
+
 // FIXME: Push most into CGM, passing down a few bits, like current
 // function name.
 llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
@@ -144,6 +182,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
   if (CanBlockBeGlobal(Info))
     return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
     
+  if (!CanGenerateCodeForBlockExpr(*this, BE, Info))
+    return llvm::UndefValue::get(ConvertType(BE->getType()));
+  
   std::vector<llvm::Constant*> Elts;
   llvm::Constant *C;
   llvm::Value *V;
diff --git a/test/CodeGenObjC/blocks-unsupported.m b/test/CodeGenObjC/blocks-unsupported.m
new file mode 100644 (file)
index 0000000..03ceddf
--- /dev/null
@@ -0,0 +1,34 @@
+// RUN: clang -fnext-runtime --emit-llvm -o %t %s -verify
+
+@class Foo;
+@protocol P;
+
+void t1()
+{
+       __block int a;
+       ^{ a = 10; }(); // expected-error {{cannot compile this block expression with __block variables yet}}
+       
+       void (^block)(void);
+    ^{ (void)block; }(); // expected-error {{}}
+
+    struct Foo *__attribute__ ((NSObject)) foo;
+    ^{ (void)foo; }(); // expected-error {{cannot compile this block expression with __attribute__((NSObject)) variable yet}}
+    
+    typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef;
+    CGColorRef color;
+    ^{ (void)color; }(); // expected-error {{cannot compile this block expression with __attribute__((NSObject)) variable yet}}
+    
+    id a1;
+    ^{ (void)a1; }(); // expected-error {{cannot compile this block expression with Objective-C variable yet}}
+    
+    Foo *a2;
+    ^{ (void)a2; }(); // expected-error {{cannot compile this block expression with Objective-C variable yet}}
+    
+    id<P> a3;
+    ^{ (void)a3; }(); // expected-error {{cannot compile this block expression with Objective-C variable yet}}
+
+    Foo<P> *a4;
+    ^{ (void)a4; }(); // expected-error {{cannot compile this block expression with Objective-C variable yet}}
+    
+    
+}