Block return type of the initialized must be
be more speciaclized than that of the initializer,
when matching protocol qualifier list.
// rdar:// 9118343.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127585 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index bed7e18..ad69f0f 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1333,7 +1333,8 @@
                                const ObjCObjectType *RHS);
   bool canAssignObjCInterfacesInBlockPointer(
                                           const ObjCObjectPointerType *LHSOPT,
-                                          const ObjCObjectPointerType *RHSOPT);
+                                          const ObjCObjectPointerType *RHSOPT,
+                                          bool BlockReturnType);
   bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
   QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
                                    const ObjCObjectPointerType *RHSOPT);
@@ -1341,7 +1342,7 @@
 
   // Functions for calculating composite types
   QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
-                      bool Unqualified = false);
+                      bool Unqualified = false, bool BlockReturnType = false);
   QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
                               bool Unqualified = false);
   QualType mergeFunctionArgumentTypes(QualType, QualType,
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 0526ebb..d20c258 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4838,7 +4838,8 @@
 /// not OK. For the return type, the opposite is not OK.
 bool ASTContext::canAssignObjCInterfacesInBlockPointer(
                                          const ObjCObjectPointerType *LHSOPT,
-                                         const ObjCObjectPointerType *RHSOPT) {
+                                         const ObjCObjectPointerType *RHSOPT,
+                                         bool BlockReturnType) {
   if (RHSOPT->isObjCBuiltinType() || LHSOPT->isObjCIdType())
     return true;
   
@@ -4856,9 +4857,9 @@
   if (LHS && RHS)  { // We have 2 user-defined types.
     if (LHS != RHS) {
       if (LHS->getDecl()->isSuperClassOf(RHS->getDecl()))
-        return false;
+        return BlockReturnType;
       if (RHS->getDecl()->isSuperClassOf(LHS->getDecl()))
-        return true;
+        return !BlockReturnType;
     }
     else
       return true;
@@ -5082,7 +5083,7 @@
     bool UnqualifiedResult = Unqualified;
     if (!UnqualifiedResult)
       UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers());
-    retType = mergeTypes(RHS, LHS, true, UnqualifiedResult);
+    retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, true);
   }
   else
     retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false,
@@ -5222,7 +5223,7 @@
 
 QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, 
                                 bool OfBlockPointer,
-                                bool Unqualified) {
+                                bool Unqualified, bool BlockReturnType) {
   // C++ [expr]: If an expression initially has the type "reference to T", the
   // type is adjusted to "T" prior to any further analysis, the expression
   // designates the object or function denoted by the reference, and the
@@ -5456,7 +5457,8 @@
     if (OfBlockPointer) {
       if (canAssignObjCInterfacesInBlockPointer(
                                           LHS->getAs<ObjCObjectPointerType>(),
-                                          RHS->getAs<ObjCObjectPointerType>()))
+                                          RHS->getAs<ObjCObjectPointerType>(),
+                                          BlockReturnType))
       return LHS;
       return QualType();
     }
diff --git a/test/SemaObjC/block-type-safety.m b/test/SemaObjC/block-type-safety.m
index c13e806..ebc6777 100644
--- a/test/SemaObjC/block-type-safety.m
+++ b/test/SemaObjC/block-type-safety.m
@@ -121,3 +121,20 @@
     return 0;
 }
 
+// rdar:// 9118343
+
+@protocol NSCopying @end
+
+@interface NSAllArray <NSCopying>
+@end
+
+@interface NSAllArray (FooConformance) <Foo>
+@end
+
+int test5() {
+    NSAllArray *(^block)(id);
+    id <Foo> (^genericBlock)(id);
+    genericBlock = block;
+    return 0;
+}
+