SemaExprObjC.cpp revision cb3a77b0d59997cea67b254ecf23f0c8c7a122b8
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 std::string Str; 99 Context.getObjCEncodingForType(EncodedType, Str); 100 101 // The type of @encode is the same as the type of the corresponding string, 102 // which is an array type. 103 QualType StrTy = Context.CharTy; 104 // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). 105 if (getLangOptions().CPlusPlus) 106 StrTy.addConst(); 107 StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), 108 ArrayType::Normal, 0); 109 110 return new (Context) ObjCEncodeExpr(StrTy, EncodedType, AtLoc, RParenLoc); 111} 112 113Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, 114 SourceLocation AtLoc, 115 SourceLocation SelLoc, 116 SourceLocation LParenLoc, 117 SourceLocation RParenLoc) { 118 QualType Ty = Context.getObjCSelType(); 119 return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); 120} 121 122Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, 123 SourceLocation AtLoc, 124 SourceLocation ProtoLoc, 125 SourceLocation LParenLoc, 126 SourceLocation RParenLoc) { 127 ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId]; 128 if (!PDecl) { 129 Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; 130 return true; 131 } 132 133 QualType Ty = Context.getObjCProtoType(); 134 if (Ty.isNull()) 135 return true; 136 Ty = Context.getPointerType(Ty); 137 return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); 138} 139 140bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, 141 Selector Sel, ObjCMethodDecl *Method, 142 bool isClassMessage, 143 SourceLocation lbrac, SourceLocation rbrac, 144 QualType &ReturnType) { 145 if (!Method) { 146 // Apply default argument promotion as for (C99 6.5.2.2p6). 147 for (unsigned i = 0; i != NumArgs; i++) 148 DefaultArgumentPromotion(Args[i]); 149 150 unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : 151 diag::warn_inst_method_not_found; 152 Diag(lbrac, DiagID) 153 << Sel << isClassMessage << SourceRange(lbrac, rbrac); 154 ReturnType = Context.getObjCIdType(); 155 return false; 156 } 157 158 ReturnType = Method->getResultType(); 159 160 unsigned NumNamedArgs = Sel.getNumArgs(); 161 assert(NumArgs >= NumNamedArgs && "Too few arguments for selector!"); 162 163 bool anyIncompatibleArgs = false; 164 for (unsigned i = 0; i < NumNamedArgs; i++) { 165 Expr *argExpr = Args[i]; 166 assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 167 168 QualType lhsType = Method->param_begin()[i]->getType(); 169 QualType rhsType = argExpr->getType(); 170 171 // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. 172 if (lhsType->isArrayType()) 173 lhsType = Context.getArrayDecayedType(lhsType); 174 else if (lhsType->isFunctionType()) 175 lhsType = Context.getPointerType(lhsType); 176 177 AssignConvertType Result = 178 CheckSingleAssignmentConstraints(lhsType, argExpr); 179 if (Args[i] != argExpr) // The expression was converted. 180 Args[i] = argExpr; // Make sure we store the converted expression. 181 182 anyIncompatibleArgs |= 183 DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, 184 argExpr, "sending"); 185 } 186 187 // Promote additional arguments to variadic methods. 188 if (Method->isVariadic()) { 189 for (unsigned i = NumNamedArgs; i < NumArgs; ++i) 190 DefaultVariadicArgumentPromotion(Args[i], VariadicMethod); 191 } else { 192 // Check for extra arguments to non-variadic methods. 193 if (NumArgs != NumNamedArgs) { 194 Diag(Args[NumNamedArgs]->getLocStart(), 195 diag::err_typecheck_call_too_many_args) 196 << 2 /*method*/ << Method->getSourceRange() 197 << SourceRange(Args[NumNamedArgs]->getLocStart(), 198 Args[NumArgs-1]->getLocEnd()); 199 } 200 } 201 202 return anyIncompatibleArgs; 203} 204 205bool Sema::isSelfExpr(Expr *RExpr) { 206 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr)) 207 if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self")) 208 return true; 209 return false; 210} 211 212// Helper method for ActOnClassMethod/ActOnInstanceMethod. 213// Will search "local" class/category implementations for a method decl. 214// Returns 0 if no method is found. 215ObjCMethodDecl *Sema::LookupPrivateMethod(Selector Sel, 216 ObjCInterfaceDecl *ClassDecl) { 217 ObjCMethodDecl *Method = 0; 218 219 if (ObjCImplementationDecl *ImpDecl = 220 ObjCImplementations[ClassDecl->getIdentifier()]) 221 Method = ImpDecl->getClassMethod(Sel); 222 223 // Look through local category implementations associated with the class. 224 if (!Method) { 225 for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { 226 if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) 227 Method = ObjCCategoryImpls[i]->getClassMethod(Sel); 228 } 229 } 230 return Method; 231} 232 233// ActOnClassMessage - used for both unary and keyword messages. 234// ArgExprs is optional - if it is present, the number of expressions 235// is obtained from Sel.getNumArgs(). 236Sema::ExprResult Sema::ActOnClassMessage( 237 Scope *S, 238 IdentifierInfo *receiverName, Selector Sel, 239 SourceLocation lbrac, SourceLocation receiverLoc, 240 SourceLocation selectorLoc, SourceLocation rbrac, 241 ExprTy **Args, unsigned NumArgs) 242{ 243 assert(receiverName && "missing receiver class name"); 244 245 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 246 ObjCInterfaceDecl* ClassDecl = 0; 247 bool isSuper = false; 248 249 if (receiverName->isStr("super")) { 250 if (getCurMethodDecl()) { 251 isSuper = true; 252 ObjCInterfaceDecl *OID = getCurMethodDecl()->getClassInterface(); 253 if (!OID) 254 return Diag(lbrac, diag::error_no_super_class_message) 255 << getCurMethodDecl()->getDeclName(); 256 ClassDecl = OID->getSuperClass(); 257 if (!ClassDecl) 258 return Diag(lbrac, diag::error_no_super_class) << OID->getDeclName(); 259 if (getCurMethodDecl()->isInstanceMethod()) { 260 QualType superTy = Context.getObjCInterfaceType(ClassDecl); 261 superTy = Context.getPointerType(superTy); 262 ExprResult ReceiverExpr = new (Context) ObjCSuperExpr(SourceLocation(), 263 superTy); 264 // We are really in an instance method, redirect. 265 return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, 266 selectorLoc, rbrac, Args, NumArgs); 267 } 268 // We are sending a message to 'super' within a class method. Do nothing, 269 // the receiver will pass through as 'super' (how convenient:-). 270 } else { 271 // 'super' has been used outside a method context. If a variable named 272 // 'super' has been declared, redirect. If not, produce a diagnostic. 273 NamedDecl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName); 274 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl); 275 if (VD) { 276 ExprResult ReceiverExpr = new (Context) DeclRefExpr(VD, VD->getType(), 277 receiverLoc); 278 // We are really in an instance method, redirect. 279 return ActOnInstanceMessage(ReceiverExpr.get(), Sel, lbrac, 280 selectorLoc, rbrac, Args, NumArgs); 281 } 282 return Diag(receiverLoc, diag::err_undeclared_var_use) << receiverName; 283 } 284 } else 285 ClassDecl = getObjCInterfaceDecl(receiverName); 286 287 // The following code allows for the following GCC-ism: 288 // 289 // typedef XCElementDisplayRect XCElementGraphicsRect; 290 // 291 // @implementation XCRASlice 292 // - whatever { // Note that XCElementGraphicsRect is a typedef name. 293 // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init]; 294 // } 295 // 296 // If necessary, the following lookup could move to getObjCInterfaceDecl(). 297 if (!ClassDecl) { 298 NamedDecl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName); 299 if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) { 300 const ObjCInterfaceType *OCIT; 301 OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType(); 302 if (!OCIT) 303 return Diag(receiverLoc, diag::err_invalid_receiver_to_message); 304 ClassDecl = OCIT->getDecl(); 305 } 306 } 307 assert(ClassDecl && "missing interface declaration"); 308 ObjCMethodDecl *Method = 0; 309 QualType returnType; 310 Method = ClassDecl->lookupClassMethod(Sel); 311 312 // If we have an implementation in scope, check "private" methods. 313 if (!Method) 314 Method = LookupPrivateMethod(Sel, ClassDecl); 315 316 // Before we give up, check if the selector is an instance method. 317 // But only in the root. This matches gcc's behaviour and what the 318 // runtime expects. 319 if (!Method) { 320 ObjCInterfaceDecl *Root = ClassDecl; 321 while (Root->getSuperClass()) 322 Root = Root->getSuperClass(); 323 Method = Root->lookupInstanceMethod(Sel); 324 } 325 326 if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 327 return true; 328 329 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true, 330 lbrac, rbrac, returnType)) 331 return true; 332 333 // If we have the ObjCInterfaceDecl* for the class that is receiving 334 // the message, use that to construct the ObjCMessageExpr. Otherwise 335 // pass on the IdentifierInfo* for the class. 336 // FIXME: need to do a better job handling 'super' usage within a class 337 // For now, we simply pass the "super" identifier through (which isn't 338 // consistent with instance methods. 339 if (isSuper) 340 return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method, 341 lbrac, rbrac, ArgExprs, NumArgs); 342 else 343 return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method, 344 lbrac, rbrac, ArgExprs, NumArgs); 345} 346 347// ActOnInstanceMessage - used for both unary and keyword messages. 348// ArgExprs is optional - if it is present, the number of expressions 349// is obtained from Sel.getNumArgs(). 350Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, 351 SourceLocation lbrac, 352 SourceLocation receiverLoc, 353 SourceLocation rbrac, 354 ExprTy **Args, unsigned NumArgs) { 355 assert(receiver && "missing receiver expression"); 356 357 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 358 Expr *RExpr = static_cast<Expr *>(receiver); 359 QualType returnType; 360 361 QualType ReceiverCType = 362 Context.getCanonicalType(RExpr->getType()).getUnqualifiedType(); 363 364 // Handle messages to 'super'. 365 if (isa<ObjCSuperExpr>(RExpr)) { 366 ObjCMethodDecl *Method = 0; 367 if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 368 // If we have an interface in scope, check 'super' methods. 369 if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) 370 if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) 371 Method = SuperDecl->lookupInstanceMethod(Sel); 372 } 373 374 if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 375 return true; 376 377 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 378 lbrac, rbrac, returnType)) 379 return true; 380 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 381 rbrac, ArgExprs, NumArgs); 382 } 383 384 // Handle messages to id. 385 if (ReceiverCType == Context.getCanonicalType(Context.getObjCIdType()) || 386 ReceiverCType->getAsBlockPointerType()) { 387 ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool( 388 Sel, SourceRange(lbrac,rbrac)); 389 if (!Method) 390 Method = FactoryMethodPool[Sel].Method; 391 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 392 lbrac, rbrac, returnType)) 393 return true; 394 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 395 rbrac, ArgExprs, NumArgs); 396 } 397 398 // Handle messages to Class. 399 if (ReceiverCType == Context.getCanonicalType(Context.getObjCClassType())) { 400 ObjCMethodDecl *Method = 0; 401 402 if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { 403 if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { 404 // First check the public methods in the class interface. 405 Method = ClassDecl->lookupClassMethod(Sel); 406 407 if (!Method) 408 Method = LookupPrivateMethod(Sel, ClassDecl); 409 // Before we give up, check if the selector is an instance method. 410 // But only in the root. This matches gcc's behaviour and what the 411 // runtime expects. 412 if (!Method) { 413 ObjCInterfaceDecl *Root = ClassDecl; 414 while (Root->getSuperClass()) 415 Root = Root->getSuperClass(); 416 Method = Root->lookupInstanceMethod(Sel); 417 } 418 } 419 if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 420 return true; 421 } 422 if (!Method) { 423 // If not messaging 'self', look for any factory method named 'Sel'. 424 if (!isSelfExpr(RExpr)) { 425 Method = FactoryMethodPool[Sel].Method; 426 if (!Method) { 427 Method = LookupInstanceMethodInGlobalPool( 428 Sel, SourceRange(lbrac,rbrac)); 429 if (Method) 430 Diag(receiverLoc, diag::warn_maynot_respond) << Sel; 431 } 432 } 433 } 434 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 435 lbrac, rbrac, returnType)) 436 return true; 437 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 438 rbrac, ArgExprs, NumArgs); 439 } 440 441 ObjCMethodDecl *Method = 0; 442 ObjCInterfaceDecl* ClassDecl = 0; 443 444 // We allow sending a message to a qualified ID ("id<foo>"), which is ok as 445 // long as one of the protocols implements the selector (if not, warn). 446 if (ObjCQualifiedIdType *QIT = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) { 447 // Search protocols for instance methods. 448 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 449 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 450 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 451 break; 452 } 453 // Check for GCC extension "Class<foo>". 454 } else if (ObjCQualifiedClassType *QIT = 455 dyn_cast<ObjCQualifiedClassType>(ReceiverCType)) { 456 // Search protocols for class methods. 457 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 458 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 459 if (PDecl && (Method = PDecl->lookupClassMethod(Sel))) 460 break; 461 } 462 } else if (const ObjCInterfaceType *OCIType = 463 ReceiverCType->getAsPointerToObjCInterfaceType()) { 464 // We allow sending a message to a pointer to an interface (an object). 465 466 ClassDecl = OCIType->getDecl(); 467 // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be 468 // faster than the following method (which can do *many* linear searches). 469 // The idea is to add class info to InstanceMethodPool. 470 Method = ClassDecl->lookupInstanceMethod(Sel); 471 472 if (!Method) { 473 // Search protocol qualifiers. 474 for (ObjCQualifiedInterfaceType::qual_iterator QI = OCIType->qual_begin(), 475 E = OCIType->qual_end(); QI != E; ++QI) { 476 if ((Method = (*QI)->lookupInstanceMethod(Sel))) 477 break; 478 } 479 } 480 if (!Method) { 481 // If we have an implementation in scope, check "private" methods. 482 if (ClassDecl) { 483 if (ObjCImplementationDecl *ImpDecl = 484 ObjCImplementations[ClassDecl->getIdentifier()]) 485 Method = ImpDecl->getInstanceMethod(Sel); 486 // Look through local category implementations associated with the class. 487 if (!Method) { 488 for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { 489 if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) 490 Method = ObjCCategoryImpls[i]->getInstanceMethod(Sel); 491 } 492 } 493 } 494 if (!isSelfExpr(RExpr)) { 495 // If we still haven't found a method, look in the global pool. This 496 // behavior isn't very desirable, however we need it for GCC 497 // compatibility. FIXME: should we deviate?? 498 if (!Method && OCIType->qual_empty()) { 499 Method = LookupInstanceMethodInGlobalPool( 500 Sel, SourceRange(lbrac,rbrac)); 501 if (Method && !OCIType->getDecl()->isForwardDecl()) 502 Diag(lbrac, diag::warn_maynot_respond) 503 << OCIType->getDecl()->getIdentifier()->getName() << Sel; 504 } 505 } 506 } 507 if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) 508 return true; 509 } else { 510 Diag(lbrac, diag::warn_bad_receiver_type) 511 << RExpr->getType() << RExpr->getSourceRange(); 512 return true; 513 } 514 515 if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, 516 lbrac, rbrac, returnType)) 517 return true; 518 return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, 519 rbrac, ArgExprs, NumArgs); 520} 521 522//===----------------------------------------------------------------------===// 523// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 524//===----------------------------------------------------------------------===// 525 526/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 527/// inheritance hierarchy of 'rProto'. 528static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 529 ObjCProtocolDecl *rProto) { 530 if (lProto == rProto) 531 return true; 532 for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), 533 E = rProto->protocol_end(); PI != E; ++PI) 534 if (ProtocolCompatibleWithProtocol(lProto, *PI)) 535 return true; 536 return false; 537} 538 539/// ClassImplementsProtocol - Checks that 'lProto' protocol 540/// has been implemented in IDecl class, its super class or categories (if 541/// lookupCategory is true). 542static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 543 ObjCInterfaceDecl *IDecl, 544 bool lookupCategory, 545 bool RHSIsQualifiedID = false) { 546 547 // 1st, look up the class. 548 const ObjCList<ObjCProtocolDecl> &Protocols = 549 IDecl->getReferencedProtocols(); 550 551 for (ObjCList<ObjCProtocolDecl>::iterator PI = Protocols.begin(), 552 E = Protocols.end(); PI != E; ++PI) { 553 if (ProtocolCompatibleWithProtocol(lProto, *PI)) 554 return true; 555 // This is dubious and is added to be compatible with gcc. 556 // In gcc, it is also allowed assigning a protocol-qualified 'id' 557 // type to a LHS object when protocol in qualified LHS is in list 558 // of protocols in the rhs 'id' object. This IMO, should be a bug. 559 // FIXME: Treat this as an extension, and flag this as an error when 560 // GCC extensions are not enabled. 561 if (RHSIsQualifiedID && ProtocolCompatibleWithProtocol(*PI, lProto)) 562 return true; 563 } 564 565 // 2nd, look up the category. 566 if (lookupCategory) 567 for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 568 CDecl = CDecl->getNextClassCategory()) { 569 for (ObjCCategoryDecl::protocol_iterator PI = CDecl->protocol_begin(), 570 E = CDecl->protocol_end(); PI != E; ++PI) 571 if (ProtocolCompatibleWithProtocol(lProto, *PI)) 572 return true; 573 } 574 575 // 3rd, look up the super class(s) 576 if (IDecl->getSuperClass()) 577 return 578 ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 579 RHSIsQualifiedID); 580 581 return false; 582} 583 584/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 585/// ObjCQualifiedIDType. 586/// FIXME: Move to ASTContext::typesAreCompatible() and friends. 587bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 588 bool compare) { 589 // Allow id<P..> and an 'id' or void* type in all cases. 590 if (const PointerType *PT = lhs->getAsPointerType()) { 591 QualType PointeeTy = PT->getPointeeType(); 592 if (Context.isObjCIdStructType(PointeeTy) || PointeeTy->isVoidType()) 593 return true; 594 } else if (const PointerType *PT = rhs->getAsPointerType()) { 595 QualType PointeeTy = PT->getPointeeType(); 596 if (Context.isObjCIdStructType(PointeeTy) || PointeeTy->isVoidType()) 597 return true; 598 } 599 600 if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 601 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 602 const ObjCQualifiedInterfaceType *rhsQI = 0; 603 QualType rtype; 604 605 if (!rhsQID) { 606 // Not comparing two ObjCQualifiedIdType's? 607 if (!rhs->isPointerType()) return false; 608 609 rtype = rhs->getAsPointerType()->getPointeeType(); 610 rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 611 if (rhsQI == 0) { 612 // If the RHS is a unqualified interface pointer "NSString*", 613 // make sure we check the class hierarchy. 614 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 615 ObjCInterfaceDecl *rhsID = IT->getDecl(); 616 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 617 // when comparing an id<P> on lhs with a static type on rhs, 618 // see if static class implements all of id's protocols, directly or 619 // through its super class and categories. 620 if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 621 return false; 622 } 623 return true; 624 } 625 } 626 } 627 628 ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 629 if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 630 RHSProtoI = rhsQI->qual_begin(); 631 RHSProtoE = rhsQI->qual_end(); 632 } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 633 RHSProtoI = rhsQID->qual_begin(); 634 RHSProtoE = rhsQID->qual_end(); 635 } else { 636 return false; 637 } 638 639 for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 640 ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 641 bool match = false; 642 643 // when comparing an id<P> on lhs with a static type on rhs, 644 // see if static class implements all of id's protocols, directly or 645 // through its super class and categories. 646 for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 647 ObjCProtocolDecl *rhsProto = *RHSProtoI; 648 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 649 (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { 650 match = true; 651 break; 652 } 653 } 654 if (rhsQI) { 655 // If the RHS is a qualified interface pointer "NSString<P>*", 656 // make sure we check the class hierarchy. 657 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 658 ObjCInterfaceDecl *rhsID = IT->getDecl(); 659 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 660 // when comparing an id<P> on lhs with a static type on rhs, 661 // see if static class implements all of id's protocols, directly or 662 // through its super class and categories. 663 if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 664 match = true; 665 break; 666 } 667 } 668 } 669 } 670 if (!match) 671 return false; 672 } 673 674 return true; 675 } 676 677 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 678 assert(rhsQID && "One of the LHS/RHS should be id<x>"); 679 680 if (!lhs->isPointerType()) 681 return false; 682 683 QualType ltype = lhs->getAsPointerType()->getPointeeType(); 684 if (const ObjCQualifiedInterfaceType *lhsQI = 685 ltype->getAsObjCQualifiedInterfaceType()) { 686 ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 687 ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 688 for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 689 bool match = false; 690 ObjCProtocolDecl *lhsProto = *LHSProtoI; 691 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 692 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 693 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 694 (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { 695 match = true; 696 break; 697 } 698 } 699 if (!match) 700 return false; 701 } 702 return true; 703 } 704 705 if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 706 // for static type vs. qualified 'id' type, check that class implements 707 // all of 'id's protocols. 708 ObjCInterfaceDecl *lhsID = IT->getDecl(); 709 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 710 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 711 if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 712 return false; 713 } 714 return true; 715 } 716 return false; 717} 718 719