SemaExprObjC.cpp revision 9baefc21bfe1bf49ab4a234e9f267f00abe0b1b1
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 (ObjCQualifiedInterfaceType *QIT = 281 dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) { 282 ClassDecl = QIT->getDecl(); 283 Method = ClassDecl->lookupInstanceMethod(Sel); 284 if (!Method) { 285 // search protocols 286 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 287 ObjCProtocolDecl *PDecl = QIT->getProtocol(i); 288 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 289 break; 290 } 291 } 292 if (!Method) 293 Diag(lbrac, diag::warn_method_not_found_in_protocol, 294 std::string("-"), Sel.getName(), 295 SourceRange(lbrac, rbrac)); 296 } 297 else if (ObjCQualifiedIdType *QIT = 298 dyn_cast<ObjCQualifiedIdType>(receiverType)) { 299 // search protocols 300 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 301 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 302 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 303 break; 304 } 305 if (!Method) 306 Diag(lbrac, diag::warn_method_not_found_in_protocol, 307 std::string("-"), Sel.getName(), 308 SourceRange(lbrac, rbrac)); 309 } 310 else { 311 ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType); 312 if (OCIReceiver == 0) { 313 Diag(lbrac, diag::error_bad_receiver_type, 314 RExpr->getType().getAsString()); 315 return true; 316 } 317 ClassDecl = OCIReceiver->getDecl(); 318 // FIXME: consider using InstanceMethodPool, since it will be faster 319 // than the following method (which can do *many* linear searches). The 320 // idea is to add class info to InstanceMethodPool... 321 Method = ClassDecl->lookupInstanceMethod(Sel); 322 } 323 if (!Method) { 324 // If we have an implementation in scope, check "private" methods. 325 if (ClassDecl) 326 if (ObjCImplementationDecl *ImpDecl = 327 ObjCImplementations[ClassDecl->getIdentifier()]) 328 Method = ImpDecl->getInstanceMethod(Sel); 329 // If we still haven't found a method, look in the global pool. This 330 // behavior isn't very desirable, however we need it for GCC 331 // compatibility. 332 if (!Method) 333 Method = InstanceMethodPool[Sel].Method; 334 } 335 if (!Method) { 336 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 337 SourceRange(lbrac, rbrac)); 338 returnType = Context.getObjCIdType(); 339 } else { 340 returnType = Method->getResultType(); 341 if (Sel.getNumArgs()) 342 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 343 return true; 344 } 345 } 346 return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, 347 ArgExprs, NumArgs); 348} 349 350//===----------------------------------------------------------------------===// 351// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 352//===----------------------------------------------------------------------===// 353 354/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 355/// inheritance hierarchy of 'rProto'. 356static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 357 ObjCProtocolDecl *rProto) { 358 if (lProto == rProto) 359 return true; 360 ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols(); 361 for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++) 362 if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i])) 363 return true; 364 return false; 365} 366 367/// ClassImplementsProtocol - Checks that 'lProto' protocol 368/// has been implemented in IDecl class, its super class or categories (if 369/// lookupCategory is true). 370static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 371 ObjCInterfaceDecl *IDecl, 372 bool lookupCategory, 373 bool RHSIsQualifiedID = false) { 374 375 // 1st, look up the class. 376 ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); 377 for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { 378 if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 379 return true; 380 // This is dubious and is added to be compatible with gcc. 381 // In gcc, it is also allowed assigning a protocol-qualified 'id' 382 // type to a LHS object when protocol in qualified LHS is in list 383 // of protocols in the rhs 'id' object. This IMO, should be a bug. 384 // FIXME: Treat this as an extension, and flag this as an error when 385 // GCC extensions are not enabled. 386 else if (RHSIsQualifiedID && 387 ProtocolCompatibleWithProtocol(protoList[i], lProto)) 388 return true; 389 } 390 391 // 2nd, look up the category. 392 if (lookupCategory) 393 for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 394 CDecl = CDecl->getNextClassCategory()) { 395 protoList = CDecl->getReferencedProtocols(); 396 for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { 397 if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 398 return true; 399 } 400 } 401 402 // 3rd, look up the super class(s) 403 if (IDecl->getSuperClass()) 404 return 405 ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 406 RHSIsQualifiedID); 407 408 return false; 409} 410 411/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 412/// ObjCQualifiedIDType. 413bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 414 bool compare) { 415 // Allow id<P..> and an 'id' or void* type in all cases. 416 if (const PointerType *PT = lhs->getAsPointerType()) { 417 QualType PointeeTy = PT->getPointeeType(); 418 if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 419 return true; 420 } else if (const PointerType *PT = rhs->getAsPointerType()) { 421 QualType PointeeTy = PT->getPointeeType(); 422 if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 423 return true; 424 } 425 426 if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 427 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 428 const ObjCQualifiedInterfaceType *rhsQI = 0; 429 QualType rtype; 430 431 if (!rhsQID) { 432 // Not comparing two ObjCQualifiedIdType's? 433 if (!rhs->isPointerType()) return false; 434 435 rtype = rhs->getAsPointerType()->getPointeeType(); 436 rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 437 if (rhsQI == 0) { 438 // If the RHS is a unqualified interface pointer "NSString*", 439 // make sure we check the class hierarchy. 440 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 441 ObjCInterfaceDecl *rhsID = IT->getDecl(); 442 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 443 // when comparing an id<P> on lhs with a static type on rhs, 444 // see if static class implements all of id's protocols, directly or 445 // through its super class and categories. 446 if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 447 return false; 448 } 449 return true; 450 } 451 } 452 } 453 454 ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 455 if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 456 RHSProtoI = rhsQI->qual_begin(); 457 RHSProtoE = rhsQI->qual_end(); 458 } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 459 RHSProtoI = rhsQID->qual_begin(); 460 RHSProtoE = rhsQID->qual_end(); 461 } else { 462 return false; 463 } 464 465 for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 466 ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 467 bool match = false; 468 469 // when comparing an id<P> on lhs with a static type on rhs, 470 // see if static class implements all of id's protocols, directly or 471 // through its super class and categories. 472 for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 473 ObjCProtocolDecl *rhsProto = *RHSProtoI; 474 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 475 compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 476 match = true; 477 break; 478 } 479 } 480 if (rhsQI) { 481 // If the RHS is a qualified interface pointer "NSString<P>*", 482 // make sure we check the class hierarchy. 483 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 484 ObjCInterfaceDecl *rhsID = IT->getDecl(); 485 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 486 // when comparing an id<P> on lhs with a static type on rhs, 487 // see if static class implements all of id's protocols, directly or 488 // through its super class and categories. 489 if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 490 match = true; 491 break; 492 } 493 } 494 } 495 } 496 if (!match) 497 return false; 498 } 499 500 return true; 501 } 502 503 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 504 assert(rhsQID && "One of the LHS/RHS should be id<x>"); 505 506 if (!lhs->isPointerType()) 507 return false; 508 509 QualType ltype = lhs->getAsPointerType()->getPointeeType(); 510 if (const ObjCQualifiedInterfaceType *lhsQI = 511 ltype->getAsObjCQualifiedInterfaceType()) { 512 ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 513 ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 514 for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 515 bool match = false; 516 ObjCProtocolDecl *lhsProto = *LHSProtoI; 517 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 518 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 519 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 520 compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 521 match = true; 522 break; 523 } 524 } 525 if (!match) 526 return false; 527 } 528 return true; 529 } 530 531 if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 532 // for static type vs. qualified 'id' type, check that class implements 533 // all of 'id's protocols. 534 ObjCInterfaceDecl *lhsID = IT->getDecl(); 535 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 536 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 537 if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 538 return false; 539 } 540 return true; 541 } 542 return false; 543} 544 545