vsapsai created this revision. vsapsai added reviewers: erik.pilkington, arphaman. Herald added subscribers: ributzka, dexonsmith, jkorous.
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 https://reviews.llvm.org/D66831 Files: clang/lib/AST/ASTContext.cpp clang/test/SemaObjC/block-type-safety.m Index: clang/test/SemaObjC/block-type-safety.m =================================================================== --- clang/test/SemaObjC/block-type-safety.m +++ 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; } Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ 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();
Index: clang/test/SemaObjC/block-type-safety.m =================================================================== --- clang/test/SemaObjC/block-type-safety.m +++ 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; } Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ 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();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits