Add some block-pointer conversions in C++

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61359 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 8463c5d..b2130e4 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -135,7 +135,7 @@
   // check for their presence as well as checking whether FromType is
   // a pointer.
   if (ToType->isBooleanType() &&
-      (FromType->isPointerType() ||
+      (FromType->isPointerType() || FromType->isBlockPointerType() ||
        First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
     return true;
 
@@ -547,7 +547,8 @@
   else if (ToType->isBooleanType() &&
            (FromType->isArithmeticType() ||
             FromType->isEnumeralType() ||
-            FromType->isPointerType())) {
+            FromType->isPointerType() ||
+            FromType->isBlockPointerType())) {
     SCS.Second = ICK_Boolean_Conversion;
     FromType = Context.BoolTy;
   } else {
@@ -857,25 +858,33 @@
     return true;
   }
 
+  // Beyond this point, both types need to be pointers or block pointers.
+  QualType ToPointeeType;
   const PointerType* ToTypePtr = ToType->getAsPointerType();
-  if (!ToTypePtr)
+  if (ToTypePtr)
+    ToPointeeType = ToTypePtr->getPointeeType();
+  else if (const BlockPointerType *ToBlockPtr = ToType->getAsBlockPointerType())
+    ToPointeeType = ToBlockPtr->getPointeeType();
+  else
     return false;
 
-  // Beyond this point, both types need to be pointers.
+  QualType FromPointeeType;
   const PointerType *FromTypePtr = FromType->getAsPointerType();
-  if (!FromTypePtr)
+  if (FromTypePtr)
+    FromPointeeType = FromTypePtr->getPointeeType();
+  else if (const BlockPointerType *FromBlockPtr 
+             = FromType->getAsBlockPointerType())
+    FromPointeeType = FromBlockPtr->getPointeeType();
+  else
     return false;
 
-  QualType FromPointeeType = FromTypePtr->getPointeeType();
-  QualType ToPointeeType = ToTypePtr->getPointeeType();
-
   // Objective C++: We're able to convert from a pointer to an
   // interface to a pointer to a different interface.
   const ObjCInterfaceType* FromIface = FromPointeeType->getAsObjCInterfaceType();
   const ObjCInterfaceType* ToIface = ToPointeeType->getAsObjCInterfaceType();
   if (FromIface && ToIface && 
       Context.canAssignObjCInterfaces(ToIface, FromIface)) {
-    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, 
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
                                                        ToPointeeType,
                                                        ToType, Context);
     return true;
@@ -887,7 +896,7 @@
     // interfaces, which is permitted. However, we're going to
     // complain about it.
     IncompatibleObjC = true;
-    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, 
+    ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
                                                        ToPointeeType,
                                                        ToType, Context);
     return true;
@@ -924,7 +933,7 @@
     return true;
   }
 
-  // If we have pointers to functions, check whether the only
+  // If we have pointers to functions or blocks, check whether the only
   // differences in the argument and result types are in Objective-C
   // pointer conversions. If so, we permit the conversion (but
   // complain about it).
diff --git a/test/SemaObjC/blocks.m b/test/SemaObjC/blocks.m
index dd8380a..8e72be6 100644
--- a/test/SemaObjC/blocks.m
+++ b/test/SemaObjC/blocks.m
@@ -20,3 +20,7 @@
 void foo4(id (^objectCreationBlock)(int)) {
     return bar4(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)()'}}
 }
+
+void foo5(id (^x)(int)) {
+  if (x) { }
+}
diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm
new file mode 100644
index 0000000..8aee152
--- /dev/null
+++ b/test/SemaObjCXX/blocks.mm
@@ -0,0 +1,26 @@
+// RUN: clang -fsyntax-only -verify -fblocks %s
+@protocol NSObject;
+
+void bar(id(^)(void));
+void foo(id <NSObject>(^objectCreationBlock)(void)) {
+    return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)(void)', expected 'id<NSObject> (^)(void)'}}
+}
+
+void bar2(id(*)(void));
+void foo2(id <NSObject>(*objectCreationBlock)(void)) {
+    return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)(void)', expected 'id<NSObject> (*)(void)'}}
+}
+
+void bar3(id(*)());
+void foo3(id (*objectCreationBlock)(int)) {
+    return bar3(objectCreationBlock); // expected-error{{incompatible type passing 'id (*)(int)', expected 'id (*)(void)'}}
+}
+
+void bar4(id(^)());
+void foo4(id (^objectCreationBlock)(int)) {
+    return bar4(objectCreationBlock); // expected-error{{incompatible type passing 'id (^)(int)', expected 'id (^)(void)'}}
+}
+
+void foo5(id (^x)(int)) {
+  if (x) { }
+}