From 48f4d4f428839d98293304bfbe83d804f2e8da2e Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 7 Apr 2018 17:42:06 +0000 Subject: [PATCH] Allow equality comparisons between block pointers and block-pointer-compatible ObjC object pointer types. Patch by Dustin Howett! llvm-svn: 329508 --- clang/lib/Sema/SemaExpr.cpp | 13 +++++++++ clang/test/SemaObjC/block-compare.mm | 51 ++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 clang/test/SemaObjC/block-compare.mm diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 71cbd7f..b8cadaf 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10029,6 +10029,19 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, 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())) { diff --git a/clang/test/SemaObjC/block-compare.mm b/clang/test/SemaObjC/block-compare.mm new file mode 100644 index 0000000..c63f484 --- /dev/null +++ b/clang/test/SemaObjC/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; +} -- 2.7.4