SemaExprObjC.cpp revision 488a9f6f9385522cce9cbcbca4e7d2a7a3a15ea9
1//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements semantic analysis for Objective-C expressions. 11// 12//===----------------------------------------------------------------------===// 13 14#include "Sema.h" 15#include "clang/AST/ASTContext.h" 16#include "clang/AST/DeclObjC.h" 17#include "clang/AST/ExprObjC.h" 18using namespace clang; 19 20Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, 21 ExprTy **Strings, 22 unsigned NumStrings) { 23 SourceLocation AtLoc = AtLocs[0]; 24 StringLiteral* S = static_cast<StringLiteral *>(Strings[0]); 25 if (NumStrings > 1) { 26 // Concatenate objc strings. 27 StringLiteral* ES = static_cast<StringLiteral *>(Strings[NumStrings-1]); 28 SourceLocation EndLoc = ES->getSourceRange().getEnd(); 29 unsigned Length = 0; 30 for (unsigned i = 0; i < NumStrings; i++) 31 Length += static_cast<StringLiteral *>(Strings[i])->getByteLength(); 32 char *strBuf = new char [Length]; 33 char *p = strBuf; 34 bool isWide = false; 35 for (unsigned i = 0; i < NumStrings; i++) { 36 S = static_cast<StringLiteral *>(Strings[i]); 37 if (S->isWide()) 38 isWide = true; 39 memcpy(p, S->getStrData(), S->getByteLength()); 40 p += S->getByteLength(); 41 S->Destroy(Context); 42 } 43 S = new (Context, 8) StringLiteral(Context, strBuf, Length, isWide, 44 Context.getPointerType(Context.CharTy), 45 AtLoc, EndLoc); 46 } 47 48 if (CheckBuiltinCFStringArgument(S)) 49 return true; 50 51 if (Context.getObjCConstantStringInterface().isNull()) { 52 // Initialize the constant string interface lazily. This assumes 53 // the NSConstantString interface is seen in this translation unit. 54 IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString"); 55 NamedDecl *IFace = LookupName(TUScope, NSIdent, LookupOrdinaryName); 56 ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace); 57 if (strIFace) 58 Context.setObjCConstantStringInterface(strIFace); 59 } 60 QualType t = Context.getObjCConstantStringInterface(); 61 // If there is no NSConstantString interface defined then treat constant 62 // strings as untyped objects and let the runtime figure it out later. 63 if (t == QualType()) { 64 t = Context.getObjCIdType(); 65 } else { 66 t = Context.getPointerType(t); 67 } 68 return new (Context) ObjCStringLiteral(S, t, AtLoc); 69} 70 71Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, 72 SourceLocation EncodeLoc, 73 SourceLocation LParenLoc, 74 TypeTy *Ty, 75 SourceLocation RParenLoc) { 76 QualType EncodedType = QualType::getFromOpaquePtr(Ty); 77 78 QualType t = Context.getPointerType(Context.CharTy); 79 return new (Context) ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc); 80} 81 82Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, 83 SourceLocation AtLoc, 84 SourceLocation SelLoc, 85 SourceLocation LParenLoc, 86 SourceLocation RParenLoc) { 87 QualType t = Context.getObjCSelType(); 88 return new (Context) ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc); 89} 90 91Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, 92 SourceLocation AtLoc, 93 SourceLocation ProtoLoc, 94 SourceLocation LParenLoc, 95 SourceLocation RParenLoc) { 96 ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId]; 97 if (!PDecl) { 98 Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; 99 return true; 100 } 101 102 QualType t = Context.getObjCProtoType(); 103 if (t.isNull()) 104 return true; 105 t = Context.getPointerType(t); 106 return new (Context) ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); 107} 108 109bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, 110 Selector Sel, ObjCMethodDecl *Method, 111 bool isClassMessage, 112 SourceLocation lbrac, SourceLocation rbrac, 113 QualType &ReturnType) { 114 if (!Method) { 115 // Apply default argument promotion as for (C99 6.5.2.2p6). 116 for (unsigned i = 0; i != NumArgs; i++) 117 DefaultArgumentPromotion(Args[i]); 118 119 unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : 120 diag::warn_inst_method_not_found; 121 Diag(lbrac, DiagID) 122 << Sel << isClassMessage << SourceRange(lbrac, rbrac); 123 ReturnType = Context.getObjCIdType(); 124 return false; 125 } 126 127 ReturnType = Method->getResultType(); 128 129 unsigned NumNamedArgs = Sel.getNumArgs(); 130 assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!"); 131 132 bool anyIncompatibleArgs = false; 133 for (unsigned i = 0; i < NumNamedArgs; i++) { 134 Expr *argExpr = Args[i]; 135 assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 136 137 QualType lhsType = Method->getParamDecl(i)->getType(); 138 QualType rhsType = argExpr->getType(); 139 140 // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. 141 if (lhsType->isArrayType()) 142 lhsType = Context.getArrayDecayedType(lhsType); 143 else if (lhsType->isFunctionType()) 144 lhsType = Context.getPointerType(lhsType); 145 146 AssignConvertType Result = 147 CheckSingleAssignmentConstraints(lhsType, argExpr); 148 if (Args[i] != argExpr) // The expression was converted. 149 Args[i] = argExpr; // Make sure we store the converted expression. 150 151 anyIncompatibleArgs |= 152 DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, 153 argExpr, "sending"); 154 } 155 156 // Promote additional arguments to variadic methods. 157 if (Method->isVariadic()) { 158 for (unsigned i = NumNamedArgs; i < NumArgs; ++i) 159 DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); 160 } else { 161 // Check for extra arguments to non-variadic methods. 162 if (NumArgs != NumNamedArgs) { 163 Diag(Args[NumNamedArgs]->getLocStart(), 164 diag::err_typecheck_call_too_many_args) 165 << 2 /*method*/ << Method->getSourceRange() 166 << SourceRange(Args[NumNamedArgs]->getLocStart(), 167 Args[NumArgs-1]->getLocEnd()); 168 } 169 } 170 171 return anyIncompatibleArgs; 172} 173 174// ActOnClassMessage - used for both unary and keyword messages. 175// ArgExprs is optional - if it is present, the number of expressions 176// is obtained from Sel.getNumArgs(). 177Sema::ExprResult Sema::ActOnClassMessage( 178 Scope *S, 179 IdentifierInfo *receiverName, Selector Sel, 180 SourceLocation lbrac, SourceLocation receiverLoc, 181 SourceLocation selectorLoc, SourceLocation rbrac, 182 ExprTy **Args, unsigned NumArgs) 183{ 184 assert(receiverName && "missing receiver class name"); 185 186 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 187 ObjCInterfaceDecl* ClassDecl = 0; 188 bool isSuper = false; 189 190 if (receiverName->isStr("super")) { 191 if (getCurMethodDecl()) { 192 isSuper = true; 193 ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface(); 194 if (!OID) 195 return Diag(lbrac, diag::error_no_super_class_message) 196 << getCurMethodDecl()->getDeclName(); 197 ClassDecl = OID->getSuperClass(); 198 if (!ClassDecl) 199 return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName(); 200 if (getCurMethodDecl()->isInstanceMethod()) { 201 QualType superTy = Context.getObjCInterfaceType(ClassDecl); 202 superTy = Context.getPointerType(superTy); 203 ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(), 204 superTy); 205 // We are really in an instance method, redirect. 206 return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, 207 selectorLoc, rbrac, Args, NumArgs); 208 } 209 // We are sending a message to 'super' within a class method. Do nothing, 210 // the receiver will pass through as 'super' (how convenient:-). 211 } else { 212 // 'super' has been used outside a method context. If a variable named 213 // 'super' has been declared, redirect. If not, produce a diagnostic. 214 NamedDecl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName); 215 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl); 216 if (VD) { 217 ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(), 218 receiverLoc); 219 // We are really in an instance method, redirect. 220 return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, 221 selectorLoc, rbrac, Args, NumArgs); 222 } 223 return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName; 224 } 225 } else 226 ClassDecl = getObjCInterfaceDecl(receiverName); 227 228 // The following code allows for the following GCC-ism: 229 // 230 // typedef XCElementDisplayRect XCElementGraphicsRect; 231 // 232 // @implementation XCRASlice 233 // - whatever { // Note that XCElementGraphicsRect is a typedef name. 234 // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init]; 235 // } 236 // 237 // If necessary, the following lookup could move to getObjCInterfaceDecl(). 238 if (!ClassDecl) { 239 NamedDecl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName); 240 if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) { 241 const ObjCInterfaceType *OCIT; 242 OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType(); 243 if (!OCIT) 244 return Diag(receiverLoc, diag::err_invalid_receiver_to_message); 245 ClassDecl = OCIT->getDecl(); 246 } 247 } 248 assert(ClassDecl && "missing interface declaration"); 249 ObjCMethodDecl *Method = 0; 250 QualType returnType; 251 Method = ClassDecl->lookupClassMethod(Sel); 252 253 // If we have an implementation in scope, check "private" methods. 254 if (!Method) { 255 if (ObjCImplementationDecl *ImpDecl = 256 ObjCImplementations[ClassDecl->getIdentifier()]) 257 Method = ImpDecl->getClassMethod(Sel); 258 259 // Look through local category implementations associated with the class. 260 if (!Method) { 261 for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { 262 if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) 263 Method = ObjCCategoryImpls[i]->getClassMethod(Sel); 264 } 265 } 266 } 267 // Before we give up, check if the selector is an instance method. 268 if (!Method) 269 Method = ClassDecl->lookupInstanceMethod(Sel); 270 271 if (Method) { 272 if (Method->getAttr<DeprecatedAttr>()) 273 Diag(receiverLoc, diag::warn_deprecated) << Method->getDeclName(); 274 if (Method->getAttr<UnavailableAttr>()) 275 Diag(receiverLoc, diag::warn_unavailable) << Method->getDeclName(); 276 } 277 278 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true, 279 lbrac, rbrac, returnType)) 280 return true; 281 282 // If we have the ObjCInterfaceDecl* for the class that is receiving 283 // the message, use that to construct the ObjCMessageExpr. Otherwise 284 // pass on the IdentifierInfo* for the class. 285 // FIXME: need to do a better job handling 'super' usage within a class 286 // For now, we simply pass the "super" identifier through (which isn't 287 // consistent with instance methods. 288 if (isSuper) 289 return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method, 290 lbrac, rbrac, ArgExprs, NumArgs); 291 else 292 return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method, 293 lbrac, rbrac, ArgExprs, NumArgs); 294} 295 296// ActOnInstanceMessage - used for both unary and keyword messages. 297// ArgExprs is optional - if it is present, the number of expressions 298// is obtained from Sel.getNumArgs(). 299Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, 300 SourceLocation lbrac, 301 SourceLocation receiverLoc, 302 SourceLocation rbrac, 303 ExprTy **Args, unsigned NumArgs) { 304 assert(receiver && "missing receiver expression"); 305 306 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 307 Expr *RExpr = static_cast<Expr *>(receiver); 308 QualType returnType; 309 310 QualType ReceiverCType = 311 Context.getCanonicalType(RExpr->getType()).getUnqualifiedType(); 312 313 // Handle messages to 'super'. 314 if (isa<ObjCSuperExpr>(RExpr)) { 315 ObjCMethodDecl *Method = 0; 316 if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 317 // If we have an interface in scope, check 'super' methods. 318 if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) 319 if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) 320 Method = SuperDecl->lookupInstanceMethod(Sel); 321 } 322 323 if (Method) { 324 if (Method->getAttr<DeprecatedAttr>()) 325 Diag(receiverLoc, diag::warn_deprecated) << Method->getDeclName(); 326 if (Method->getAttr<UnavailableAttr>()) 327 Diag(receiverLoc, diag::warn_unavailable) << Method->getDeclName(); 328 } 329 330 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 331 lbrac, rbrac, returnType)) 332 return true; 333 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 334 rbrac, ArgExprs, NumArgs); 335 } 336 337 // Handle messages to id. 338 if (ReceiverCType == Context.getCanonicalType(Context.getObjCIdType()) || 339 ReceiverCType->getAsBlockPointerType()) { 340 ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool( 341 Sel, SourceRange(lbrac,rbrac)); 342 if (!Method) 343 Method = FactoryMethodPool[Sel].Method; 344 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 345 lbrac, rbrac, returnType)) 346 return true; 347 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 348 rbrac, ArgExprs, NumArgs); 349 } 350 351 // Handle messages to Class. 352 if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) { 353 ObjCMethodDecl *Method = 0; 354 if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 355 // If we have an implementation in scope, check "private" methods. 356 if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) 357 if (ObjCImplementationDecl *ImpDecl = 358 ObjCImplementations[ClassDecl->getIdentifier()]) 359 Method = ImpDecl->getClassMethod(Sel); 360 361 if (Method) { 362 if (Method->getAttr<DeprecatedAttr>()) 363 Diag(receiverLoc, diag::warn_deprecated) << Method->getDeclName(); 364 if (Method->getAttr<UnavailableAttr>()) 365 Diag(receiverLoc, diag::warn_unavailable) << Method->getDeclName(); 366 } 367 } 368 if (!Method) 369 Method = FactoryMethodPool[Sel].Method; 370 if (!Method) 371 Method = LookupInstanceMethodInGlobalPool( 372 Sel, SourceRange(lbrac,rbrac)); 373 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 374 lbrac, rbrac, returnType)) 375 return true; 376 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 377 rbrac, ArgExprs, NumArgs); 378 } 379 380 ObjCMethodDecl *Method = 0; 381 ObjCInterfaceDecl* ClassDecl = 0; 382 383 // We allow sending a message to a qualified ID ("id<foo>"), which is ok as 384 // long as one of the protocols implements the selector (if not, warn). 385 if (ObjCQualifiedIdType *QIT = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) { 386 // Search protocols 387 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 388 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 389 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 390 break; 391 } 392 if (!Method) 393 Diag(lbrac, diag::warn_method_not_found_in_protocol) 394 << Sel << RExpr->getSourceRange(); 395 } else if (const ObjCInterfaceType *OCIReceiver = 396 ReceiverCType->getAsPointerToObjCInterfaceType()) { 397 // We allow sending a message to a pointer to an interface (an object). 398 399 ClassDecl = OCIReceiver->getDecl(); 400 // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be 401 // faster than the following method (which can do *many* linear searches). 402 // The idea is to add class info to InstanceMethodPool. 403 Method = ClassDecl->lookupInstanceMethod(Sel); 404 405 if (!Method) { 406 // Search protocol qualifiers. 407 for (ObjCQualifiedIdType::qual_iterator QI = OCIReceiver->qual_begin(), 408 E = OCIReceiver->qual_end(); QI != E; ++QI) { 409 if ((Method = (*QI)->lookupInstanceMethod(Sel))) 410 break; 411 } 412 } 413 414 if (!Method && !OCIReceiver->qual_empty()) 415 Diag(lbrac, diag::warn_method_not_found_in_protocol) 416 << Sel << SourceRange(lbrac, rbrac); 417 418 if (Method) { 419 if (Method->getAttr<DeprecatedAttr>()) 420 Diag(receiverLoc, diag::warn_deprecated) << Method->getDeclName(); 421 if (Method->getAttr<UnavailableAttr>()) 422 Diag(receiverLoc, diag::warn_unavailable) << Method->getDeclName(); 423 } 424 } else { 425 Diag(lbrac, diag::error_bad_receiver_type) 426 << RExpr->getType() << RExpr->getSourceRange(); 427 return true; 428 } 429 430 if (!Method) { 431 // If we have an implementation in scope, check "private" methods. 432 if (ClassDecl) 433 if (ObjCImplementationDecl *ImpDecl = 434 ObjCImplementations[ClassDecl->getIdentifier()]) 435 Method = ImpDecl->getInstanceMethod(Sel); 436 // If we still haven't found a method, look in the global pool. This 437 // behavior isn't very desirable, however we need it for GCC 438 // compatibility. 439 if (!Method) 440 Method = LookupInstanceMethodInGlobalPool( 441 Sel, SourceRange(lbrac,rbrac)); 442 } 443 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 444 lbrac, rbrac, returnType)) 445 return true; 446 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 447 rbrac, ArgExprs, NumArgs); 448} 449 450//===----------------------------------------------------------------------===// 451// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 452//===----------------------------------------------------------------------===// 453 454/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 455/// inheritance hierarchy of 'rProto'. 456static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 457 ObjCProtocolDecl *rProto) { 458 if (lProto == rProto) 459 return true; 460 for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), 461 E = rProto->protocol_end(); PI != E; ++PI) 462 if (ProtocolCompatibleWithProtocol(lProto, *PI)) 463 return true; 464 return false; 465} 466 467/// ClassImplementsProtocol - Checks that 'lProto' protocol 468/// has been implemented in IDecl class, its super class or categories (if 469/// lookupCategory is true). 470static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 471 ObjCInterfaceDecl *IDecl, 472 bool lookupCategory, 473 bool RHSIsQualifiedID = false) { 474 475 // 1st, look up the class. 476 const ObjCList<ObjCProtocolDecl> &Protocols = 477 IDecl->getReferencedProtocols(); 478 479 for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(), 480 E = Protocols.end(); PI != E; ++PI) { 481 if (ProtocolCompatibleWithProtocol(lProto, *PI)) 482 return true; 483 // This is dubious and is added to be compatible with gcc. 484 // In gcc, it is also allowed assigning a protocol-qualified 'id' 485 // type to a LHS object when protocol in qualified LHS is in list 486 // of protocols in the rhs 'id' object. This IMO, should be a bug. 487 // FIXME: Treat this as an extension, and flag this as an error when 488 // GCC extensions are not enabled. 489 if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto)) 490 return true; 491 } 492 493 // 2nd, look up the category. 494 if (lookupCategory) 495 for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 496 CDecl = CDecl->getNextClassCategory()) { 497 for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), 498 E = CDecl->protocol_end(); PI != E; ++PI) 499 if (ProtocolCompatibleWithProtocol(lProto, *PI)) 500 return true; 501 } 502 503 // 3rd, look up the super class(s) 504 if (IDecl->getSuperClass()) 505 return 506 ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 507 RHSIsQualifiedID); 508 509 return false; 510} 511 512/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 513/// ObjCQualifiedIDType. 514bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 515 bool compare) { 516 // Allow id<P..> and an 'id' or void* type in all cases. 517 if (const PointerType *PT = lhs->getAsPointerType()) { 518 QualType PointeeTy = PT->getPointeeType(); 519 if (Context.isObjCIdStructType(PointeeTy) || PointeeTy->isVoidType()) 520 return true; 521 } else if (const PointerType *PT = rhs->getAsPointerType()) { 522 QualType PointeeTy = PT->getPointeeType(); 523 if (Context.isObjCIdStructType(PointeeTy) || PointeeTy->isVoidType()) 524 return true; 525 } 526 527 if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 528 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 529 const ObjCQualifiedInterfaceType *rhsQI = 0; 530 QualType rtype; 531 532 if (!rhsQID) { 533 // Not comparing two ObjCQualifiedIdType's? 534 if (!rhs->isPointerType()) return false; 535 536 rtype = rhs->getAsPointerType()->getPointeeType(); 537 rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 538 if (rhsQI == 0) { 539 // If the RHS is a unqualified interface pointer "NSString*", 540 // make sure we check the class hierarchy. 541 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 542 ObjCInterfaceDecl *rhsID = IT->getDecl(); 543 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 544 // when comparing an id<P> on lhs with a static type on rhs, 545 // see if static class implements all of id's protocols, directly or 546 // through its super class and categories. 547 if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 548 return false; 549 } 550 return true; 551 } 552 } 553 } 554 555 ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 556 if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 557 RHSProtoI = rhsQI->qual_begin(); 558 RHSProtoE = rhsQI->qual_end(); 559 } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 560 RHSProtoI = rhsQID->qual_begin(); 561 RHSProtoE = rhsQID->qual_end(); 562 } else { 563 return false; 564 } 565 566 for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 567 ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 568 bool match = false; 569 570 // when comparing an id<P> on lhs with a static type on rhs, 571 // see if static class implements all of id's protocols, directly or 572 // through its super class and categories. 573 for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 574 ObjCProtocolDecl *rhsProto = *RHSProtoI; 575 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 576 (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { 577 match = true; 578 break; 579 } 580 } 581 if (rhsQI) { 582 // If the RHS is a qualified interface pointer "NSString<P>*", 583 // make sure we check the class hierarchy. 584 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 585 ObjCInterfaceDecl *rhsID = IT->getDecl(); 586 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 587 // when comparing an id<P> on lhs with a static type on rhs, 588 // see if static class implements all of id's protocols, directly or 589 // through its super class and categories. 590 if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 591 match = true; 592 break; 593 } 594 } 595 } 596 } 597 if (!match) 598 return false; 599 } 600 601 return true; 602 } 603 604 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 605 assert(rhsQID && "One of the LHS/RHS should be id<x>"); 606 607 if (!lhs->isPointerType()) 608 return false; 609 610 QualType ltype = lhs->getAsPointerType()->getPointeeType(); 611 if (const ObjCQualifiedInterfaceType *lhsQI = 612 ltype->getAsObjCQualifiedInterfaceType()) { 613 ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 614 ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 615 for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 616 bool match = false; 617 ObjCProtocolDecl *lhsProto = *LHSProtoI; 618 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 619 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 620 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 621 (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { 622 match = true; 623 break; 624 } 625 } 626 if (!match) 627 return false; 628 } 629 return true; 630 } 631 632 if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 633 // for static type vs. qualified 'id' type, check that class implements 634 // all of 'id's protocols. 635 ObjCInterfaceDecl *lhsID = IT->getDecl(); 636 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 637 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 638 if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 639 return false; 640 } 641 return true; 642 } 643 return false; 644} 645 646