diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 2637b68097c8..67fcff0db49f 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -758,6 +758,9 @@ public: assert(SelStructType && "isObjCSelType used before 'SEL' type is built"); return T->getAsStructureType() == SelStructType; } + bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS); + bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, + bool ForCompare); // Check the safety of assignment from LHS to RHS bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4490e9a3a9c0..727dc4ee3d6f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3023,43 +3023,219 @@ static bool areCompatVectorTypes(const VectorType *LHS, LHS->getNumElements() == RHS->getNumElements(); } +//===----------------------------------------------------------------------===// +// 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; + for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), + E = rProto->protocol_end(); PI != E; ++PI) + if (ProtocolCompatibleWithProtocol(lProto, *PI)) + 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, + bool RHSIsQualifiedID = false) { + + // 1st, look up the class. + const ObjCList &Protocols = + IDecl->getReferencedProtocols(); + + for (ObjCList::iterator PI = Protocols.begin(), + E = Protocols.end(); PI != E; ++PI) { + if (ProtocolCompatibleWithProtocol(lProto, *PI)) + return true; + // This is dubious and is added to be compatible with gcc. In gcc, it is + // also allowed assigning a protocol-qualified 'id' type to a LHS object + // when protocol in qualified LHS is in list of protocols in the rhs 'id' + // object. This IMO, should be a bug. + // FIXME: Treat this as an extension, and flag this as an error when GCC + // extensions are not enabled. + if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto)) + return true; + } + + // 2nd, look up the category. + if (lookupCategory) + for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; + CDecl = CDecl->getNextClassCategory()) { + for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), + E = CDecl->protocol_end(); PI != E; ++PI) + if (ProtocolCompatibleWithProtocol(lProto, *PI)) + return true; + } + + // 3rd, look up the super class(s) + if (IDecl->getSuperClass()) + return + ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, + RHSIsQualifiedID); + + return false; +} + +/// QualifiedIdConformsQualifiedId - compare id with id +/// return true if lhs's protocols conform to rhs's protocol; false +/// otherwise. +bool ASTContext::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) { + if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType()) + return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false); + return false; +} + +/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an +/// ObjCQualifiedIDType. +bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, + bool compare) { + // Allow id and an 'id' or void* type in all cases. + if (lhs->isVoidPointerType() || + lhs->isObjCIdType() || lhs->isObjCClassType()) + return true; + else if (rhs->isVoidPointerType() || + rhs->isObjCIdType() || rhs->isObjCClassType()) + return true; + + if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) { + const ObjCObjectPointerType *rhsOPT = rhs->getAsObjCObjectPointerType(); + + if (!rhsOPT) return false; + + if (rhsOPT->qual_empty()) { + // If the RHS is a unqualified interface pointer "NSString*", + // make sure we check the class hierarchy. + if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { + for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), + E = lhsQID->qual_end(); I != E; ++I) { + // when comparing an id

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 (!ClassImplementsProtocol(*I, rhsID, true)) + return false; + } + } + // If there are no qualifiers and no interface, we have an 'id'. + return true; + } + // Both the right and left sides have qualifiers. + for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), + E = lhsQID->qual_end(); I != E; ++I) { + ObjCProtocolDecl *lhsProto = *I; + bool match = false; + + // when comparing an id

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. + for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(), + E = rhsOPT->qual_end(); J != E; ++J) { + ObjCProtocolDecl *rhsProto = *J; + if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || + (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { + match = true; + break; + } + } + // If the RHS is a qualified interface pointer "NSString

*", + // make sure we check the class hierarchy. + if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { + for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), + E = lhsQID->qual_end(); I != E; ++I) { + // when comparing an id

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 (ClassImplementsProtocol(*I, rhsID, true)) { + match = true; + break; + } + } + } + if (!match) + return false; + } + + return true; + } + + const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType(); + assert(rhsQID && "One of the LHS/RHS should be id"); + + if (const ObjCObjectPointerType *lhsOPT = + lhs->getAsObjCInterfacePointerType()) { + if (lhsOPT->qual_empty()) { + bool match = false; + if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) { + for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(), + E = rhsQID->qual_end(); I != E; ++I) { + // when comparing an id

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 (ClassImplementsProtocol(*I, lhsID, true)) { + match = true; + break; + } + } + if (!match) + return false; + } + return true; + } + // Both the right and left sides have qualifiers. + for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(), + E = lhsOPT->qual_end(); I != E; ++I) { + ObjCProtocolDecl *lhsProto = *I; + bool match = false; + + // when comparing an id

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. + for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), + E = rhsQID->qual_end(); J != E; ++J) { + ObjCProtocolDecl *rhsProto = *J; + if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || + (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { + match = true; + break; + } + } + if (!match) + return false; + } + return true; + } + return false; +} + /// canAssignObjCInterfaces - Return true if the two interface types are /// 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 type represents the built-in 'id' or 'Class' types, return true. if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType()) return true; + if (LHSOPT->isObjCQualifiedIdType() || RHSOPT->isObjCQualifiedIdType()) + return ObjCQualifiedIdTypesAreCompatible(QualType(LHSOPT,0), + QualType(RHSOPT,0), + false); + const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType(); const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType(); - if (!LHS || !RHS) { - // We have qualified builtin types. - // Both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = LHSOPT->qual_begin(), - E = LHSOPT->qual_end(); I != E; ++I) { - bool RHSImplementsProtocol = false; - - // when comparing an id

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. - for (ObjCObjectPointerType::qual_iterator J = RHSOPT->qual_begin(), - E = RHSOPT->qual_end(); J != E; ++J) { - if ((*J)->lookupProtocolNamed((*I)->getIdentifier())) { - RHSImplementsProtocol = true; - break; - } - } - if (!RHSImplementsProtocol) - return false; - } - // The RHS implements all protocols listed on the LHS. - return true; - } - return canAssignObjCInterfaces(LHS, RHS); + if (LHS && RHS) // We have 2 user-defined types. + return canAssignObjCInterfaces(LHS, RHS); + + return false; } bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, @@ -3087,7 +3263,7 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS, // If the RHS doesn't implement the protocol on the left, the types // are incompatible. for (ObjCInterfaceType::qual_iterator RHSPI = RHS->qual_begin(), - RHSPE = RHS->qual_end(); + RHSPE = RHS->qual_end(); RHSPI != RHSPE; RHSPI++) { if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) { RHSImplementsProtocol = true; @@ -3441,10 +3617,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { return QualType(); } case Type::ObjCObjectPointer: { - // FIXME: Incorporate tests from Sema::ObjCQualifiedIdTypesAreCompatible(). - if (LHS->isObjCQualifiedIdType() && RHS->isObjCQualifiedIdType()) - return QualType(); - if (canAssignObjCInterfaces(LHS->getAsObjCObjectPointerType(), RHS->getAsObjCObjectPointerType())) return LHS; diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3bb763a13f8d..9f3eff9f1dbf 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1201,7 +1201,6 @@ public: bool &IncompleteImpl); void WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethod, ObjCMethodDecl *IntfMethod); - bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS); NamespaceDecl *GetStdNamespace(); @@ -3197,9 +3196,6 @@ public: unsigned NewWidth, bool NewSign, SourceLocation Loc, unsigned DiagID); - bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, - bool ForCompare); - /// Checks that the Objective-C declaration is declared in the global scope. /// Emits an error and marks the declaration as invalid if it's not declared /// in the global scope. diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 19cbf091b5f8..8bd2f530e406 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -369,7 +369,7 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, if (!Context.typesAreCompatible(LHSType, RHSType)) { // FIXME: Incorporate this test with typesAreCompatible. if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType()) - if (ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false)) + if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false)) return; Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) << Property->getType() << SuperProperty->getType() << inheritedName; @@ -804,8 +804,8 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, ObjCMethodDecl *IntfMethodDecl) { if (!Context.typesAreCompatible(IntfMethodDecl->getResultType(), ImpMethodDecl->getResultType()) && - !QualifiedIdConformsQualifiedId(IntfMethodDecl->getResultType(), - ImpMethodDecl->getResultType())) { + !Context.QualifiedIdConformsQualifiedId(IntfMethodDecl->getResultType(), + ImpMethodDecl->getResultType())) { Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_ret_types) << ImpMethodDecl->getDeclName() << IntfMethodDecl->getResultType() << ImpMethodDecl->getResultType(); @@ -816,7 +816,8 @@ void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, IF = IntfMethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); IM != EM; ++IM, ++IF) { if (Context.typesAreCompatible((*IF)->getType(), (*IM)->getType()) || - QualifiedIdConformsQualifiedId((*IF)->getType(), (*IM)->getType())) + Context.QualifiedIdConformsQualifiedId((*IF)->getType(), + (*IM)->getType())) continue; Diag((*IM)->getLocation(), diag::warn_conflicting_param_types) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5d4fbd8080e5..bfde991555a2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3171,7 +3171,7 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, compositeType = RHSTy; } else if ((LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) && - ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { + Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { // Need to handle "id" explicitly. // GCC allows qualified id and any Objective-C type to devolve to // id. Currently localizing to here until clear this should be @@ -3436,17 +3436,6 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return Compatible; return Incompatible; } - // FIXME: Look into removing. With ObjCObjectPointerType, I don't see a need. - if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) { - if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false)) - return Compatible; - // Relax integer conversions like we do for pointers below. - if (rhsType->isIntegerType()) - return IntToPointer; - if (lhsType->isIntegerType()) - return PointerToInt; - return IncompatibleObjCQualifiedId; - } // Allow scalar to ExtVector assignments, and assignments of an ExtVector type // to the same ExtVector type. if (lhsType->isExtVectorType()) { @@ -3528,6 +3517,8 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return Compatible; if (Context.typesAreCompatible(lhsType, rhsType)) return Compatible; + if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) + return IncompatibleObjCQualifiedId; return IncompatiblePointer; } if (const PointerType *RHSPT = rhsType->getAsPointerType()) { diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 2d144100e5d0..47ce949d020b 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -651,196 +651,3 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, 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; - for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), - E = rProto->protocol_end(); PI != E; ++PI) - if (ProtocolCompatibleWithProtocol(lProto, *PI)) - 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, - bool RHSIsQualifiedID = false) { - - // 1st, look up the class. - const ObjCList &Protocols = - IDecl->getReferencedProtocols(); - - for (ObjCList::iterator PI = Protocols.begin(), - E = Protocols.end(); PI != E; ++PI) { - if (ProtocolCompatibleWithProtocol(lProto, *PI)) - return true; - // This is dubious and is added to be compatible with gcc. In gcc, it is - // also allowed assigning a protocol-qualified 'id' type to a LHS object - // when protocol in qualified LHS is in list of protocols in the rhs 'id' - // object. This IMO, should be a bug. - // FIXME: Treat this as an extension, and flag this as an error when GCC - // extensions are not enabled. - if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto)) - return true; - } - - // 2nd, look up the category. - if (lookupCategory) - for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) { - for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), - E = CDecl->protocol_end(); PI != E; ++PI) - if (ProtocolCompatibleWithProtocol(lProto, *PI)) - return true; - } - - // 3rd, look up the super class(s) - if (IDecl->getSuperClass()) - return - ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, - RHSIsQualifiedID); - - return false; -} - -/// QualifiedIdConformsQualifiedId - compare id with id -/// return true if lhs's protocols conform to rhs's protocol; false -/// otherwise. -bool Sema::QualifiedIdConformsQualifiedId(QualType lhs, QualType rhs) { - if (lhs->isObjCQualifiedIdType() && rhs->isObjCQualifiedIdType()) - return ObjCQualifiedIdTypesAreCompatible(lhs, rhs, false); - return false; -} - -/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an -/// ObjCQualifiedIDType. -/// FIXME: Move to ASTContext::typesAreCompatible() and friends. -bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, - bool compare) { - // Allow id and an 'id' or void* type in all cases. - if (lhs->isVoidPointerType() || - lhs->isObjCIdType() || lhs->isObjCClassType()) - return true; - else if (rhs->isVoidPointerType() || - rhs->isObjCIdType() || rhs->isObjCClassType()) - return true; - - if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) { - const ObjCObjectPointerType *rhsOPT = rhs->getAsObjCObjectPointerType(); - - if (!rhsOPT) return false; - - if (rhsOPT->qual_empty()) { - // If the RHS is a unqualified interface pointer "NSString*", - // make sure we check the class hierarchy. - if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { - // when comparing an id

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 (!ClassImplementsProtocol(*I, rhsID, true)) - return false; - } - } - // If there are no qualifiers and no interface, we have an 'id'. - return true; - } - // Both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { - ObjCProtocolDecl *lhsProto = *I; - bool match = false; - - // when comparing an id

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. - for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(), - E = rhsOPT->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; - if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || - (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { - match = true; - break; - } - } - // If the RHS is a qualified interface pointer "NSString

*", - // make sure we check the class hierarchy. - if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { - // when comparing an id

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 (ClassImplementsProtocol(*I, rhsID, true)) { - match = true; - break; - } - } - } - if (!match) - return false; - } - - return true; - } - - const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType(); - assert(rhsQID && "One of the LHS/RHS should be id"); - - if (const ObjCObjectPointerType *lhsOPT = - lhs->getAsObjCInterfacePointerType()) { - if (lhsOPT->qual_empty()) { - bool match = false; - if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(), - E = rhsQID->qual_end(); I != E; ++I) { - // when comparing an id

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 (ClassImplementsProtocol(*I, lhsID, true)) { - match = true; - break; - } - } - if (!match) - return false; - } - return true; - } - // Both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(), - E = lhsOPT->qual_end(); I != E; ++I) { - ObjCProtocolDecl *lhsProto = *I; - bool match = false; - - // when comparing an id

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. - for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), - E = rhsQID->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; - if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || - (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { - match = true; - break; - } - } - if (!match) - return false; - } - return true; - } - return false; -} - diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 503f226fd66c..dc5f3e8e734c 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1020,7 +1020,8 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // Conversions with Objective-C's id<...>. if ((FromObjCPtr->isObjCQualifiedIdType() || ToObjCPtr->isObjCQualifiedIdType()) && - ObjCQualifiedIdTypesAreCompatible(ToType, FromType, /*compare=*/false)) { + Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType, + /*compare=*/false)) { ConvertedType = ToType; return true; } diff --git a/clang/test/SemaObjC/comptypes-1.m b/clang/test/SemaObjC/comptypes-1.m index 8717bd09eb84..df0785bf89e1 100644 --- a/clang/test/SemaObjC/comptypes-1.m +++ b/clang/test/SemaObjC/comptypes-1.m @@ -66,9 +66,7 @@ int main() /* Any comparison between 'MyClass *' and anything which is not an 'id' must generate a warning. */ - /* FIXME: GCC considers this a warning ("comparison of distinct pointer types"). */ - /* There is a corresponding FIXME in ASTContext::mergeTypes() */ - if (obj_p == obj_c) foo() ; + if (obj_p == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('id' and 'MyClass *')}} if (obj_c == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'MyOtherClass *')}} if (obj_cp == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'MyClass *')}} diff --git a/clang/test/SemaObjC/comptypes-7.m b/clang/test/SemaObjC/comptypes-7.m index faca6937cb74..881fd2b5553b 100644 --- a/clang/test/SemaObjC/comptypes-7.m +++ b/clang/test/SemaObjC/comptypes-7.m @@ -28,7 +28,7 @@ int main() obj = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id'}} obj_p = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'id'}} - obj_p = j; // expected-warning {{incompatible type assigning 'int *', expected 'id'}} + obj_p = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id'}} obj_c = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'MyClass *'}} obj_c = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'MyClass *'}} @@ -42,7 +42,7 @@ int main() i = obj_C; // expected-warning {{incompatible pointer to integer conversion assigning 'Class', expected 'int'}} j = obj; // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}} - j = obj_p; // expected-warning {{incompatible type assigning 'id', expected 'int *'}} + j = obj_p; // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}} j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'int *'}} j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'int *'}} diff --git a/clang/test/SemaObjC/conditional-expr.m b/clang/test/SemaObjC/conditional-expr.m index 8ae13382772c..2043503ddf7b 100644 --- a/clang/test/SemaObjC/conditional-expr.m +++ b/clang/test/SemaObjC/conditional-expr.m @@ -27,9 +27,8 @@ @implementation DTFilterOutputStream2 // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'nextOutputStream' not found}} - (id)initWithNextOutputStream:(id ) outputStream { id nextOutputStream = [self nextOutputStream]; - // GCC warns about both of these. self = nextOutputStream; // expected-warning {{incompatible type assigning 'id', expected 'DTFilterOutputStream2 *'}} - return nextOutputStream ? nextOutputStream : self; + return nextOutputStream ? nextOutputStream : self; // expected-warning {{incompatible operand types ('id' and 'DTFilterOutputStream2 *')}} } @end @@ -37,9 +36,8 @@ @implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}} - (id)initWithNextOutputStream:(id ) outputStream { id nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}} - // GCC warns about both of these as well (no errors). self = nextOutputStream; // expected-warning {{incompatible type assigning 'id', expected 'DTFilterOutputStream3 *'}} - return nextOutputStream ? nextOutputStream : self; + return nextOutputStream ? nextOutputStream : self; // expected-warning {{incompatible operand types ('id' and 'DTFilterOutputStream3 *')}} } @end @@ -86,7 +84,7 @@ void f4(int cond, id x, B *y) { } void f5(int cond, id x, C *y) { - (cond ? x : y).intProp = 1; // expected-error {{property 'intProp' not found on object of type 'C *'}} + (cond ? x : y).intProp = 1; // expected-warning {{incompatible operand types ('id' and 'C *')}} expected-error {{property 'intProp' not found on object of type 'id'}} } void f6(int cond, C *x, D *y) {