r210491 - Objective-C. Consider block pointer as NSObject as well as conforming to
Fariborz Jahanian
fjahanian at apple.com
Mon Jun 9 14:42:02 PDT 2014
Author: fjahanian
Date: Mon Jun 9 16:42:01 2014
New Revision: 210491
URL: http://llvm.org/viewvc/llvm-project?rev=210491&view=rev
Log:
Objective-C. Consider block pointer as NSObject as well as conforming to
'NSCopying' protocol when diagnosing block to ObjC pointer conversion.
// rdar://16739120
Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/SemaObjC/block-type-safety.m
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=210491&r1=210490&r2=210491&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Jun 9 16:42:01 2014
@@ -5478,6 +5478,36 @@ static QualType checkConditionalPointerC
return ResultTy;
}
+/// \brief Returns true if QT is quelified-id and implements 'NSObject' and/or
+/// 'NSCopying' protocols (and nothing else); or QT is an NSObject and optionally
+/// implements 'NSObject' and/or NSCopying' protocols (and nothing else).
+static bool isObjCPtrBlockCompatible(Sema &S, ASTContext &C, QualType QT) {
+ if (QT->isObjCIdType())
+ return true;
+
+ const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>();
+ if (!OPT)
+ return false;
+
+ if (ObjCInterfaceDecl *ID = OPT->getInterfaceDecl())
+ if (ID->getIdentifier() != &C.Idents.get("NSObject"))
+ return false;
+
+ ObjCProtocolDecl* PNSCopying =
+ S.LookupProtocol(&C.Idents.get("NSCopying"), SourceLocation());
+ ObjCProtocolDecl* PNSObject =
+ S.LookupProtocol(&C.Idents.get("NSObject"), SourceLocation());
+
+ for (auto *Proto : OPT->quals()) {
+ if ((PNSCopying && declaresSameEntity(Proto, PNSCopying)) ||
+ (PNSObject && declaresSameEntity(Proto, PNSObject)))
+ ;
+ else
+ return false;
+ }
+ return true;
+}
+
/// \brief Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
@@ -6435,8 +6465,9 @@ Sema::CheckAssignmentConstraints(QualTyp
return IncompatiblePointer;
}
- // T^ -> id; not T^ ->A* and not T^ -> id<P>
- if (RHSType->isBlockPointerType() && LHSType->isObjCIdType()) {
+ // Only under strict condition T^ is compatible with an Objective-C pointer.
+ if (RHSType->isBlockPointerType() &&
+ isObjCPtrBlockCompatible(*this, Context, LHSType)) {
maybeExtendBlockObject(*this, RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
Modified: cfe/trunk/test/SemaObjC/block-type-safety.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/block-type-safety.m?rev=210491&r1=210490&r2=210491&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/block-type-safety.m (original)
+++ cfe/trunk/test/SemaObjC/block-type-safety.m Mon Jun 9 16:42:01 2014
@@ -23,6 +23,7 @@ void r1(Sub* (^f)()) { // expected-note{
}
@protocol NSObject;
+ at class NSObject;
void r2 (id<NSObject> (^f) (void)) {
id o = f();
@@ -177,3 +178,23 @@ NSArray* anArray1;
aBlock = anArray1; // expected-error {{assigning to 'void (^)()' from incompatible type 'NSArray *'}}
}
+void Test2() {
+ void (^aBlock)();
+ id<NSObject> anQualId1 = aBlock; // Ok
+ id<NSObject, NSCopying> anQualId2 = aBlock; // Ok
+ id<NSObject, NSCopying, NSObject, NSCopying> anQualId3 = aBlock; // Ok
+ id <P1> anQualId4 = aBlock; // expected-error {{initializing 'id<P1>' with an expression of incompatible type 'void (^)()'}}
+ id<NSObject, P1, NSCopying> anQualId5 = aBlock; // expected-error {{initializing 'id<NSObject,P1,NSCopying>' with an expression of incompatible type 'void (^)()'}}
+ id<NSCopying> anQualId6 = aBlock; // Ok
+}
+
+void Test3() {
+ void (^aBlock)();
+ NSObject *NSO = aBlock; // Ok
+ NSObject<NSObject> *NSO1 = aBlock; // Ok
+ NSObject<NSObject, NSCopying> *NSO2 = aBlock; // Ok
+ NSObject<NSObject, NSCopying, NSObject, NSCopying> *NSO3 = aBlock; // Ok
+ NSObject <P1> *NSO4 = aBlock; // expected-error {{initializing 'NSObject<P1> *' with an expression of incompatible type 'void (^)()'}}
+ NSObject<NSObject, P1, NSCopying> *NSO5 = aBlock; // expected-error {{initializing 'NSObject<NSObject,P1,NSCopying> *' with an expression of incompatible type 'void (^)()'}}
+ NSObject<NSCopying> *NSO6 = aBlock; // Ok
+}
More information about the cfe-commits
mailing list