SemaExprObjC.cpp revision e2af8b16cb66b59ac3570c5561289469bd852699
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 return Diag(S->getLocStart(), diag::err_undef_interface, 59 NSIdent->getName()); 60 Context.setObjCConstantStringInterface(strIFace); 61 } 62 QualType t = Context.getObjCConstantStringInterface(); 63 t = Context.getPointerType(t); 64 return new ObjCStringLiteral(S, t, AtLoc); 65} 66 67Sema::ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, 68 SourceLocation EncodeLoc, 69 SourceLocation LParenLoc, 70 TypeTy *Ty, 71 SourceLocation RParenLoc) { 72 QualType EncodedType = QualType::getFromOpaquePtr(Ty); 73 74 QualType t = Context.getPointerType(Context.CharTy); 75 return new ObjCEncodeExpr(t, EncodedType, AtLoc, RParenLoc); 76} 77 78Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, 79 SourceLocation AtLoc, 80 SourceLocation SelLoc, 81 SourceLocation LParenLoc, 82 SourceLocation RParenLoc) { 83 QualType t = Context.getObjCSelType(); 84 return new ObjCSelectorExpr(t, Sel, AtLoc, RParenLoc); 85} 86 87Sema::ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, 88 SourceLocation AtLoc, 89 SourceLocation ProtoLoc, 90 SourceLocation LParenLoc, 91 SourceLocation RParenLoc) { 92 ObjCProtocolDecl* PDecl = ObjCProtocols[ProtocolId]; 93 if (!PDecl) { 94 Diag(ProtoLoc, diag::err_undeclared_protocol, ProtocolId->getName()); 95 return true; 96 } 97 98 QualType t = Context.getObjCProtoType(); 99 if (t.isNull()) 100 return true; 101 t = Context.getPointerType(t); 102 return new ObjCProtocolExpr(t, PDecl, AtLoc, RParenLoc); 103} 104 105bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, 106 ObjCMethodDecl *Method) { 107 bool anyIncompatibleArgs = false; 108 109 for (unsigned i = 0; i < NumArgs; i++) { 110 Expr *argExpr = Args[i]; 111 assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); 112 113 QualType lhsType = Method->getParamDecl(i)->getType(); 114 QualType rhsType = argExpr->getType(); 115 116 // If necessary, apply function/array conversion. C99 6.7.5.3p[7,8]. 117 if (lhsType->isArrayType()) 118 lhsType = Context.getArrayDecayedType(lhsType); 119 else if (lhsType->isFunctionType()) 120 lhsType = Context.getPointerType(lhsType); 121 122 AssignConvertType Result = 123 CheckSingleAssignmentConstraints(lhsType, argExpr); 124 if (Args[i] != argExpr) // The expression was converted. 125 Args[i] = argExpr; // Make sure we store the converted expression. 126 127 anyIncompatibleArgs |= 128 DiagnoseAssignmentResult(Result, argExpr->getLocStart(), lhsType, rhsType, 129 argExpr, "sending"); 130 } 131 return anyIncompatibleArgs; 132} 133 134// ActOnClassMessage - used for both unary and keyword messages. 135// ArgExprs is optional - if it is present, the number of expressions 136// is obtained from Sel.getNumArgs(). 137Sema::ExprResult Sema::ActOnClassMessage( 138 Scope *S, 139 IdentifierInfo *receiverName, Selector Sel, 140 SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) 141{ 142 assert(receiverName && "missing receiver class name"); 143 144 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 145 ObjCInterfaceDecl* ClassDecl = 0; 146 if (!strcmp(receiverName->getName(), "super") && CurMethodDecl) { 147 ClassDecl = CurMethodDecl->getClassInterface()->getSuperClass(); 148 if (!ClassDecl) 149 return Diag(lbrac, diag::error_no_super_class, 150 CurMethodDecl->getClassInterface()->getName()); 151 if (CurMethodDecl->isInstance()) { 152 // Synthesize a cast to the super class. This hack allows us to loosely 153 // represent super without creating a special expression node. 154 IdentifierInfo &II = Context.Idents.get("self"); 155 ExprResult ReceiverExpr = ActOnIdentifierExpr(S, lbrac, II, false); 156 QualType superTy = Context.getObjCInterfaceType(ClassDecl); 157 superTy = Context.getPointerType(superTy); 158 ReceiverExpr = ActOnCastExpr(SourceLocation(), superTy.getAsOpaquePtr(), 159 SourceLocation(), ReceiverExpr.Val); 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 return new ObjCMessageExpr(receiverName, Sel, returnType, Method, 206 lbrac, rbrac, ArgExprs, NumArgs); 207} 208 209// ActOnInstanceMessage - used for both unary and keyword messages. 210// ArgExprs is optional - if it is present, the number of expressions 211// is obtained from Sel.getNumArgs(). 212Sema::ExprResult Sema::ActOnInstanceMessage( 213 ExprTy *receiver, Selector Sel, 214 SourceLocation lbrac, SourceLocation rbrac, ExprTy **Args, unsigned NumArgs) 215{ 216 assert(receiver && "missing receiver expression"); 217 218 Expr **ArgExprs = reinterpret_cast<Expr **>(Args); 219 Expr *RExpr = static_cast<Expr *>(receiver); 220 QualType receiverType; 221 QualType returnType; 222 ObjCMethodDecl *Method = 0; 223 224 receiverType = RExpr->getType().getCanonicalType().getUnqualifiedType(); 225 226 if (receiverType == Context.getObjCIdType().getCanonicalType()) { 227 Method = InstanceMethodPool[Sel].Method; 228 if (!Method) 229 Method = FactoryMethodPool[Sel].Method; 230 if (!Method) { 231 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 232 SourceRange(lbrac, rbrac)); 233 returnType = Context.getObjCIdType(); 234 } else { 235 returnType = Method->getResultType(); 236 if (Sel.getNumArgs()) 237 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 238 return true; 239 } 240 } else if (receiverType == Context.getObjCClassType().getCanonicalType()) { 241 if (CurMethodDecl) { 242 ObjCInterfaceDecl* ClassDecl = CurMethodDecl->getClassInterface(); 243 // If we have an implementation in scope, check "private" methods. 244 if (ClassDecl) 245 if (ObjCImplementationDecl *ImpDecl = 246 ObjCImplementations[ClassDecl->getIdentifier()]) 247 Method = ImpDecl->getClassMethod(Sel); 248 } 249 if (!Method) 250 Method = FactoryMethodPool[Sel].Method; 251 if (!Method) 252 Method = InstanceMethodPool[Sel].Method; 253 if (!Method) { 254 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 255 SourceRange(lbrac, rbrac)); 256 returnType = Context.getObjCIdType(); 257 } else { 258 returnType = Method->getResultType(); 259 if (Sel.getNumArgs()) 260 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 261 return true; 262 } 263 } else { 264 bool receiverIsQualId = isa<ObjCQualifiedIdType>(receiverType); 265 // FIXME (snaroff): checking in this code from Patrick. Needs to be 266 // revisited. how do we get the ClassDecl from the receiver expression? 267 if (!receiverIsQualId) 268 while (const PointerType *PTy = receiverType->getAsPointerType()) 269 receiverType = PTy->getPointeeType(); 270 271 ObjCInterfaceDecl* ClassDecl = 0; 272 if (ObjCQualifiedInterfaceType *QIT = 273 dyn_cast<ObjCQualifiedInterfaceType>(receiverType)) { 274 ClassDecl = QIT->getDecl(); 275 Method = ClassDecl->lookupInstanceMethod(Sel); 276 if (!Method) { 277 // search protocols 278 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 279 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 280 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 281 break; 282 } 283 } 284 if (!Method) 285 Diag(lbrac, diag::warn_method_not_found_in_protocol, 286 std::string("-"), Sel.getName(), 287 SourceRange(lbrac, rbrac)); 288 } 289 else if (ObjCQualifiedIdType *QIT = 290 dyn_cast<ObjCQualifiedIdType>(receiverType)) { 291 // search protocols 292 for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { 293 ObjCProtocolDecl *PDecl = QIT->getProtocols(i); 294 if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) 295 break; 296 } 297 if (!Method) 298 Diag(lbrac, diag::warn_method_not_found_in_protocol, 299 std::string("-"), Sel.getName(), 300 SourceRange(lbrac, rbrac)); 301 } 302 else { 303 ObjCInterfaceType *OCIReceiver =dyn_cast<ObjCInterfaceType>(receiverType); 304 if (OCIReceiver == 0) { 305 Diag(lbrac, diag::error_bad_receiver_type, 306 RExpr->getType().getAsString()); 307 return true; 308 } 309 ClassDecl = OCIReceiver->getDecl(); 310 // FIXME: consider using InstanceMethodPool, since it will be faster 311 // than the following method (which can do *many* linear searches). The 312 // idea is to add class info to InstanceMethodPool... 313 Method = ClassDecl->lookupInstanceMethod(Sel); 314 } 315 if (!Method) { 316 // If we have an implementation in scope, check "private" methods. 317 if (ClassDecl) 318 if (ObjCImplementationDecl *ImpDecl = 319 ObjCImplementations[ClassDecl->getIdentifier()]) 320 Method = ImpDecl->getInstanceMethod(Sel); 321 // If we still haven't found a method, look in the global pool. This 322 // behavior isn't very desirable, however we need it for GCC 323 // compatibility. 324 if (!Method) 325 Method = InstanceMethodPool[Sel].Method; 326 } 327 if (!Method) { 328 Diag(lbrac, diag::warn_method_not_found, std::string("-"), Sel.getName(), 329 SourceRange(lbrac, rbrac)); 330 returnType = Context.getObjCIdType(); 331 } else { 332 returnType = Method->getResultType(); 333 if (Sel.getNumArgs()) 334 if (CheckMessageArgumentTypes(ArgExprs, Sel.getNumArgs(), Method)) 335 return true; 336 } 337 } 338 return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, 339 ArgExprs, NumArgs); 340} 341 342//===----------------------------------------------------------------------===// 343// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. 344//===----------------------------------------------------------------------===// 345 346/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the 347/// inheritance hierarchy of 'rProto'. 348static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, 349 ObjCProtocolDecl *rProto) { 350 if (lProto == rProto) 351 return true; 352 ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols(); 353 for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++) 354 if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i])) 355 return true; 356 return false; 357} 358 359/// ClassImplementsProtocol - Checks that 'lProto' protocol 360/// has been implemented in IDecl class, its super class or categories (if 361/// lookupCategory is true). 362static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, 363 ObjCInterfaceDecl *IDecl, 364 bool lookupCategory, 365 bool RHSIsQualifiedID = false) { 366 367 // 1st, look up the class. 368 ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); 369 for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { 370 if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 371 return true; 372 // This is dubious and is added to be compatible with gcc. 373 // In gcc, it is also allowed assigning a protocol-qualified 'id' 374 // type to a LHS object when protocol in qualified LHS is in list 375 // of protocols in the rhs 'id' object. This IMO, should be a bug. 376 // FIXME: Treat this as an extension, and flag this as an error when 377 // GCC extensions are not enabled. 378 else if (RHSIsQualifiedID && 379 ProtocolCompatibleWithProtocol(protoList[i], lProto)) 380 return true; 381 } 382 383 // 2nd, look up the category. 384 if (lookupCategory) 385 for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; 386 CDecl = CDecl->getNextClassCategory()) { 387 protoList = CDecl->getReferencedProtocols(); 388 for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { 389 if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) 390 return true; 391 } 392 } 393 394 // 3rd, look up the super class(s) 395 if (IDecl->getSuperClass()) 396 return 397 ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory, 398 RHSIsQualifiedID); 399 400 return false; 401} 402 403/// ObjCQualifiedIdTypesAreCompatible - We know that one of lhs/rhs is an 404/// ObjCQualifiedIDType. 405bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, 406 bool compare) { 407 // Allow id<P..> and an 'id' or void* type in all cases. 408 if (const PointerType *PT = lhs->getAsPointerType()) { 409 QualType PointeeTy = PT->getPointeeType(); 410 if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 411 return true; 412 } else if (const PointerType *PT = rhs->getAsPointerType()) { 413 QualType PointeeTy = PT->getPointeeType(); 414 if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) 415 return true; 416 } 417 418 if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { 419 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 420 const ObjCQualifiedInterfaceType *rhsQI = 0; 421 QualType rtype; 422 423 if (!rhsQID) { 424 // Not comparing two ObjCQualifiedIdType's? 425 if (!rhs->isPointerType()) return false; 426 427 rtype = rhs->getAsPointerType()->getPointeeType(); 428 rhsQI = rtype->getAsObjCQualifiedInterfaceType(); 429 if (rhsQI == 0) { 430 // If the RHS is a unqualified interface pointer "NSString*", 431 // make sure we check the class hierarchy. 432 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 433 ObjCInterfaceDecl *rhsID = IT->getDecl(); 434 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 435 // when comparing an id<P> on lhs with a static type on rhs, 436 // see if static class implements all of id's protocols, directly or 437 // through its super class and categories. 438 if (!ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) 439 return false; 440 } 441 return true; 442 } 443 } 444 } 445 446 ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; 447 if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). 448 RHSProtoI = rhsQI->qual_begin(); 449 RHSProtoE = rhsQI->qual_end(); 450 } else if (rhsQID) { // We have a qualified id (e.g. "id<Proto> *"). 451 RHSProtoI = rhsQID->qual_begin(); 452 RHSProtoE = rhsQID->qual_end(); 453 } else { 454 return false; 455 } 456 457 for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { 458 ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); 459 bool match = false; 460 461 // when comparing an id<P> on lhs with a static type on rhs, 462 // see if static class implements all of id's protocols, directly or 463 // through its super class and categories. 464 for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { 465 ObjCProtocolDecl *rhsProto = *RHSProtoI; 466 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 467 compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 468 match = true; 469 break; 470 } 471 } 472 if (rhsQI) { 473 // If the RHS is a qualified interface pointer "NSString<P>*", 474 // make sure we check the class hierarchy. 475 if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { 476 ObjCInterfaceDecl *rhsID = IT->getDecl(); 477 for (unsigned i = 0; i != lhsQID->getNumProtocols(); ++i) { 478 // when comparing an id<P> on lhs with a static type on rhs, 479 // see if static class implements all of id's protocols, directly or 480 // through its super class and categories. 481 if (ClassImplementsProtocol(lhsQID->getProtocols(i), rhsID, true)) { 482 match = true; 483 break; 484 } 485 } 486 } 487 } 488 if (!match) 489 return false; 490 } 491 492 return true; 493 } 494 495 const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); 496 assert(rhsQID && "One of the LHS/RHS should be id<x>"); 497 498 if (!lhs->isPointerType()) 499 return false; 500 501 QualType ltype = lhs->getAsPointerType()->getPointeeType(); 502 if (const ObjCQualifiedInterfaceType *lhsQI = 503 ltype->getAsObjCQualifiedInterfaceType()) { 504 ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); 505 ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); 506 for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { 507 bool match = false; 508 ObjCProtocolDecl *lhsProto = *LHSProtoI; 509 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 510 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 511 if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || 512 compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { 513 match = true; 514 break; 515 } 516 } 517 if (!match) 518 return false; 519 } 520 return true; 521 } 522 523 if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) { 524 // for static type vs. qualified 'id' type, check that class implements 525 // all of 'id's protocols. 526 ObjCInterfaceDecl *lhsID = IT->getDecl(); 527 for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { 528 ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); 529 if (!ClassImplementsProtocol(rhsProto, lhsID, compare, true)) 530 return false; 531 } 532 return true; 533 } 534 return false; 535} 536 537