diff options
author | Steve Naroff <snaroff@apple.com> | 2009-03-01 16:12:44 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-03-01 16:12:44 +0000 |
commit | 114aecb26bfab1496b86fd6007669a3572a734b0 (patch) | |
tree | f472d7e804d3258104f2f892b1636782150d724a | |
parent | 3d23bb03c12e462259331cafd1f2f264a0a5b16b (diff) | |
download | bcm5719-llvm-114aecb26bfab1496b86fd6007669a3572a734b0.tar.gz bcm5719-llvm-114aecb26bfab1496b86fd6007669a3572a734b0.zip |
Fix <rdar://problem/6619539> incompatible pointer types sending 'XCElementSpacer *', expected 'XCElement *' (not handling protocol signatures correctly?).
- Reworked ASTContext::canAssignObjCInterfaces().
- Added ObjCProtocolDecl::lookupProtocolNamed().
llvm-svn: 65773
-rw-r--r-- | clang/include/clang/AST/DeclObjC.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 48 | ||||
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 13 | ||||
-rw-r--r-- | clang/test/SemaObjC/protocol-typecheck.m | 25 | ||||
-rw-r--r-- | clang/test/SemaObjC/protocol-undef.m | 3 |
5 files changed, 63 insertions, 28 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 33662b287d5..9bb327874b4 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -596,6 +596,8 @@ public: ReferencedProtocols.set(List, Num, C); } + ObjCProtocolDecl *lookupProtocolNamed(IdentifierInfo *PName); + // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupInstanceMethod(Selector Sel); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 749655d8712..2100a66c389 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2501,33 +2501,29 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, // Finally, we must have two protocol-qualified interfaces. const ObjCQualifiedInterfaceType *LHSP =cast<ObjCQualifiedInterfaceType>(LHS); const ObjCQualifiedInterfaceType *RHSP =cast<ObjCQualifiedInterfaceType>(RHS); - ObjCQualifiedInterfaceType::qual_iterator LHSPI = LHSP->qual_begin(); - ObjCQualifiedInterfaceType::qual_iterator LHSPE = LHSP->qual_end(); - ObjCQualifiedInterfaceType::qual_iterator RHSPI = RHSP->qual_begin(); - ObjCQualifiedInterfaceType::qual_iterator RHSPE = RHSP->qual_end(); - - // All protocols in LHS must have a presence in RHS. Since the protocol lists - // are both sorted alphabetically and have no duplicates, we can scan RHS and - // LHS in a single parallel scan until we run out of elements in LHS. - assert(LHSPI != LHSPE && "Empty LHS protocol list?"); - ObjCProtocolDecl *LHSProto = *LHSPI; - - while (RHSPI != RHSPE) { - ObjCProtocolDecl *RHSProto = *RHSPI++; - // If the RHS has a protocol that the LHS doesn't, ignore it. - if (RHSProto != LHSProto) - continue; - - // Otherwise, the RHS does have this element. - ++LHSPI; - if (LHSPI == LHSPE) - return true; // All protocols in LHS exist in RHS. - - LHSProto = *LHSPI; - } - // If we got here, we didn't find one of the LHS's protocols in the RHS list. - return false; + // All LHS protocols must have a presence on the RHS. + assert(LHSP->qual_begin() != LHSP->qual_end() && "Empty LHS protocol list?"); + + for (ObjCQualifiedInterfaceType::qual_iterator LHSPI = LHSP->qual_begin(), + LHSPE = LHSP->qual_end(); + LHSPI != LHSPE; LHSPI++) { + bool RHSImplementsProtocol = false; + + // If the RHS doesn't implement the protocol on the left, the types + // are incompatible. + for (ObjCQualifiedInterfaceType::qual_iterator RHSPI = RHSP->qual_begin(), + RHSPE = RHSP->qual_end(); + !RHSImplementsProtocol && (RHSPI != RHSPE); RHSPI++) { + if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) + RHSImplementsProtocol = true; + } + // FIXME: For better diagnostics, consider passing back the protocol name. + if (!RHSImplementsProtocol) + return false; + } + // The RHS implements all protocols listed on the LHS. + return true; } bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) { diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index bdbcce750d0..4d2fcb69ac7 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -412,6 +412,19 @@ void ObjCProtocolDecl::Destroy(ASTContext &C) { ObjCContainerDecl::Destroy(C); } +ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { + ObjCProtocolDecl *PDecl = this; + + if (Name == getIdentifier()) + return PDecl; + + for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I) + if ((PDecl = (*I)->lookupProtocolNamed(Name))) + return PDecl; + + return NULL; +} + // lookupInstanceMethod - Lookup a instance method in the protocol and protocols // it inherited. ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(Selector Sel) { diff --git a/clang/test/SemaObjC/protocol-typecheck.m b/clang/test/SemaObjC/protocol-typecheck.m new file mode 100644 index 00000000000..5ffe73fd938 --- /dev/null +++ b/clang/test/SemaObjC/protocol-typecheck.m @@ -0,0 +1,25 @@ +// RUN: clang -fsyntax-only -verify %s + +@interface NSObject @end +@protocol XCElementP @end +@protocol XCElementSpacerP <XCElementP> @end + +@protocol PWhatever @end + +@interface XX + +- (void)setFlexElement:(NSObject <PWhatever, XCElementP> *)flexer; +- (void)setFlexElement2:(NSObject <PWhatever, XCElementSpacerP> *)flexer; + +@end + +void func() { + NSObject <PWhatever, XCElementSpacerP> * flexer; + NSObject <PWhatever, XCElementP> * flexer2; + XX *obj; + [obj setFlexElement:flexer]; + // FIXME: GCC provides the following diagnostic (which is much better): + // protocol-typecheck.m:21: warning: class 'NSObject <PWhatever, XCElementP>' does not implement the 'XCElementSpacerP' protocol + [obj setFlexElement2:flexer2]; // expected-warning{{incompatible pointer types sending 'NSObject<PWhatever,XCElementP> *', expected 'NSObject<PWhatever,XCElementSpacerP> *'}} +} + diff --git a/clang/test/SemaObjC/protocol-undef.m b/clang/test/SemaObjC/protocol-undef.m index c35d3f86360..a490fa26fd8 100644 --- a/clang/test/SemaObjC/protocol-undef.m +++ b/clang/test/SemaObjC/protocol-undef.m @@ -40,8 +40,7 @@ typedef NSObject <OzzyActionDelegateP> OzzyActionDelegate; - (void)_recalculateStoredArraysForAnchor:(OzzyAnchor *)anchor { Ozzy * contentGroup = anchor.contentGroup; if (contentGroup == ((void *)0)) { - // GCC doesn't warn about the following (which seems wrong). - contentGroup = anchor; // expected-warning{{incompatible pointer types assigning 'OzzyAnchor *', expected 'Ozzy *'}} + contentGroup = anchor; } } @end |