SemaExprObjC.cpp revision 00cb97b4750df8b2f2e9d56b56f7b07bddacd275
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 delete S; 42 } 43 S = new StringLiteral(strBuf, Length, 44 isWide, 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 Decl *IFace = LookupDecl(NSIdent, Decl::IDNS_Ordinary, TUScope); 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 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 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 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->getName()); 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 ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); 107} 108 109bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, 110 ObjCMethodDecl *Method) { 111 bool anyIncompatibleArgs = false; 112 113 for (unsigned i = 0; i < NumArgs; i++) { 114 Expr *argExpr = Args[i]; 115 assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 116 117 QualType lhsType = Method->getParamDecl(i)->getType(); 118 QualType rhsType = argExpr->getType(); 119 120 // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. 121 if (lhsType->isArrayType()) 122 lhsType = Context.getArrayDecayedType(lhsType); 123 else if (lhsType->isFunctionType()) 124 lhsType = Context.getPointerType(lhsType); 125 126 AssignConvertType Result = 127 CheckSingleAssignmentConstraints(lhsType, argExpr); 128 if (Args[i] != argExpr) // The expression was converted. 129 Args[i] = argExpr; // Make sure we store the converted expression. 130 131 anyIncompatibleArgs |= 132 DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, 133 argExpr, "sending"); 134 } 135 return anyIncompatibleArgs; 136} 137 138// ActOnClassMessage - used for both unary and keyword messages. 139// ArgExprs is optional - if it is present, the number of expressions 140// is obtained from Sel.getNumArgs(). 141Sema::ExprResult Sema::ActOnClassMessage( 142 Scope *S, 143 IdentifierInfo *receiverName, Selector Sel, 144 SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) 145{ 146 assert(receiverName && "missing receiver class name"); 147 148 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 149 ObjCInterfaceDecl* ClassDecl = 0; 150 if (!strcmp(receiverName->getName(), "super") && getCurMethodDecl()) { 151 ClassDecl = getCurMethodDecl()->getClassInterface()->getSuperClass(); 152 if (!ClassDecl) 153 return Diag(lbrac, diag::error_no_super_class, 154 getCurMethodDecl()->getClassInterface()->getName()); 155 if (getCurMethodDecl()->isInstance()) { 156 QualType superTy = Context.getObjCInterfaceType(ClassDecl); 157 superTy = Context.getPointerType(superTy); 158 ExprResult ReceiverExpr = new PreDefinedExpr(SourceLocation(), superTy, 159 PreDefinedExpr::ObjCSuper); 160 // We are really in an instance method, redirect. 161 return ActOnInstanceMessage(ReceiverExpr.Val, Sel, lbrac, rbrac, 162 Args, NumArgs); 163 } 164 // We are sending a message to 'super' within a class method. Do nothing, 165 // the receiver will pass through as 'super' (how convenient:-). 166 } else 167 ClassDecl = getObjCInterfaceDecl(receiverName); 168 169 // ClassDecl is null in the following case. 170 // 171 // typedef XCElementDisplayRect XCElementGraphicsRect; 172 // 173 // @implementation XCRASlice 174 // - whatever { // Note that XCElementGraphicsRect is a typedef name. 175 // _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init]; 176 // } 177 // 178 // FIXME: Investigate why GCC allows the above. 179 ObjCMethodDecl *Method = 0; 180 QualType returnType; 181 if (ClassDecl) { 182 Method = ClassDecl->lookupClassMethod(Sel); 183 184 // If we have an implementation in scope, check "private" methods. 185 if (!Method) { 186 if (ObjCImplementationDecl *ImpDecl = 187 ObjCImplementations[ClassDecl->getIdentifier()]) 188 Method = ImpDecl->getClassMethod(Sel); 189 } 190 // Before we give up, check if the selector is an instance method. 191 if (!Method) 192 Method = ClassDecl->lookupInstanceMethod(Sel); 193 } 194 if (!Method) { 195 Diag(lbrac, diag::warn_method_not_found, std::string("+"), Sel.getName(), 196 SourceRange(lbrac, rbrac)); 197 returnType = Context.getObjCIdType(); 198 } else { 199 returnType = Method->getResultType(); 200 if (Sel.getNumArgs()) { 201 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 202 return true; 203 } 204 } 205 206 // If we have the ObjCInterfaceDecl* for the class that is receiving 207 // the message, use that to construct the ObjCMessageExpr. Otherwise 208 // pass on the IdentifierInfo* for the class. 209 if (ClassDecl) 210 return new ObjCMessageExpr(ClassDecl, Sel, returnType, Method, 211 lbrac, rbrac, ArgExprs, NumArgs); 212 else 213 return new ObjCMessageExpr(receiverName, Sel, returnType, Method, 214 lbrac, rbrac, ArgExprs, NumArgs); 215} 216 217// ActOnInstanceMessage - used for both unary and keyword messages. 218// ArgExprs is optional - if it is present, the number of expressions 219// is obtained from Sel.getNumArgs(). 220Sema::ExprResult Sema::ActOnInstanceMessage( 221 ExprTy *receiver, Selector Sel, 222 SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) 223{ 224 assert(receiver && "missing receiver expression"); 225 226 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 227 Expr *RExpr = static_cast<Expr *>(receiver); 228 QualType receiverType; 229 QualType returnType; 230 ObjCMethodDecl *Method = 0; 231 232 receiverType = RExpr->getType().getCanonicalType().getUnqualifiedType(); 233 234 if (receiverType == Context.getObjCIdType().getCanonicalType()) { 235 Method = InstanceMethodPool[Sel].Method; 236 if (!Method) 237 Method = FactoryMethodPool[Sel].Method; 238 if (!Method) { 239 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 240 SourceRange(lbrac, rbrac)); 241 returnType = Context.getObjCIdType(); 242 } else { 243 returnType = Method->getResultType(); 244 if (Sel.getNumArgs()) 245 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 246 return true; 247 } 248 } else if (receiverType == Context.getObjCClassType().getCanonicalType()) { 249 if (getCurMethodDecl()) { 250 ObjCInterfaceDecl* ClassDecl = getCurMethodDecl()->getClassInterface(); 251 // If we have an implementation in scope, check "private" methods. 252 if (ClassDecl) 253 if (ObjCImplementationDecl *ImpDecl = 254 ObjCImplementations[ClassDecl->getIdentifier()]) 255 Method = ImpDecl->getClassMethod(Sel); 256 } 257 if (!Method) 258 Method = FactoryMethodPool[Sel].Method; 259 if (!Method) 260 Method = InstanceMethodPool[Sel].Method; 261 if (!Method) { 262 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 263 SourceRange(lbrac, rbrac)); 264 returnType = Context.getObjCIdType(); 265 } else { 266 returnType = Method->getResultType(); 267 if (Sel.getNumArgs()) 268 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 269 return true; 270 } 271 } else { 272 bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType); 273 // FIXME (snaroff): checking in this code from Patrick. Needs to be 274 // revisited. how do we get the ClassDecl from the receiver expression? 275 if (!receiverIsQualId) 276 while (const PointerType *PTy = receiverType->getAsPointerType()) 277 receiverType = PTy->getPointeeType(); 278 279 ObjCInterfaceDecl* ClassDecl = 0; 280 if (ObjCQualifiedIdType *QIT = 281 dyn_cast<ObjCQualifiedIdType>(receiverType)) { 282 // search protocols 283 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 284 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 285 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 286 break; 287 } 288 if (!Method) 289 Diag(lbrac, diag::warn_method_not_found_in_protocol, 290 std::string("-"), Sel.getName(), 291 SourceRange(lbrac, rbrac)); 292 } else { 293 ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType); 294 if (OCIReceiver == 0) { 295 Diag(lbrac, diag::error_bad_receiver_type, 296 RExpr->getType().getAsString()); 297 return true; 298 } 299 300 ClassDecl = OCIReceiver->getDecl(); 301 // FIXME: consider using InstanceMethodPool, since it will be faster 302 // than the following method (which can do *many* linear searches). The 303 // idea is to add class info to InstanceMethodPool. 304 Method = ClassDecl->lookupInstanceMethod(Sel); 305 306 if (!Method) { 307 // Search protocol qualifiers. 308 for (ObjCQualifiedIdType::qual_iterator QI = OCIReceiver->qual_begin(), 309 E = OCIReceiver->qual_end(); QI != E; ++QI) { 310 if ((Method = (*QI)->lookupInstanceMethod(Sel))) 311 break; 312 } 313 } 314 315 if (!Method && !OCIReceiver->qual_empty()) 316 Diag(lbrac, diag::warn_method_not_found_in_protocol, 317 std::string("-"), Sel.getName(), 318 SourceRange(lbrac, rbrac)); 319 } 320 321 if (!Method) { 322 // If we have an implementation in scope, check "private" methods. 323 if (ClassDecl) 324 if (ObjCImplementationDecl *ImpDecl = 325 ObjCImplementations[ClassDecl->getIdentifier()]) 326 Method = ImpDecl->getInstanceMethod(Sel); 327 // If we still haven't found a method, look in the global pool. This 328 // behavior isn't very desirable, however we need it for GCC 329 // compatibility. 330 if (!Method) 331 Method = InstanceMethodPool[Sel].Method; 332 } 333 if (!Method) { 334 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 335 SourceRange(lbrac, rbrac)); 336 returnType = Context.getObjCIdType(); 337 } else { 338 returnType = Method->getResultType(); 339 if (Sel.getNumArgs()) 340 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 341 return true; 342 } 343 } 344 return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, 345 ArgExprs, NumArgs); 346} 347 348//===----------------------------------------------------------------------===// 349// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 350//===----------------------------------------------------------------------===// 351 352/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 353/// inheritance hierarchy of 'rProto'. 354static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 355 ObjCProtocolDecl *rProto) { 356 if (lProto == rProto) 357 return true; 358 ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols(); 359 for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++) 360 if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i])) 361 return true; 362 return false; 363} 364 365/// ClassImplementsProtocol - Checks that 'lProto' protocol 366/// has been implemented in IDecl class, its super class or categories (if 367/// lookupCategory is true). 368static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 369 ObjCInterfaceDecl *IDecl, 370 bool lookupCategory, 371 bool RHSIsQualifiedID = false) { 372 373 // 1st, look up the class. 374 ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); 375 for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { 376 if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 377 return true; 378 // This is dubious and is added to be compatible with gcc. 379 // In gcc, it is also allowed assigning a protocol-qualified 'id' 380 // type to a LHS object when protocol in qualified LHS is in list 381 // of protocols in the rhs 'id' object. This IMO, should be a bug. 382 // FIXME: Treat this as an extension, and flag this as an error when 383 // GCC extensions are not enabled. 384 else if (RHSIsQualifiedID && 385 ProtocolCompatibleWithProtocol(protoList[i], lProto)) 386 return true; 387 } 388 389 // 2nd, look up the category. 390 if (lookupCategory) 391 for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 392 CDecl = CDecl->getNextClassCategory()) { 393 protoList = CDecl->getReferencedProtocols(); 394 for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { 395 if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 396 return true; 397 } 398 } 399 400 // 3rd, look up the super class(s) 401 if (IDecl->getSuperClass()) 402 return 403 ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 404 RHSIsQualifiedID); 405 406 return false; 407} 408 409/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 410/// ObjCQualifiedIDType. 411bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 412 bool compare) { 413 // Allow id<P..> and an 'id' or void* type in all cases. 414 if (const PointerType *PT = lhs->getAsPointerType()) { 415 QualType PointeeTy = PT->getPointeeType(); 416 if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 417 return true; 418 } else if (const PointerType *PT = rhs->getAsPointerType()) { 419 QualType PointeeTy = PT->getPointeeType(); 420 if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 421 return true; 422 } 423 424 if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 425 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 426 const ObjCQualifiedInterfaceType *rhsQI = 0; 427 QualType rtype; 428 429 if (!rhsQID) { 430 // Not comparing two ObjCQualifiedIdType's? 431 if (!rhs->isPointerType()) return false; 432 433 rtype = rhs->getAsPointerType()->getPointeeType(); 434 rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 435 if (rhsQI == 0) { 436 // If the RHS is a unqualified interface pointer "NSString*", 437 // make sure we check the class hierarchy. 438 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 439 ObjCInterfaceDecl *rhsID = IT->getDecl(); 440 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 441 // when comparing an id<P> on lhs with a static type on rhs, 442 // see if static class implements all of id's protocols, directly or 443 // through its super class and categories. 444 if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 445 return false; 446 } 447 return true; 448 } 449 } 450 } 451 452 ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 453 if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 454 RHSProtoI = rhsQI->qual_begin(); 455 RHSProtoE = rhsQI->qual_end(); 456 } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 457 RHSProtoI = rhsQID->qual_begin(); 458 RHSProtoE = rhsQID->qual_end(); 459 } else { 460 return false; 461 } 462 463 for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 464 ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 465 bool match = false; 466 467 // when comparing an id<P> on lhs with a static type on rhs, 468 // see if static class implements all of id's protocols, directly or 469 // through its super class and categories. 470 for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 471 ObjCProtocolDecl *rhsProto = *RHSProtoI; 472 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 473 compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 474 match = true; 475 break; 476 } 477 } 478 if (rhsQI) { 479 // If the RHS is a qualified interface pointer "NSString<P>*", 480 // make sure we check the class hierarchy. 481 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 482 ObjCInterfaceDecl *rhsID = IT->getDecl(); 483 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 484 // when comparing an id<P> on lhs with a static type on rhs, 485 // see if static class implements all of id's protocols, directly or 486 // through its super class and categories. 487 if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 488 match = true; 489 break; 490 } 491 } 492 } 493 } 494 if (!match) 495 return false; 496 } 497 498 return true; 499 } 500 501 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 502 assert(rhsQID && "One of the LHS/RHS should be id<x>"); 503 504 if (!lhs->isPointerType()) 505 return false; 506 507 QualType ltype = lhs->getAsPointerType()->getPointeeType(); 508 if (const ObjCQualifiedInterfaceType *lhsQI = 509 ltype->getAsObjCQualifiedInterfaceType()) { 510 ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 511 ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 512 for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 513 bool match = false; 514 ObjCProtocolDecl *lhsProto = *LHSProtoI; 515 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 516 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 517 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 518 compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 519 match = true; 520 break; 521 } 522 } 523 if (!match) 524 return false; 525 } 526 return true; 527 } 528 529 if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 530 // for static type vs. qualified 'id' type, check that class implements 531 // all of 'id's protocols. 532 ObjCInterfaceDecl *lhsID = IT->getDecl(); 533 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 534 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 535 if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 536 return false; 537 } 538 return true; 539 } 540 return false; 541} 542 543