]> granicus.if.org Git - clang/commitdiff
move ObjCQualifiedIdTypesAreCompatible out of ASTContext into Sema.
authorChris Lattner <sabre@nondot.org>
Mon, 7 Apr 2008 05:30:13 +0000 (05:30 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 7 Apr 2008 05:30:13 +0000 (05:30 +0000)
While it is similar to the other compatibility predicates in ASTContext,
it is not used by them and is different.

In addition, greatly simplify ObjCQualifiedIdTypesAreCompatible and
fix some canonical type bugs.  Also, simplify my Type::getAsObjC* methods.

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

include/clang/AST/ASTContext.h
include/clang/AST/DeclObjC.h
lib/AST/ASTContext.cpp
lib/AST/Type.cpp
lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprObjC.cpp

index 188d440407d16ea4efa31efd66859c82f1ffe3ee..bec9efa2b13b80d90aca208e2baf52f8e866b6f3 100644 (file)
@@ -335,7 +335,6 @@ public:
   bool builtinTypesAreCompatible(QualType, QualType);
   bool vectorTypesAreCompatible(QualType, QualType);
   
-  bool ObjCQualifiedIdTypesAreCompatible(QualType, QualType, bool = false);
   bool objcTypesAreCompatible(QualType, QualType);
   bool isObjCIdType(QualType T) const {
     if (!IdStructType) // ObjC isn't enabled
index 04bf38b87d7b977ee1d5e986478716fec3479931..a1e0f256fc74c2701757d4c6803dfde0aac4e857 100644 (file)
@@ -420,11 +420,15 @@ private:
 /// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ 
 /// feature with nice semantics and lousy syntax:-). Here is an example:
 ///
-/// @protocol NSDraggingInfo
+/// @protocol NSDraggingInfo <refproto1, refproto2>
 /// - (NSWindow *)draggingDestinationWindow;
 /// - (NSImage *)draggedImage;
 /// @end
 ///
+/// This says that NSDraggingInfo requires two methods and requires everything
+/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as
+/// well.
+///
 /// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo>
 /// @end
 ///
index 65c4e0567f7d499fb0d04b1df50727a2f4a7367d..439a99c4b266388c87d8a60d685341e6b65fd183 100644 (file)
@@ -1507,182 +1507,6 @@ areCompatObjCQualInterfaces(const ObjCQualifiedInterfaceType *LHS,
   return false;
 }
 
-/// 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;
-}
-
-/// ClassImplementsProtocol - Checks that 'lProto' protocol
-/// has been implemented in IDecl class, its super class or categories (if
-/// lookupCategory is true). 
-static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
-                                    ObjCInterfaceDecl *IDecl, 
-                                    bool lookupCategory) {
-  
-  // 1st, look up the class.
-  ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols();
-  for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) {
-    if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
-      return true;
-  }
-  
-  // 2nd, look up the category.
-  if (lookupCategory)
-    for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
-         CDecl = CDecl->getNextClassCategory()) {
-      protoList = CDecl->getReferencedProtocols();
-      for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) {
-        if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
-          return true;
-      }
-    }
-  
-  // 3rd, look up the super class(s)
-  if (IDecl->getSuperClass())
-    return 
-      ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory);
-  
-  return false;
-}
-                                           
-/// ObjCQualifiedIdTypesAreCompatible - Compares two types, at least
-/// 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,
-                                                   bool compare) {
-  // match id<P..> with an 'id' type in all cases.
-  if (const PointerType *PT = lhs->getAsPointerType()) {
-    QualType PointeeTy = PT->getPointeeType();
-    if (isObjCIdType(PointeeTy) || PointeeTy->isVoidType())
-      return true;
-  } else if (const PointerType *PT = rhs->getAsPointerType()) {
-    QualType PointeeTy = PT->getPointeeType();
-    if (isObjCIdType(PointeeTy) || PointeeTy->isVoidType())
-      return true;
-  }
-  
-  ObjCQualifiedInterfaceType *lhsQI = 0;
-  ObjCQualifiedInterfaceType *rhsQI = 0;
-  ObjCInterfaceDecl *lhsID = 0;
-  ObjCInterfaceDecl *rhsID = 0;
-  ObjCQualifiedIdType *lhsQID = dyn_cast<ObjCQualifiedIdType>(lhs);
-  ObjCQualifiedIdType *rhsQID = dyn_cast<ObjCQualifiedIdType>(rhs);
-  
-  if (lhsQID) {
-    if (!rhsQID && rhs->getTypeClass() == Type::Pointer) {
-      QualType rtype = 
-        cast<PointerType>(rhs.getCanonicalType())->getPointeeType();
-      rhsQI = 
-        dyn_cast<ObjCQualifiedInterfaceType>(
-          rtype.getCanonicalType().getTypePtr());
-      if (!rhsQI) {
-        ObjCInterfaceType *IT = dyn_cast<ObjCInterfaceType>(
-                                  rtype.getCanonicalType().getTypePtr());
-        if (IT)
-          rhsID = IT->getDecl();
-      }
-    }
-    if (!rhsQI && !rhsQID && !rhsID)
-      return false;
-    
-    ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
-    if (rhsQI) {
-      RHSProtoI = rhsQI->qual_begin();
-      RHSProtoE = rhsQI->qual_end();
-    } else if (rhsQID) {
-      RHSProtoI = rhsQID->qual_begin();
-      RHSProtoE = rhsQID->qual_end();
-    }
-    
-    for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) {
-      ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i);
-      bool match = false;
-
-      // when comparing an id<P> on lhs with a static type on rhs,
-      // see if static class implements all of id's protocols, directly or
-      // through its super class and categories.
-      if (rhsID) {
-        if (ClassImplementsProtocol(lhsProto, rhsID, true))
-          match = true;
-      } else {
-        for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
-          ObjCProtocolDecl *rhsProto = *RHSProtoI;
-          if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
-              compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
-            match = true;
-            break;
-          }
-        }
-      }
-      if (!match)
-        return false;
-    }    
-  }
-  else if (rhsQID) {
-    if (!lhsQID && lhs->getTypeClass() == Type::Pointer) {
-      QualType ltype = 
-      cast<PointerType>(lhs.getCanonicalType())->getPointeeType();
-      lhsQI = 
-      dyn_cast<ObjCQualifiedInterfaceType>(
-        ltype.getCanonicalType().getTypePtr());
-      if (!lhsQI) {
-        ObjCInterfaceType *IT = dyn_cast<ObjCInterfaceType>(
-                                  ltype.getCanonicalType().getTypePtr());
-        if (IT)
-          lhsID = IT->getDecl();
-      }
-    }
-    if (!lhsQI && !lhsQID && !lhsID)
-      return false;
-    
-    ObjCQualifiedIdType::qual_iterator LHSProtoI, LHSProtoE;
-    if (lhsQI) {
-      LHSProtoI = lhsQI->qual_begin();
-      LHSProtoE = lhsQI->qual_end();
-    } else if (lhsQID) {
-      LHSProtoI = lhsQID->qual_begin();
-      LHSProtoE = lhsQID->qual_end();
-    }
-    
-    bool match = false;
-    // for static type vs. qualified 'id' type, check that class implements
-    // one of 'id's protocols.
-    if (lhsID) {
-      for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
-        ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
-        if (ClassImplementsProtocol(rhsProto, lhsID, compare)) {
-          match = true;
-          break;
-        }
-      }
-    } else {
-      for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
-        match = false;
-        ObjCProtocolDecl *lhsProto = *LHSProtoI;
-        for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
-          ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
-          if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
-            compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
-            match = true;
-            break;
-          }
-        }
-      }
-    }
-    if (!match)
-      return false;
-  }
-  return true;
-}
 
 bool ASTContext::vectorTypesAreCompatible(QualType lhs, QualType rhs) {
   const VectorType *lVector = lhs->getAsVectorType();
index 16f54cae132a112cb327e6188d04aa5b318c0c7d..f80f3641da020508a0701fec46cbea009b0e44b2 100644 (file)
@@ -429,42 +429,22 @@ const OCUVectorType *Type::getAsOCUVectorType() const {
 }
 
 const ObjCInterfaceType *Type::getAsObjCInterfaceType() const {
-  // Are we directly an ObjCInterface type?
-  if (const ObjCInterfaceType *VTy = dyn_cast<ObjCInterfaceType>(this))
-    return VTy;
-  
-  // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ObjCInterfaceType>(CanonicalType)) {  
-    // Look through type qualifiers
-    if (isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->getAsObjCInterfaceType();
-    return 0;
-  }
-  
-  // If this is a typedef for an objc interface type, strip the typedef off
-  // without losing all typedef information.
-  return getDesugaredType()->getAsObjCInterfaceType();
+  // There is no sugar for ObjCInterfaceType's, just return the canonical
+  // type pointer if it is the right class.
+  return dyn_cast<ObjCInterfaceType>(CanonicalType);
 }
 
 const ObjCQualifiedInterfaceType *
 Type::getAsObjCQualifiedInterfaceType() const {
-  // Are we directly an ObjCQualifiedInterfaceType?
-  if (const ObjCQualifiedInterfaceType *VTy =
-         dyn_cast<ObjCQualifiedInterfaceType>(this))
-    return VTy;
-  
-  // If the canonical form of this type isn't the right kind, reject it.
-  if (!isa<ObjCQualifiedInterfaceType>(CanonicalType)) {  
-    // Look through type qualifiers
-    if (isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType()))
-      return CanonicalType.getUnqualifiedType()->
-         getAsObjCQualifiedInterfaceType();
-    return 0;
-  }
-  
-  // If this is a typedef for an objc qual interface type, strip the typedef off
-  // without losing all typedef information.
-  return getDesugaredType()->getAsObjCQualifiedInterfaceType();
+  // There is no sugar for ObjCQualifiedInterfaceType's, just return the canonical
+  // type pointer if it is the right class.
+  return dyn_cast<ObjCQualifiedInterfaceType>(CanonicalType);
+}
+
+const ObjCQualifiedIdType *Type::getAsObjCQualifiedIdType() const {
+  // There is no sugar for ObjCQualifiedIdType's, just return the canonical
+  // type pointer if it is the right class.
+  return dyn_cast<ObjCQualifiedIdType>(CanonicalType);
 }
 
 
index 98ecf87ce66274d6da94bf7495b73f5635044204..70aaf24791604f7c76c0ecf8701b5769a37defb1 100644 (file)
@@ -825,6 +825,10 @@ private:
                                           unsigned NewWidth, bool NewSign,
                                           SourceLocation Loc, unsigned DiagID);
   
+  bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
+                                         bool ForCompare);
+
+  
   void InitBuiltinVaListType();
   
   //===--------------------------------------------------------------------===//
index a661d0172bf44085b231439d17892f51b6fa51ad..a528519d2655e5716545b471a6a38db1255cbc26 100644 (file)
@@ -1185,9 +1185,8 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
     return Incompatible;
   }
   
-  if (lhsType->isObjCQualifiedIdType() 
-           || rhsType->isObjCQualifiedIdType()) {
-    if (Context.ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType))
+  if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) {
+    if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false))
       return Compatible;
     return Incompatible;
   }
@@ -1368,9 +1367,9 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
   return InvalidOperands(loc, lex, rex);
 }
 
-inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
-  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) 
-{
+// C99 6.5.6
+QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex,
+                                        SourceLocation loc, bool isCompAssign) {
   if (lex->getType()->isVectorType() || rex->getType()->isVectorType())
     return CheckVectorOperands(loc, lex, rex);
     
@@ -1437,8 +1436,9 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
   return InvalidOperands(loc, lex, rex);
 }
 
-inline QualType Sema::CheckShiftOperands( // C99 6.5.7
-  Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) {
+// C99 6.5.7
+QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
+                                  bool isCompAssign) {
   // C99 6.5.7p2: Each of the operands shall have integer type.
   if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType())
     return InvalidOperands(loc, lex, rex);
@@ -1453,9 +1453,9 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7
   return lex->getType();
 }
 
-inline QualType Sema::CheckCompareOperands( // C99 6.5.8
-  Expr *&lex, Expr *&rex, SourceLocation loc, bool isRelational)
-{
+// C99 6.5.8
+QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc,
+                                    bool isRelational) {
   // C99 6.5.8p3 / C99 6.5.9p4
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
     UsualArithmeticConversions(lex, rex);
@@ -1514,7 +1514,7 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8
     return Context.IntTy;
   }
   if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())
-      && Context.ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
+      && ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
     ImpCastExprToType(rex, lType); 
     return Context.IntTy;
   }
index ec6e41bf39f25c6d9e59b794e9293a6aac6ae2a8..63dd0d780fd057987a4daec5ec9468d26902562f 100644 (file)
@@ -297,3 +297,170 @@ Sema::ExprResult Sema::ActOnInstanceMessage(
   return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, 
                              ArgExprs, NumArgs);
 }
+
+//===----------------------------------------------------------------------===//
+// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's.
+//===----------------------------------------------------------------------===//
+
+/// 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;
+}
+
+/// ClassImplementsProtocol - Checks that 'lProto' protocol
+/// has been implemented in IDecl class, its super class or categories (if
+/// lookupCategory is true). 
+static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto,
+                                    ObjCInterfaceDecl *IDecl, 
+                                    bool lookupCategory) {
+  
+  // 1st, look up the class.
+  ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols();
+  for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) {
+    if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
+      return true;
+  }
+  
+  // 2nd, look up the category.
+  if (lookupCategory)
+    for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl;
+         CDecl = CDecl->getNextClassCategory()) {
+      protoList = CDecl->getReferencedProtocols();
+      for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) {
+        if (ProtocolCompatibleWithProtocol(lProto, protoList[i]))
+          return true;
+      }
+    }
+  
+  // 3rd, look up the super class(s)
+  if (IDecl->getSuperClass())
+    return 
+      ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory);
+  
+  return false;
+}
+
+bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
+                                             bool compare) {
+  // Allow id<P..> and an 'id' or void* type in all cases.
+  if (const PointerType *PT = lhs->getAsPointerType()) {
+    QualType PointeeTy = PT->getPointeeType();
+    if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType())
+      return true;
+  } else if (const PointerType *PT = rhs->getAsPointerType()) {
+    QualType PointeeTy = PT->getPointeeType();
+    if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType())
+      return true;
+  }
+  
+  const ObjCQualifiedInterfaceType *lhsQI = 0;
+  const ObjCQualifiedInterfaceType *rhsQI = 0;
+  ObjCInterfaceDecl *lhsID = 0;
+  ObjCInterfaceDecl *rhsID = 0;
+  const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType();
+  const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType();
+  
+  if (lhsQID) {
+    if (!rhsQID && rhs->isPointerType()) {
+      QualType rtype = rhs->getAsPointerType()->getPointeeType();
+      rhsQI = rtype->getAsObjCQualifiedInterfaceType();
+      if (!rhsQI) {
+        if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType())
+          rhsID = IT->getDecl();
+      }
+    }
+    if (!rhsQI && !rhsQID && !rhsID)
+      return false;
+    
+    ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE;
+    if (rhsQI) {
+      RHSProtoI = rhsQI->qual_begin();
+      RHSProtoE = rhsQI->qual_end();
+    } else if (rhsQID) {
+      RHSProtoI = rhsQID->qual_begin();
+      RHSProtoE = rhsQID->qual_end();
+    }
+    
+    for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) {
+      ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i);
+      bool match = false;
+
+      // when comparing an id<P> on lhs with a static type on rhs,
+      // see if static class implements all of id's protocols, directly or
+      // through its super class and categories.
+      if (rhsID) {
+        if (ClassImplementsProtocol(lhsProto, rhsID, true))
+          match = true;
+      } else {
+        for (; RHSProtoI != RHSProtoE; ++RHSProtoI) {
+          ObjCProtocolDecl *rhsProto = *RHSProtoI;
+          if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+              compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
+            match = true;
+            break;
+          }
+        }
+      }
+      if (!match)
+        return false;
+    }    
+  } else if (rhsQID) {
+    if (!lhsQID && lhs->isPointerType()) {
+      QualType ltype = lhs->getAsPointerType()->getPointeeType();
+      lhsQI = ltype->getAsObjCQualifiedInterfaceType();
+      if (!lhsQI) {
+        if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType())
+          lhsID = IT->getDecl();
+      }
+    }
+    if (!lhsQI && !lhsQID && !lhsID)
+      return false;
+    
+    ObjCQualifiedIdType::qual_iterator LHSProtoI, LHSProtoE;
+    if (lhsQI) {
+      LHSProtoI = lhsQI->qual_begin();
+      LHSProtoE = lhsQI->qual_end();
+    } else if (lhsQID) {
+      LHSProtoI = lhsQID->qual_begin();
+      LHSProtoE = lhsQID->qual_end();
+    }
+    
+    bool match = false;
+    // for static type vs. qualified 'id' type, check that class implements
+    // one of 'id's protocols.
+    if (lhsID) {
+      for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
+        ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
+        if (ClassImplementsProtocol(rhsProto, lhsID, compare)) {
+          match = true;
+          break;
+        }
+      }
+    } else {
+      for (; LHSProtoI != LHSProtoE; ++LHSProtoI) {
+        match = false;
+        ObjCProtocolDecl *lhsProto = *LHSProtoI;
+        for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) {
+          ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j);
+          if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
+            compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) {
+            match = true;
+            break;
+          }
+        }
+      }
+    }
+    if (!match)
+      return false;
+  }
+  return true;  
+}
+