]> granicus.if.org Git - clang/commitdiff
More objective-c type analysis. This time involving objective types
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 21 Dec 2007 00:33:59 +0000 (00:33 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 21 Dec 2007 00:33:59 +0000 (00:33 +0000)
of conforming protocols (or not).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@45276 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
Sema/SemaExpr.cpp
include/clang/AST/ASTContext.h

index 417c56570ac71290e484e330fec707b10ced630a..5ec5131074ff9a0e6a87cd1213dcdc63ad7a13d7 100644 (file)
@@ -1278,10 +1278,25 @@ bool ASTContext::QualifiedInterfaceTypesAreCompatible(QualType lhs,
   return true;
 }
 
+/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the
+/// inheritance hierarchy of 'rProto'.
+static bool ProtocolCompatibleWithProtocol(ObjcProtocolDecl *lProto,
+                                           ObjcProtocolDecl *rProto) {
+  if (lProto == rProto)
+    return true;
+  ObjcProtocolDecl** RefPDecl = rProto->getReferencedProtocols();
+  for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++)
+    if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i]))
+      return true;
+  return false;
+}
+
 /// ObjcQualifiedIdTypesAreCompatible - Compares two types, at least
-/// one of which is a protocol qualified 'id' type.
+/// one of which is a protocol qualified 'id' type. When 'compare'
+/// is true it is for comparison; when false, for assignment/initialization.
 bool ASTContext::ObjcQualifiedIdTypesAreCompatible(QualType lhs, 
-                                                   QualType rhs) {
+                                                   QualType rhs,
+                                                   bool compare) {
   // match id<P..> with an 'id' type in all cases.
   if (const PointerType *PT = lhs->getAsPointerType()) {
     QualType PointeeTy = PT->getPointeeType();
@@ -1339,7 +1354,8 @@ bool ASTContext::ObjcQualifiedIdTypesAreCompatible(QualType lhs,
       }
       for (unsigned j = 0; j < numRhsProtocols; j++) {
         ObjcProtocolDecl *rhsProto = rhsProtoList[j];
-        if (lhsProto == rhsProto) {
+        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+            compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
           match = true;
           break;
         }
@@ -1385,7 +1401,8 @@ bool ASTContext::ObjcQualifiedIdTypesAreCompatible(QualType lhs,
       ObjcProtocolDecl *lhsProto = lhsProtoList[i];
       for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
         ObjcProtocolDecl *rhsProto = rhsQID->getProtocols(j);
-        if (lhsProto == rhsProto) {
+        if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+          compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
           match = true;
           break;
         }
index e720c2e460343c081d497beed921ed0c4c3d1009..d7a89865ea0edc06b63763940358e310bd42cbf7 100644 (file)
@@ -1400,7 +1400,7 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8
     return Context.IntTy;
   }
   if ((lType->isObjcQualifiedIdType() || rType->isObjcQualifiedIdType())
-      && Context.ObjcQualifiedIdTypesAreCompatible(lType, rType)) {
+      && Context.ObjcQualifiedIdTypesAreCompatible(lType, rType, true)) {
     promoteExprToType(rex, lType); 
     return Context.IntTy;
   }
index 80188e25cf54c04f72e1eab189f373346e5c6668..a96cb5dfdc820f3a72ceca627dd7fe6578a3873c 100644 (file)
@@ -297,7 +297,7 @@ public:
   /// Objective-C specific type checking.
   bool interfaceTypesAreCompatible(QualType, QualType);
   bool QualifiedInterfaceTypesAreCompatible(QualType, QualType);
-  bool ObjcQualifiedIdTypesAreCompatible(QualType, QualType);
+  bool ObjcQualifiedIdTypesAreCompatible(QualType, QualType, bool = false);
   bool objcTypesAreCompatible(QualType, QualType);
   bool isObjcIdType(QualType T) const {
     if (!IdStructType) // ObjC isn't enabled