From c4e405996217f4be20f73186da53b23b5c4783dc Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 7 Apr 2008 04:07:56 +0000 Subject: [PATCH] Simplify some objc compatibility testing, make interfaceTypesAreCompatible 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 | 2 +- include/clang/AST/ASTContext.h | 3 - lib/AST/ASTContext.cpp | 106 +++++++++++++++----------------- 3 files changed, 50 insertions(+), 61 deletions(-) diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj index cb349bec9b..1001205307 100644 --- a/clang.xcodeproj/project.pbxproj +++ b/clang.xcodeproj/project.pbxproj @@ -739,8 +739,8 @@ 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 */, diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 1829c76159..2accd9bf4b 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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 diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 36c0a4dc6f..a0bbac7485 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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(lhs.getTypePtr()); - ObjCInterfaceType *rhsIT = cast(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(lhs.getCanonicalType().getTypePtr()); - assert(lhsQI && "QualifiedInterfaceTypesAreCompatible - bad lhs type"); - ObjCQualifiedInterfaceType *rhsQI = - dyn_cast(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(lcanon)) - lcanon = RT->getPointeeType(); - if (ReferenceType *RT = dyn_cast(rcanon)) - rcanon = RT->getPointeeType(); + if (ReferenceType *RT = dyn_cast(LHS)) + LHS = RT->getPointeeType(); + if (ReferenceType *RT = dyn_cast(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(lcanon)->getDecl(); - return EDecl->getIntegerType() == rcanon; + if (LHS->isEnumeralType() && RHS->isIntegralType()) { + EnumDecl* EDecl = cast(LHS)->getDecl(); + return EDecl->getIntegerType() == RHS; } - if (rcanon->isEnumeralType() && lcanon->isIntegralType()) { - EnumDecl* EDecl = cast(rcanon)->getDecl(); - return EDecl->getIntegerType() == lcanon; + if (RHS->isEnumeralType() && LHS->isIntegralType()) { + EnumDecl* EDecl = cast(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(LHS)->getDecl(), + cast(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"); } -- 2.40.0