summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2009-03-01 16:12:44 +0000
committerSteve Naroff <snaroff@apple.com>2009-03-01 16:12:44 +0000
commit114aecb26bfab1496b86fd6007669a3572a734b0 (patch)
treef472d7e804d3258104f2f892b1636782150d724a
parent3d23bb03c12e462259331cafd1f2f264a0a5b16b (diff)
downloadbcm5719-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.h2
-rw-r--r--clang/lib/AST/ASTContext.cpp48
-rw-r--r--clang/lib/AST/DeclObjC.cpp13
-rw-r--r--clang/test/SemaObjC/protocol-typecheck.m25
-rw-r--r--clang/test/SemaObjC/protocol-undef.m3
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
OpenPOWER on IntegriCloud