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