]> granicus.if.org Git - clang/commitdiff
Simplify some objc compatibility testing, make interfaceTypesAreCompatible
authorChris Lattner <sabre@nondot.org>
Mon, 7 Apr 2008 04:07:56 +0000 (04:07 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 7 Apr 2008 04:07:56 +0000 (04:07 +0000)
a static function named isCompatibleInterfaceAssign.

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

clang.xcodeproj/project.pbxproj
include/clang/AST/ASTContext.h
lib/AST/ASTContext.cpp

index cb349bec9bfdcf6621f92d5202385551d018a777..10012053070eb19bec40a56fac856c6811a51def 100644 (file)
                                DED676F90B6C797B00AAD4A3 /* Builtins.h */,
                                DEC63B1B0C7B940600DBF169 /* CFG.h */,
                                DEC8D9900A9433CD00353FCA /* Decl.h */,
-                               84AF36A00CB17A3B00C820A5 /* DeclObjC.h */,
                                035611470DA6A45C00D2EF2A /* DeclBase.h */,
+                               84AF36A00CB17A3B00C820A5 /* DeclObjC.h */,
                                DE0FCA620A95859D00248FD5 /* Expr.h */,
                                1A30A9E80B93A4C800201A91 /* ExprCXX.h */,
                                1A68BC110D0CADDD001A28C8 /* PPCBuiltins.def */,
index 1829c7615984052639c113c07ec7ca4596ae6073..2accd9bf4b60a9ce89b94452bb4dcdde9bf0689c 100644 (file)
@@ -366,9 +366,6 @@ private:
   
   void InitBuiltinTypes();
   void InitBuiltinType(QualType &R, BuiltinType::Kind K);
-  
-  /// helper function for Objective-C specific type checking.
-  bool interfaceTypesAreCompatible(QualType, QualType);
 };
   
 }  // end namespace clang
index 36c0a4dc6f82b724fb03f315800db4a94bf78002..a0bbac7485551e4d3840b3148b8fce767622e9e4 100644 (file)
@@ -1443,45 +1443,36 @@ bool ASTContext::objcTypesAreCompatible(QualType LHS, QualType RHS) {
   return false;
 }
 
-/// Check that 'lhs' and 'rhs' are compatible interface types. Both types
-/// must be canonical types.
-bool ASTContext::interfaceTypesAreCompatible(QualType lhs, QualType rhs) {
-  assert (lhs->isCanonical() &&
-          "interfaceTypesAreCompatible strip typedefs of lhs");
-  assert (rhs->isCanonical() &&
-          "interfaceTypesAreCompatible strip typedefs of rhs");
-  if (lhs == rhs)
-    return true;
-  ObjCInterfaceType *lhsIT = cast<ObjCInterfaceType>(lhs.getTypePtr());
-  ObjCInterfaceType *rhsIT = cast<ObjCInterfaceType>(rhs.getTypePtr());
-  ObjCInterfaceDecl *rhsIDecl = rhsIT->getDecl();
-  ObjCInterfaceDecl *lhsIDecl = lhsIT->getDecl();
-  // rhs is derived from lhs it is OK; else it is not OK.
-  while (rhsIDecl != NULL) {
-    if (rhsIDecl == lhsIDecl)
+/// isCompatibleInterfaceAssign - Return true if it is ok to assign a
+/// pointer from the RHS interface to the LHS interface.  This is true if the
+/// RHS is exactly LHS or if it is a subclass of LHS.
+static bool isCompatibleInterfaceAssign(ObjCInterfaceDecl *LHS,
+                                        ObjCInterfaceDecl *RHS) {
+  // If RHS is derived from LHS it is OK; else it is not OK.
+  while (RHS != NULL) {
+    if (RHS == LHS)
       return true;
-    rhsIDecl = rhsIDecl->getSuperClass();
+    RHS = RHS->getSuperClass();
   }
   return false;
 }
 
 bool ASTContext::QualifiedInterfaceTypesAreCompatible(QualType lhs, 
                                                       QualType rhs) {
-  ObjCQualifiedInterfaceType *lhsQI = 
-    dyn_cast<ObjCQualifiedInterfaceType>(lhs.getCanonicalType().getTypePtr());
-  assert(lhsQI && "QualifiedInterfaceTypesAreCompatible - bad lhs type");
-  ObjCQualifiedInterfaceType *rhsQI = 
-    dyn_cast<ObjCQualifiedInterfaceType>(rhs.getCanonicalType().getTypePtr());
-  assert(rhsQI && "QualifiedInterfaceTypesAreCompatible - bad rhs type");
-  if (!interfaceTypesAreCompatible(
-         getObjCInterfaceType(lhsQI->getDecl()).getCanonicalType(), 
-         getObjCInterfaceType(rhsQI->getDecl()).getCanonicalType()))
+  const ObjCQualifiedInterfaceType *lhsQI =
+    lhs->getAsObjCQualifiedInterfaceType();
+  const ObjCQualifiedInterfaceType *rhsQI = 
+    rhs->getAsObjCQualifiedInterfaceType();
+  assert(lhsQI && rhsQI && "QualifiedInterfaceTypesAreCompatible - bad type");
+  
+  if (!isCompatibleInterfaceAssign(lhsQI->getDecl(), rhsQI->getDecl()))
     return false;
-  /* All protocols in lhs must have a presense in rhs. */
-  for (unsigned i =0; i < lhsQI->getNumProtocols(); i++) {
+  
+  // All protocols in lhs must have a presence in rhs.
+  for (unsigned i = 0; i != lhsQI->getNumProtocols(); ++i) {
     bool match = false;
     ObjCProtocolDecl *lhsProto = lhsQI->getProtocols(i);
-    for (unsigned j = 0; j < rhsQI->getNumProtocols(); j++) {
+    for (unsigned j = 0; j != rhsQI->getNumProtocols(); ++j) {
       ObjCProtocolDecl *rhsProto = rhsQI->getProtocols(j);
       if (lhsProto == rhsProto) {
         match = true;
@@ -1794,29 +1785,29 @@ bool ASTContext::arrayTypesAreCompatible(QualType lhs, QualType rhs) {
 /// both shall have the identically qualified version of a compatible type.
 /// C99 6.2.7p1: Two types have compatible types if their types are the 
 /// same. See 6.7.[2,3,5] for additional rules.
-bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) {
-  QualType lcanon = lhs.getCanonicalType();
-  QualType rcanon = rhs.getCanonicalType();
+bool ASTContext::typesAreCompatible(QualType LHS_NC, QualType RHS_NC) {
+  QualType LHS = LHS_NC.getCanonicalType();
+  QualType RHS = RHS_NC.getCanonicalType();
   
   // If two types are identical, they are are compatible
-  if (lcanon == rcanon)
+  if (LHS == RHS)
     return true;
   
-  if (lcanon.getCVRQualifiers() != rcanon.getCVRQualifiers() ||
-      lcanon.getAddressSpace() != rcanon.getAddressSpace())
+  if (LHS.getCVRQualifiers() != RHS.getCVRQualifiers() ||
+      LHS.getAddressSpace() != RHS.getAddressSpace())
     return false;
 
   // C++ [expr]: If an expression initially has the type "reference to T", the
   // type is adjusted to "T" prior to any further analysis, the expression
   // designates the object or function denoted by the reference, and the
   // expression is an lvalue.
-  if (ReferenceType *RT = dyn_cast<ReferenceType>(lcanon))
-    lcanon = RT->getPointeeType();
-  if (ReferenceType *RT = dyn_cast<ReferenceType>(rcanon))
-    rcanon = RT->getPointeeType();
+  if (ReferenceType *RT = dyn_cast<ReferenceType>(LHS))
+    LHS = RT->getPointeeType();
+  if (ReferenceType *RT = dyn_cast<ReferenceType>(RHS))
+    RHS = RT->getPointeeType();
   
-  Type::TypeClass LHSClass = lcanon->getTypeClass();
-  Type::TypeClass RHSClass = rcanon->getTypeClass();
+  Type::TypeClass LHSClass = LHS->getTypeClass();
+  Type::TypeClass RHSClass = RHS->getTypeClass();
   
   // We want to consider the two function types to be the same for these
   // comparisons, just force one to the other.
@@ -1834,18 +1825,18 @@ bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) {
     // For Objective-C, it is possible for two types to be compatible
     // when their classes don't match (when dealing with "id"). If either type
     // is an interface, we defer to objcTypesAreCompatible(). 
-    if (lcanon->isObjCInterfaceType() || rcanon->isObjCInterfaceType())
-      return objcTypesAreCompatible(lcanon, rcanon);
+    if (LHS->isObjCInterfaceType() || RHS->isObjCInterfaceType())
+      return objcTypesAreCompatible(LHS, RHS);
       
     // C99 6.7.2.2p4: Each enumerated type shall be compatible with char,
     // a signed integer type, or an unsigned integer type. 
-    if (lcanon->isEnumeralType() && rcanon->isIntegralType()) {
-      EnumDecl* EDecl = cast<EnumType>(lcanon)->getDecl();
-      return EDecl->getIntegerType() == rcanon;
+    if (LHS->isEnumeralType() && RHS->isIntegralType()) {
+      EnumDecl* EDecl = cast<EnumType>(LHS)->getDecl();
+      return EDecl->getIntegerType() == RHS;
     }
-    if (rcanon->isEnumeralType() && lcanon->isIntegralType()) {
-      EnumDecl* EDecl = cast<EnumType>(rcanon)->getDecl();
-      return EDecl->getIntegerType() == lcanon;
+    if (RHS->isEnumeralType() && LHS->isIntegralType()) {
+      EnumDecl* EDecl = cast<EnumType>(RHS)->getDecl();
+      return EDecl->getIntegerType() == LHS;
     }
 
     return false;
@@ -1854,24 +1845,25 @@ bool ASTContext::typesAreCompatible(QualType lhs, QualType rhs) {
   switch (LHSClass) {
   case Type::FunctionProto: assert(0 && "Canonicalized away above");
   case Type::Pointer:
-    return pointerTypesAreCompatible(lcanon, rcanon);
+    return pointerTypesAreCompatible(LHS, RHS);
   case Type::ConstantArray:
   case Type::VariableArray:
   case Type::IncompleteArray:
-    return arrayTypesAreCompatible(lcanon, rcanon);
+    return arrayTypesAreCompatible(LHS, RHS);
   case Type::FunctionNoProto:
-    return functionTypesAreCompatible(lcanon, rcanon);
+    return functionTypesAreCompatible(LHS, RHS);
   case Type::Tagged: // handle structures, unions
-    return tagTypesAreCompatible(lcanon, rcanon);
+    return tagTypesAreCompatible(LHS, RHS);
   case Type::Builtin:
-    return builtinTypesAreCompatible(lcanon, rcanon); 
+    return builtinTypesAreCompatible(LHS, RHS); 
   case Type::ObjCInterface:
-    return interfaceTypesAreCompatible(lcanon, rcanon); 
+    return isCompatibleInterfaceAssign(cast<ObjCInterfaceType>(LHS)->getDecl(),
+                                       cast<ObjCInterfaceType>(RHS)->getDecl());
   case Type::Vector:
   case Type::OCUVector:
-    return vectorTypesAreCompatible(lcanon, rcanon);
+    return vectorTypesAreCompatible(LHS, RHS);
   case Type::ObjCQualifiedInterface:
-    return QualifiedInterfaceTypesAreCompatible(lcanon, rcanon);
+    return QualifiedInterfaceTypesAreCompatible(LHS, RHS);
   default:
     assert(0 && "unexpected type");
   }