diff options
43 files changed, 892 insertions, 755 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index fbd56023d6..b13028d8f7 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -107,7 +107,6 @@ class ASTContext { /// ObjCIdType - a pseudo built-in typedef type (set by Sema). QualType ObjCIdType; - const RecordType *IdStructType; /// ObjCSelType - another pseudo built-in typedef type (set by Sema). QualType ObjCSelType; @@ -119,7 +118,6 @@ class ASTContext { /// ObjCClassType - another pseudo built-in typedef type (set by Sema). QualType ObjCClassType; - const RecordType *ClassStructType; QualType ObjCConstantStringType; RecordDecl *CFConstantStringTypeDecl; @@ -375,7 +373,7 @@ public: /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for the /// given interface decl and the conforming protocol list. - QualType getObjCObjectPointerType(ObjCInterfaceDecl *Decl, + QualType getObjCObjectPointerType(QualType OIT = QualType(), ObjCProtocolDecl **ProtocolList = 0, unsigned NumProtocols = 0); @@ -770,26 +768,18 @@ public: bool isObjCIdType(QualType T) const { return T == ObjCIdType; } - bool isObjCIdStructType(QualType T) const { - if (!IdStructType) // ObjC isn't enabled - return false; - return T->getAsStructureType() == IdStructType; - } bool isObjCClassType(QualType T) const { return T == ObjCClassType; } - bool isObjCClassStructType(QualType T) const { - if (!ClassStructType) // ObjC isn't enabled - return false; - return T->getAsStructureType() == ClassStructType; - } bool isObjCSelType(QualType T) const { assert(SelStructType && "isObjCSelType used before 'SEL' type is built"); return T->getAsStructureType() == SelStructType; } // Check the safety of assignment from LHS to RHS - bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, + bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT); + bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS, const ObjCInterfaceType *RHS); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 39eb1842b3..8de6a03c8f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -396,9 +396,13 @@ public: bool isVectorType() const; // GCC vector type. bool isExtVectorType() const; // Extended vector type. bool isObjCObjectPointerType() const; // Pointer to *any* ObjC object. + // FIXME: change this to 'raw' interface type, so we can used 'interface' type + // for the common case. bool isObjCInterfaceType() const; // NSString or NSString<foo> bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedIdType() const; // id<foo> + bool isObjCIdType() const; // id + bool isObjCClassType() const; // Class bool isTemplateTypeParmType() const; // C++ template type parameter bool isNullPtrType() const; // C++0x nullptr_t @@ -443,9 +447,12 @@ public: const ComplexType *getAsComplexIntegerType() const; // GCC complex int type. const ExtVectorType *getAsExtVectorType() const; // Extended vector type. const ObjCObjectPointerType *getAsObjCObjectPointerType() const; + // The following is a convenience method that returns an ObjCObjectPointerType + // for object declared using an interface. + const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; + const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; const ObjCInterfaceType *getAsObjCInterfaceType() const; const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const; - const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; const TemplateTypeParmType *getAsTemplateTypeParmType() const; const TemplateSpecializationType * @@ -460,6 +467,10 @@ public: /// This method should never be used when type qualifiers are meaningful. const Type *getArrayElementTypeNoTypeQual() const; + /// getPointeeType - If this is a pointer or ObjC object pointer, this + /// returns the respective pointee. + QualType getPointeeType() const; + /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar @@ -1809,53 +1820,6 @@ public: static bool classof(const TypenameType *T) { return true; } }; -/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>', -/// and 'Interface <p> *'. -/// -/// Duplicate protocols are removed and protocol list is canonicalized to be in -/// alphabetical order. -class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { - ObjCInterfaceDecl *Decl; - // List of protocols for this protocol conforming object type - // List is sorted on protocol name. No protocol is entered more than once. - llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols; - - ObjCObjectPointerType(ObjCInterfaceDecl *D, - ObjCProtocolDecl **Protos, unsigned NumP) : - Type(ObjCObjectPointer, QualType(), /*Dependent=*/false), - Decl(D), Protocols(Protos, Protos+NumP) { } - friend class ASTContext; // ASTContext creates these. - -public: - ObjCInterfaceDecl *getDecl() const { return Decl; } - - /// isObjCQualifiedIdType - true for "id <p>". - bool isObjCQualifiedIdType() const { return Decl == 0 && Protocols.size(); } - - /// qual_iterator and friends: this provides access to the (potentially empty) - /// list of protocols qualifying this interface. - typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator; - - qual_iterator qual_begin() const { return Protocols.begin(); } - qual_iterator qual_end() const { return Protocols.end(); } - bool qual_empty() const { return Protocols.size() == 0; } - - /// getNumProtocols - Return the number of qualifying protocols in this - /// interface type, or 0 if there are none. - unsigned getNumProtocols() const { return Protocols.size(); } - - void Profile(llvm::FoldingSetNodeID &ID); - static void Profile(llvm::FoldingSetNodeID &ID, - const ObjCInterfaceDecl *Decl, - ObjCProtocolDecl **protocols, unsigned NumProtocols); - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { - return T->getTypeClass() == ObjCObjectPointer; - } - static bool classof(const ObjCObjectPointerType *) { return true; } -}; - /// ObjCInterfaceType - Interfaces are the core concept in Objective-C for /// object oriented design. They basically correspond to C++ classes. There /// are two kinds of interface types, normal interfaces like "NSString" and @@ -1868,10 +1832,15 @@ protected: ObjCInterfaceType(TypeClass tc, ObjCInterfaceDecl *D) : Type(tc, QualType(), /*Dependent=*/false), Decl(D) { } friend class ASTContext; // ASTContext creates these. + + // FIXME: These can go away when we move ASTContext::canAssignObjCInterfaces + // to this class (as a static helper). + bool isObjCIdInterface() const; + bool isObjCClassInterface() const; public: ObjCInterfaceDecl *getDecl() const { return Decl; } - + /// qual_iterator and friends: this provides access to the (potentially empty) /// list of protocols qualifying this interface. If this is an instance of /// ObjCQualifiedInterfaceType it returns the list, otherwise it returns an @@ -1893,11 +1862,85 @@ public: static bool classof(const ObjCInterfaceType *) { return true; } }; +/// ObjCObjectPointerType - Used to represent 'id', 'Interface *', 'id <p>', +/// and 'Interface <p> *'. +/// +/// Duplicate protocols are removed and protocol list is canonicalized to be in +/// alphabetical order. +class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { + QualType PointeeType; // will always point to an interface type. + + // List of protocols for this protocol conforming object type + // List is sorted on protocol name. No protocol is entered more than once. + llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols; + + ObjCObjectPointerType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) : + Type(ObjCObjectPointer, QualType(), /*Dependent=*/false), + PointeeType(T), Protocols(Protos, Protos+NumP) { } + friend class ASTContext; // ASTContext creates these. + friend class ObjCInterfaceType; // To enable 'id' and 'Class' predicates. + + static ObjCInterfaceType *IdInterfaceT; + static ObjCInterfaceType *ClassInterfaceT; + static void setIdInterface(QualType T) { + IdInterfaceT = dyn_cast<ObjCInterfaceType>(T.getTypePtr()); + } + static void setClassInterface(QualType T) { + ClassInterfaceT = dyn_cast<ObjCInterfaceType>(T.getTypePtr()); + } + static ObjCInterfaceType *getIdInterface() { return IdInterfaceT; } + static ObjCInterfaceType *getClassInterface() { return ClassInterfaceT; } +public: + // Get the pointee type. Pointee is required to always be an interface type. + // Note: Pointee can be a TypedefType whose canonical type is an interface. + // Example: typedef NSObject T; T *var; + QualType getPointeeType() const { return PointeeType; } + + const ObjCInterfaceType *getInterfaceType() const { + return PointeeType->getAsObjCInterfaceType(); + } + ObjCInterfaceDecl *getInterfaceDecl() const { + return getInterfaceType()->getDecl(); + } + /// isObjCQualifiedIdType - true for "id <p>". + bool isObjCQualifiedIdType() const { + return getInterfaceType() == IdInterfaceT && Protocols.size(); + } + bool isObjCIdType() const { + return getInterfaceType() == IdInterfaceT && !Protocols.size(); + } + bool isObjCClassType() const { + return getInterfaceType() == ClassInterfaceT && !Protocols.size(); + } + /// qual_iterator and friends: this provides access to the (potentially empty) + /// list of protocols qualifying this interface. + typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator; + + qual_iterator qual_begin() const { return Protocols.begin(); } + qual_iterator qual_end() const { return Protocols.end(); } + bool qual_empty() const { return Protocols.size() == 0; } + + /// getNumProtocols - Return the number of qualifying protocols in this + /// interface type, or 0 if there are none. + unsigned getNumProtocols() const { return Protocols.size(); } + + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, QualType T, + ObjCProtocolDecl **protocols, unsigned NumProtocols); + virtual void getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const; + static bool classof(const Type *T) { + return T->getTypeClass() == ObjCObjectPointer; + } + static bool classof(const ObjCObjectPointerType *) { return true; } +}; + /// ObjCQualifiedInterfaceType - This class represents interface types /// conforming to a list of protocols, such as INTF<Proto1, Proto2, Proto1>. /// /// Duplicate protocols are removed and protocol list is canonicalized to be in /// alphabetical order. +/// FIXME: Remove this class (converting uses to ObjCObjectPointerType). class ObjCQualifiedInterfaceType : public ObjCInterfaceType, public llvm::FoldingSetNode { @@ -1983,7 +2026,7 @@ inline QualType::GCAttrTypes QualType::getObjCGCAttr() const { return AT->getElementType().getObjCGCAttr(); if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT)) return EXTQT->getObjCGCAttr(); - if (const PointerType *PT = CT->getAsPointerType()) + if (const ObjCObjectPointerType *PT = CT->getAsObjCObjectPointerType()) return PT->getPointeeType().getObjCGCAttr(); return GCNone; } @@ -2115,6 +2158,18 @@ inline bool Type::isObjCQualifiedIdType() const { } return false; } +inline bool Type::isObjCIdType() const { + if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) { + return OPT->isObjCIdType(); + } + return false; +} +inline bool Type::isObjCClassType() const { + if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) { + return OPT->isObjCClassType(); + } + return false; +} inline bool Type::isTemplateTypeParmType() const { return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType()); } @@ -2134,12 +2189,12 @@ inline bool Type::isOverloadableType() const { inline bool Type::hasPointerRepresentation() const { return (isPointerType() || isReferenceType() || isBlockPointerType() || - isObjCInterfaceType() || isObjCQualifiedIdType() || + isObjCInterfaceType() || isObjCObjectPointerType() || isObjCQualifiedInterfaceType() || isNullPtrType()); } inline bool Type::hasObjCPointerRepresentation() const { - return (isObjCInterfaceType() || isObjCQualifiedIdType() || + return (isObjCInterfaceType() || isObjCObjectPointerType() || isObjCQualifiedInterfaceType()); } diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 4bc5e27aac..dd7c93639f 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -196,7 +196,7 @@ public: } static inline bool IsLocType(QualType T) { - return T->isPointerType() || T->isObjCQualifiedIdType() + return T->isPointerType() || T->isObjCObjectPointerType() || T->isBlockPointerType(); } }; diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2bd1482adc..dbac120d26 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -42,8 +42,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, Idents(idents), Selectors(sels), BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { if (size_reserve > 0) Types.reserve(size_reserve); - InitBuiltinTypes(); TUDecl = TranslationUnitDecl::Create(*this); + InitBuiltinTypes(); } ASTContext::~ASTContext() { @@ -190,11 +190,10 @@ void ASTContext::InitBuiltinTypes() { LongDoubleComplexTy = getComplexType(LongDoubleTy); BuiltinVaListType = QualType(); + ObjCIdType = QualType(); - IdStructType = 0; ObjCClassType = QualType(); - ClassStructType = 0; - + ObjCConstantStringType = QualType(); // void * type @@ -1071,7 +1070,7 @@ QualType ASTContext::getObjCGCQualType(QualType T, if (T->isPointerType()) { QualType Pointee = T->getAsPointerType()->getPointeeType(); - if (Pointee->isPointerType()) { + if (Pointee->isPointerType() || Pointee->isObjCObjectPointerType()) { QualType ResultType = getObjCGCQualType(Pointee, GCAttr); return getPointerType(ResultType); } @@ -1847,15 +1846,18 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols, /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for /// the given interface decl and the conforming protocol list. -QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl, +QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, ObjCProtocolDecl **Protocols, unsigned NumProtocols) { + if (InterfaceT.isNull()) + InterfaceT = QualType(ObjCObjectPointerType::getIdInterface(), 0); + // Sort the protocol list alphabetically to canonicalize it. if (NumProtocols) SortAndUniqueProtocols(Protocols, NumProtocols); llvm::FoldingSetNodeID ID; - ObjCObjectPointerType::Profile(ID, Decl, Protocols, NumProtocols); + ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); void *InsertPos = 0; if (ObjCObjectPointerType *QT = @@ -1864,7 +1866,7 @@ QualType ASTContext::getObjCObjectPointerType(ObjCInterfaceDecl *Decl, // No Match; ObjCObjectPointerType *QType = - new (*this,8) ObjCObjectPointerType(Decl, Protocols, NumProtocols); + new (*this,8) ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols); Types.push_back(QType); ObjCObjectPointerTypes.InsertNode(QType, InsertPos); @@ -2745,25 +2747,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += 'j'; getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false, false); - } else if (T->isObjCQualifiedIdType()) { - getObjCEncodingForTypeImpl(getObjCIdType(), S, - ExpandPointedToStructures, - ExpandStructures, FD); - if (FD || EncodingProperty) { - // Note that we do extended encoding of protocol qualifer list - // Only when doing ivar or property encoding. - const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType(); - S += '"'; - for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(), - E = QIDT->qual_end(); I != E; ++I) { - S += '<'; - S += (*I)->getNameAsString(); - S += '>'; - } - S += '"'; - } - return; - } + } else if (const PointerType *PT = T->getAsPointerType()) { QualType PointeeTy = PT->getPointeeType(); bool isReadOnly = false; @@ -2797,42 +2781,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S.replace(S.end()-2, S.end(), replace); } } - if (isObjCIdStructType(PointeeTy)) { - S += '@'; - return; - } - else if (PointeeTy->isObjCInterfaceType()) { - if (!EncodingProperty && - isa<TypedefType>(PointeeTy.getTypePtr())) { - // Another historical/compatibility reason. - // We encode the underlying type which comes out as - // {...}; - S += '^'; - getObjCEncodingForTypeImpl(PointeeTy, S, - false, ExpandPointedToStructures, - NULL); - return; - } - S += '@'; - if (FD || EncodingProperty) { - const ObjCInterfaceType *OIT = - PointeeTy.getUnqualifiedType()->getAsObjCInterfaceType(); - ObjCInterfaceDecl *OI = OIT->getDecl(); - S += '"'; - S += OI->getNameAsCString(); - for (ObjCInterfaceType::qual_iterator I = OIT->qual_begin(), - E = OIT->qual_end(); I != E; ++I) { - S += '<'; - S += (*I)->getNameAsString(); - S += '>'; - } - S += '"'; - } - return; - } else if (isObjCClassStructType(PointeeTy)) { - S += '#'; - return; - } else if (isObjCSelType(PointeeTy)) { + if (isObjCSelType(PointeeTy)) { S += ':'; return; } @@ -2937,7 +2886,61 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } S += '}'; } - else + else if (const ObjCObjectPointerType *OPT = T->getAsObjCObjectPointerType()) { + if (OPT->isObjCIdType()) { + S += '@'; + return; + } else if (OPT->isObjCClassType()) { + S += '#'; + return; + } else if (OPT->isObjCQualifiedIdType()) { + getObjCEncodingForTypeImpl(getObjCIdType(), S, + ExpandPointedToStructures, + ExpandStructures, FD); + if (FD || EncodingProperty) { + // Note that we do extended encoding of protocol qualifer list + // Only when doing ivar or property encoding. + const ObjCObjectPointerType *QIDT = T->getAsObjCQualifiedIdType(); + S += '"'; + for (ObjCObjectPointerType::qual_iterator I = QIDT->qual_begin(), + E = QIDT->qual_end(); I != E; ++I) { + S += '<'; + S += (*I)->getNameAsString(); + S += '>'; + } + S += '"'; + } + return; + } else { + QualType PointeeTy = OPT->getPointeeType(); + if (!EncodingProperty && + isa<TypedefType>(PointeeTy.getTypePtr())) { + // Another historical/compatibility reason. + // We encode the underlying type which comes out as + // {...}; + S += '^'; + getObjCEncodingForTypeImpl(PointeeTy, S, + false, ExpandPointedToStructures, + NULL); + return; + } + S += '@'; + if (FD || EncodingProperty) { + const ObjCInterfaceType *OIT = OPT->getInterfaceType(); + ObjCInterfaceDecl *OI = OIT->getDecl(); + S += '"'; + S += OI->getNameAsCString(); + for (ObjCInterfaceType::qual_iterator I = OIT->qual_begin(), + E = OIT->qual_end(); I != E; ++I) { + S += '<'; + S += (*I)->getNameAsString(); + S += '>'; + } + S += '"'; + } + return; + } + } else assert(0 && "@encode for type not implemented!"); } @@ -2967,23 +2970,12 @@ void ASTContext::setBuiltinVaListType(QualType T) void ASTContext::setObjCIdType(QualType T) { ObjCIdType = T; - const TypedefType *TT = T->getAsTypedefType(); - if (!TT) - return; - - TypedefDecl *TD = TT->getDecl(); - - // typedef struct objc_object *id; - const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType(); - // User error - caller will issue diagnostics. - if (!ptr) - return; - const RecordType *rec = ptr->getPointeeType()->getAsStructureType(); - // User error - caller will issue diagnostics. - if (!rec) - return; - IdStructType = rec; + assert(TT && "missing 'id' typedef"); + const ObjCObjectPointerType *OPT = + TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType(); + assert(OPT && "missing 'id' type"); + ObjCObjectPointerType::setIdInterface(OPT->getPointeeType()); } void ASTContext::setObjCSelType(QualType T) @@ -3013,18 +3005,12 @@ void ASTContext::setObjCProtoType(QualType QT) void ASTContext::setObjCClassType(QualType T) { ObjCClassType = T; - const TypedefType *TT = T->getAsTypedefType(); - if (!TT) - return; - TypedefDecl *TD = TT->getDecl(); - - // typedef struct objc_class *Class; - const PointerType *ptr = TD->getUnderlyingType()->getAsPointerType(); - assert(ptr && "'Class' incorrectly typed"); - const RecordType *rec = ptr->getPointeeType()->getAsStructureType(); - assert(rec && "'Class' incorrectly typed"); - ClassStructType = rec; + assert(TT && "missing 'Class' typedef"); + const ObjCObjectPointerType *OPT = + TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType(); + assert(OPT && "missing 'Class' type"); + ObjCObjectPointerType::setClassInterface(OPT->getPointeeType()); } void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { @@ -3123,6 +3109,8 @@ bool ASTContext::isObjCNSObjectType(QualType Ty) const { /// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified /// ID type). bool ASTContext::isObjCObjectPointerType(QualType Ty) const { + if (Ty->isObjCObjectPointerType()) + return true; if (Ty->isObjCQualifiedIdType()) return true; @@ -3198,8 +3186,30 @@ static bool areCompatVectorTypes(const VectorType *LHS, /// compatible for assignment from RHS to LHS. This handles validation of any /// protocol qualifiers on the LHS or RHS. /// +/// FIXME: Move the following to ObjCObjectPointerType/ObjCInterfaceType. +bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, + const ObjCObjectPointerType *RHSOPT) { + // If either interface represents the built-in 'id' or 'Class' types, + // then return true (no need to call canAssignObjCInterfaces()). + if (LHSOPT->isObjCIdType() || RHSOPT->isObjCIdType() || + LHSOPT->isObjCClassType() || RHSOPT->isObjCClassType()) + return true; + + const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); + const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); + if (!LHS || !RHS) + return false; + return canAssignObjCInterfaces(LHS, RHS); +} + bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, const ObjCInterfaceType *RHS) { + // If either interface represents the built-in 'id' or 'Class' types, + // then return true. + if (LHS->isObjCIdInterface() || RHS->isObjCIdInterface() || + LHS->isObjCClassInterface() || RHS->isObjCClassInterface()) + return true; + // Verify that the base decls are compatible: the RHS must be a subclass of // the LHS. if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl())) @@ -3245,25 +3255,14 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) { // get the "pointed to" types - const PointerType *LHSPT = LHS->getAsPointerType(); - const PointerType *RHSPT = RHS->getAsPointerType(); + const ObjCObjectPointerType *LHSOPT = LHS->getAsObjCObjectPointerType(); + const ObjCObjectPointerType *RHSOPT = RHS->getAsObjCObjectPointerType(); - if (!LHSPT || !RHSPT) - return false; - - QualType lhptee = LHSPT->getPointeeType(); - QualType rhptee = RHSPT->getPointeeType(); - const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType(); - const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType(); - // ID acts sort of like void* for ObjC interfaces - if (LHSIface && isObjCIdStructType(rhptee)) - return true; - if (RHSIface && isObjCIdStructType(lhptee)) - return true; - if (!LHSIface || !RHSIface) + if (!LHSOPT || !RHSOPT) return false; - return canAssignObjCInterfaces(LHSIface, RHSIface) || - canAssignObjCInterfaces(RHSIface, LHSIface); + + return canAssignObjCInterfaces(LHSOPT, RHSOPT) || + canAssignObjCInterfaces(RHSOPT, LHSOPT); } /// typesAreCompatible - C99 6.7.3p9: For two qualified types to be compatible, @@ -3406,8 +3405,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { // issue error. if ((GCAttr == QualType::Weak && GCLHSAttr != GCAttr) || (GCAttr == QualType::Strong && GCLHSAttr != GCAttr && - LHSCan->isPointerType() && !isObjCObjectPointerType(LHSCan) && - !isObjCIdStructType(LHSCan->getAsPointerType()->getPointeeType()))) + !LHSCan->isObjCObjectPointerType())) return QualType(); RHS = QualType(cast<ExtQualType>(RHS.getDesugaredType())->getBaseType(), @@ -3432,8 +3430,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { // issue error. if ((GCAttr == QualType::Weak & |