[ObjC] Fix type checking for qualified id block parameters.
When checking if block types are compatible, we are checking for
compatibility their return types and parameters' types. As these types
have different variance, we need to check them in different order.
rdar://problem/52788423
Reviewers: erik.pilkington, arphaman
Reviewed By: arphaman
Subscribers: jkorous, dexonsmith, ributzka, cfe-commits
Differential Revision: https://reviews.llvm.org/D66831
llvm-svn: 370130
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 03683ce..063c202 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -8191,9 +8191,9 @@
}
if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType())
- return finish(ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
- QualType(RHSOPT,0),
- false));
+ return finish(ObjCQualifiedIdTypesAreCompatible(
+ QualType(BlockReturnType ? LHSOPT : RHSOPT, 0),
+ QualType(BlockReturnType ? RHSOPT : LHSOPT, 0), false));
const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
diff --git a/clang/test/SemaObjC/block-type-safety.m b/clang/test/SemaObjC/block-type-safety.m
index 96c781b..66fda2d 100644
--- a/clang/test/SemaObjC/block-type-safety.m
+++ b/clang/test/SemaObjC/block-type-safety.m
@@ -133,9 +133,20 @@
@end
int test5() {
+ // Returned value is used outside of a block, so error on changing
+ // a return type to a more general than expected.
NSAllArray *(^block)(id);
id <Foo> (^genericBlock)(id);
genericBlock = block;
+ block = genericBlock; // expected-error {{incompatible block pointer types assigning to 'NSAllArray *(^)(id)' from 'id<Foo> (^)(id)'}}
+
+ // A parameter is used inside a block, so error on changing a parameter type
+ // to a more specific than an argument type it will be called with.
+ // rdar://problem/52788423
+ void (^blockWithParam)(NSAllArray *);
+ void (^genericBlockWithParam)(id<Foo>);
+ genericBlockWithParam = blockWithParam; // expected-error {{incompatible block pointer types assigning to 'void (^)(id<Foo>)' from 'void (^)(NSAllArray *)'}}
+ blockWithParam = genericBlockWithParam;
return 0;
}