aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2010-07-19 22:02:22 +0000
committerFariborz Jahanian <fjahanian@apple.com>2010-07-19 22:02:22 +0000
commita8f8dac6a29f6d33474a38a32ce9dd859b696da9 (patch)
treee6ec19f35c62814246229380bad479ff3564610b
parentbaa400654bd6f8396f9a07188445ae7955b060a3 (diff)
Patch to type match comparing Objective-C Classes which implement
protocols (Radar 8191774). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108758 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h2
-rw-r--r--lib/AST/ASTContext.cpp32
-rw-r--r--test/SemaObjC/compare-qualified-class.m30
3 files changed, 63 insertions, 1 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 3799451360..488cfe0929 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1235,6 +1235,8 @@ public:
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare);
+ bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
+
// Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d41051f5dc..03e91f101e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -4226,6 +4226,32 @@ bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) {
return false;
}
+/// ObjCQualifiedClassTypesAreCompatible - compare Class<p,...> and
+/// Class<p1, ...>.
+bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs,
+ QualType rhs) {
+ const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>();
+ const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>();
+ assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible");
+
+ for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(),
+ E = lhsQID->qual_end(); I != E; ++I) {
+ bool match = false;
+ ObjCProtocolDecl *lhsProto = *I;
+ for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(),
+ E = rhsOPT->qual_end(); J != E; ++J) {
+ ObjCProtocolDecl *rhsProto = *J;
+ if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) {
+ match = true;
+ break;
+ }
+ }
+ if (!match)
+ return false;
+ }
+ return true;
+}
+
/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an
/// ObjCQualifiedIDType.
bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
@@ -4365,7 +4391,11 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0),
QualType(RHSOPT,0),
false);
-
+
+ if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass())
+ return ObjCQualifiedClassTypesAreCompatible(QualType(LHSOPT,0),
+ QualType(RHSOPT,0));
+
// If we have 2 user-defined types, fall into that path.
if (LHS->getInterface() && RHS->getInterface())
return canAssignObjCInterfaces(LHS, RHS);
diff --git a/test/SemaObjC/compare-qualified-class.m b/test/SemaObjC/compare-qualified-class.m
new file mode 100644
index 0000000000..cb2b26a4f7
--- /dev/null
+++ b/test/SemaObjC/compare-qualified-class.m
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// rdar:// 8191774
+
+@protocol SomeProtocol
+@end
+
+@protocol SomeProtocol1
+@end
+
+@interface SomeObject <SomeProtocol>
+@end
+
+int main () {
+ Class <SomeProtocol> classA;
+ Class <SomeProtocol> classB;
+ Class <SomeProtocol, SomeProtocol1> classC;
+ Class <SomeProtocol1> classD;
+ void * pv = 0;
+ Class c = (Class)0;;
+ if (pv)
+ return classA == pv;
+
+ if (c)
+ return classA == c;
+
+ return classA == classB || classA == classC ||
+ classC == classA ||
+ classA == classD; // expected-warning {{comparison of distinct pointer types ('Class<SomeProtocol> *' and 'Class<SomeProtocol1> *')}}
+}
+