forked from OSchip/llvm-project
Objective-C. Consider block pointer as NSObject as well as conforming to
'NSCopying' protocol when diagnosing block to ObjC pointer conversion. // rdar://16739120 llvm-svn: 210491
This commit is contained in:
parent
28f3ca66a9
commit
7ea91b2892
|
@ -5478,6 +5478,36 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
|
|||
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(QualType LHSType, ExprResult &RHS,
|
|||
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;
|
||||
|
|
|
@ -23,6 +23,7 @@ void r1(Sub* (^f)()) { // expected-note{{passing argument to parameter 'f' here}
|
|||
}
|
||||
|
||||
@protocol NSObject;
|
||||
@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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue