Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -7745,8 +7745,8 @@ return IntToBlockPointer; } - // id -> T^ - if (getLangOpts().ObjC1 && RHSType->isObjCIdType()) { + // id (or strictly compatible object type) -> T^ + if (getLangOpts().ObjC1 && RHSType->isBlockCompatibleObjCPointerType(Context)) { Kind = CK_AnyPointerToBlockPointerCast; return Compatible; } @@ -10028,6 +10028,18 @@ RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast); return ResultTy; } + + if(!IsRelational && + LHSType->isBlockPointerType() && + RHSType->isBlockCompatibleObjCPointerType(Context)) { + LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BlockPointerToObjCPointerCast); + return ResultTy; + } else if(!IsRelational && + LHSType->isBlockCompatibleObjCPointerType(Context) && + RHSType->isBlockPointerType()) { + RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BlockPointerToObjCPointerCast); + return ResultTy; + } } if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) || (LHSType->isIntegerType() && RHSType->isAnyPointerType())) { Index: test/Sema/objc_block_compare.mm =================================================================== --- /dev/null +++ test/Sema/objc_block_compare.mm @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -S -o - -triple i686-windows -verify -fblocks \ +// RUN: -Wno-unused-comparison %s + +#pragma clang diagnostic ignored "-Wunused-comparison" + +#define nil ((id)nullptr) + +@protocol NSObject +@end + +@protocol NSCopying +@end + +@protocol OtherProtocol +@end + +__attribute__((objc_root_class)) +@interface NSObject +@end + +__attribute__((objc_root_class)) +@interface Test +@end + +int main() { + void (^block)() = ^{}; + NSObject *object; + id qualifiedId; + + id poorlyQualified1; + Test *objectOfWrongType; + + block == nil; + block == object; + block == qualifiedId; + + nil == block; + object == block; + qualifiedId == block; + + // these are still not valid: blocks must be compared with id, NSObject*, or a protocol-qualified id + // conforming to NSCopying or NSObject. + + block == poorlyQualified1; // expected-error {{invalid operands to binary expression ('void (^)()' and 'id')}} + block == objectOfWrongType; // expected-error {{invalid operands to binary expression ('void (^)()' and 'Test *')}} + + poorlyQualified1 == block; // expected-error {{invalid operands to binary expression ('id' and 'void (^)()')}} + objectOfWrongType == block; // expected-error {{invalid operands to binary expression ('Test *' and 'void (^)()')}} + + return 0; +}