1 //===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===// 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 expressions involving 11 // pseudo-object references. Pseudo-objects are conceptual objects 12 // whose storage is entirely abstract and all accesses to which are 13 // translated through some sort of abstraction barrier. 14 // 15 // For example, Objective-C objects can have "properties", either 16 // declared or undeclared. A property may be accessed by writing 17 // expr.prop 18 // where 'expr' is an r-value of Objective-C pointer type and 'prop' 19 // is the name of the property. If this expression is used in a context 20 // needing an r-value, it is treated as if it were a message-send 21 // of the associated 'getter' selector, typically: 22 // [expr prop] 23 // If it is used as the LHS of a simple assignment, it is treated 24 // as a message-send of the associated 'setter' selector, typically: 25 // [expr setProp: RHS] 26 // If it is used as the LHS of a compound assignment, or the operand 27 // of a unary increment or decrement, both are required; for example, 28 // 'expr.prop *= 100' would be translated to: 29 // [expr setProp: [expr prop] * 100] 30 // 31 //===----------------------------------------------------------------------===// 32 33 #include "clang/Sema/SemaInternal.h" 34 #include "clang/AST/ExprObjC.h" 35 #include "clang/Basic/CharInfo.h" 36 #include "clang/Lex/Preprocessor.h" 37 #include "clang/Sema/Initialization.h" 38 #include "clang/Sema/ScopeInfo.h" 39 #include "llvm/ADT/SmallString.h" 40 41 using namespace clang; 42 using namespace sema; 43 44 namespace { 45 // Basically just a very focused copy of TreeTransform. 46 template <class T> struct Rebuilder { 47 Sema &S; 48 Rebuilder(Sema &S) : S(S) {} 49 50 T &getDerived() { return static_cast<T&>(*this); } 51 52 Expr *rebuild(Expr *e) { 53 // Fast path: nothing to look through. 54 if (typename T::specific_type *specific 55 = dyn_cast<typename T::specific_type>(e)) 56 return getDerived().rebuildSpecific(specific); 57 58 // Otherwise, we should look through and rebuild anything that 59 // IgnoreParens would. 60 61 if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { 62 e = rebuild(parens->getSubExpr()); 63 return new (S.Context) ParenExpr(parens->getLParen(), 64 parens->getRParen(), 65 e); 66 } 67 68 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { 69 assert(uop->getOpcode() == UO_Extension); 70 e = rebuild(uop->getSubExpr()); 71 return new (S.Context) UnaryOperator(e, uop->getOpcode(), 72 uop->getType(), 73 uop->getValueKind(), 74 uop->getObjectKind(), 75 uop->getOperatorLoc()); 76 } 77 78 if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 79 assert(!gse->isResultDependent()); 80 unsigned resultIndex = gse->getResultIndex(); 81 unsigned numAssocs = gse->getNumAssocs(); 82 83 SmallVector<Expr*, 8> assocs(numAssocs); 84 SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs); 85 86 for (unsigned i = 0; i != numAssocs; ++i) { 87 Expr *assoc = gse->getAssocExpr(i); 88 if (i == resultIndex) assoc = rebuild(assoc); 89 assocs[i] = assoc; 90 assocTypes[i] = gse->getAssocTypeSourceInfo(i); 91 } 92 93 return new (S.Context) GenericSelectionExpr(S.Context, 94 gse->getGenericLoc(), 95 gse->getControllingExpr(), 96 assocTypes, 97 assocs, 98 gse->getDefaultLoc(), 99 gse->getRParenLoc(), 100 gse->containsUnexpandedParameterPack(), 101 resultIndex); 102 } 103 104 llvm_unreachable("bad expression to rebuild!"); 105 } 106 }; 107 108 struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { 109 Expr *NewBase; 110 ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) 111 : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} 112 113 typedef ObjCPropertyRefExpr specific_type; 114 Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { 115 // Fortunately, the constraint that we're rebuilding something 116 // with a base limits the number of cases here. 117 assert(refExpr->isObjectReceiver()); 118 119 if (refExpr->isExplicitProperty()) { 120 return new (S.Context) 121 ObjCPropertyRefExpr(refExpr->getExplicitProperty(), 122 refExpr->getType(), refExpr->getValueKind(), 123 refExpr->getObjectKind(), refExpr->getLocation(), 124 NewBase); 125 } 126 return new (S.Context) 127 ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), 128 refExpr->getImplicitPropertySetter(), 129 refExpr->getType(), refExpr->getValueKind(), 130 refExpr->getObjectKind(),refExpr->getLocation(), 131 NewBase); 132 } 133 }; 134 135 struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> { 136 Expr *NewBase; 137 Expr *NewKeyExpr; 138 ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr) 139 : Rebuilder<ObjCSubscriptRefRebuilder>(S), 140 NewBase(newBase), NewKeyExpr(newKeyExpr) {} 141 142 typedef ObjCSubscriptRefExpr specific_type; 143 Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) { 144 assert(refExpr->getBaseExpr()); 145 assert(refExpr->getKeyExpr()); 146 147 return new (S.Context) 148 ObjCSubscriptRefExpr(NewBase, 149 NewKeyExpr, 150 refExpr->getType(), refExpr->getValueKind(), 151 refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(), 152 refExpr->setAtIndexMethodDecl(), 153 refExpr->getRBracket()); 154 } 155 }; 156 157 class PseudoOpBuilder { 158 public: 159 Sema &S; 160 unsigned ResultIndex; 161 SourceLocation GenericLoc; 162 SmallVector<Expr *, 4> Semantics; 163 164 PseudoOpBuilder(Sema &S, SourceLocation genericLoc) 165 : S(S), ResultIndex(PseudoObjectExpr::NoResult), 166 GenericLoc(genericLoc) {} 167 168 virtual ~PseudoOpBuilder() {} 169 170 /// Add a normal semantic expression. 171 void addSemanticExpr(Expr *semantic) { 172 Semantics.push_back(semantic); 173 } 174 175 /// Add the 'result' semantic expression. 176 void addResultSemanticExpr(Expr *resultExpr) { 177 assert(ResultIndex == PseudoObjectExpr::NoResult); 178 ResultIndex = Semantics.size(); 179 Semantics.push_back(resultExpr); 180 } 181 182 ExprResult buildRValueOperation(Expr *op); 183 ExprResult buildAssignmentOperation(Scope *Sc, 184 SourceLocation opLoc, 185 BinaryOperatorKind opcode, 186 Expr *LHS, Expr *RHS); 187 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 188 UnaryOperatorKind opcode, 189 Expr *op); 190 191 virtual ExprResult complete(Expr *syntacticForm); 192 193 OpaqueValueExpr *capture(Expr *op); 194 OpaqueValueExpr *captureValueAsResult(Expr *op); 195 196 void setResultToLastSemantic() { 197 assert(ResultIndex == PseudoObjectExpr::NoResult); 198 ResultIndex = Semantics.size() - 1; 199 } 200 201 /// Return true if assignments have a non-void result. 202 bool CanCaptureValueOfType(QualType ty) { 203 assert(!ty->isIncompleteType()); 204 assert(!ty->isDependentType()); 205 206 if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl()) 207 return ClassDecl->isTriviallyCopyable(); 208 return true; 209 } 210 211 virtual Expr *rebuildAndCaptureObject(Expr *) = 0; 212 virtual ExprResult buildGet() = 0; 213 virtual ExprResult buildSet(Expr *, SourceLocation, 214 bool captureSetValueAsResult) = 0; 215 }; 216 217 /// A PseudoOpBuilder for Objective-C \@properties. 218 class ObjCPropertyOpBuilder : public PseudoOpBuilder { 219 ObjCPropertyRefExpr *RefExpr; 220 ObjCPropertyRefExpr *SyntacticRefExpr; 221 OpaqueValueExpr *InstanceReceiver; 222 ObjCMethodDecl *Getter; 223 224 ObjCMethodDecl *Setter; 225 Selector SetterSelector; 226 Selector GetterSelector; 227 228 public: 229 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : 230 PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), 231 SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) { 232 } 233 234 ExprResult buildRValueOperation(Expr *op); 235 ExprResult buildAssignmentOperation(Scope *Sc, 236 SourceLocation opLoc, 237 BinaryOperatorKind opcode, 238 Expr *LHS, Expr *RHS); 239 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 240 UnaryOperatorKind opcode, 241 Expr *op); 242 243 bool tryBuildGetOfReference(Expr *op, ExprResult &result); 244 bool findSetter(bool warn=true); 245 bool findGetter(); 246 247 Expr *rebuildAndCaptureObject(Expr *syntacticBase); 248 ExprResult buildGet(); 249 ExprResult buildSet(Expr *op, SourceLocation, bool); 250 ExprResult complete(Expr *SyntacticForm); 251 252 bool isWeakProperty() const; 253 }; 254 255 /// A PseudoOpBuilder for Objective-C array/dictionary indexing. 256 class ObjCSubscriptOpBuilder : public PseudoOpBuilder { 257 ObjCSubscriptRefExpr *RefExpr; 258 OpaqueValueExpr *InstanceBase; 259 OpaqueValueExpr *InstanceKey; 260 ObjCMethodDecl *AtIndexGetter; 261 Selector AtIndexGetterSelector; 262 263 ObjCMethodDecl *AtIndexSetter; 264 Selector AtIndexSetterSelector; 265 266 public: 267 ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) : 268 PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()), 269 RefExpr(refExpr), 270 InstanceBase(0), InstanceKey(0), 271 AtIndexGetter(0), AtIndexSetter(0) { } 272 273 ExprResult buildRValueOperation(Expr *op); 274 ExprResult buildAssignmentOperation(Scope *Sc, 275 SourceLocation opLoc, 276 BinaryOperatorKind opcode, 277 Expr *LHS, Expr *RHS); 278 Expr *rebuildAndCaptureObject(Expr *syntacticBase); 279 280 bool findAtIndexGetter(); 281 bool findAtIndexSetter(); 282 283 ExprResult buildGet(); 284 ExprResult buildSet(Expr *op, SourceLocation, bool); 285 }; 286 287 } 288 289 /// Capture the given expression in an OpaqueValueExpr. 290 OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { 291 // Make a new OVE whose source is the given expression. 292 OpaqueValueExpr *captured = 293 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), 294 e->getValueKind(), e->getObjectKind(), 295 e); 296 297 // Make sure we bind that in the semantics. 298 addSemanticExpr(captured); 299 return captured; 300 } 301 302 /// Capture the given expression as the result of this pseudo-object 303 /// operation. This routine is safe against expressions which may 304 /// already be captured. 305 /// 306 /// \returns the captured expression, which will be the 307 /// same as the input if the input was already captured 308 OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { 309 assert(ResultIndex == PseudoObjectExpr::NoResult); 310 311 // If the expression hasn't already been captured, just capture it 312 // and set the new semantic 313 if (!isa<OpaqueValueExpr>(e)) { 314 OpaqueValueExpr *cap = capture(e); 315 setResultToLastSemantic(); 316 return cap; 317 } 318 319 // Otherwise, it must already be one of our semantic expressions; 320 // set ResultIndex to its index. 321 unsigned index = 0; 322 for (;; ++index) { 323 assert(index < Semantics.size() && 324 "captured expression not found in semantics!"); 325 if (e == Semantics[index]) break; 326 } 327 ResultIndex = index; 328 return cast<OpaqueValueExpr>(e); 329 } 330 331 /// The routine which creates the final PseudoObjectExpr. 332 ExprResult PseudoOpBuilder::complete(Expr *syntactic) { 333 return PseudoObjectExpr::Create(S.Context, syntactic, 334 Semantics, ResultIndex); 335 } 336 337 /// The main skeleton for building an r-value operation. 338 ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { 339 Expr *syntacticBase = rebuildAndCaptureObject(op); 340 341 ExprResult getExpr = buildGet(); 342 if (getExpr.isInvalid()) return ExprError(); 343 addResultSemanticExpr(getExpr.take()); 344 345 return complete(syntacticBase); 346 } 347 348 /// The basic skeleton for building a simple or compound 349 /// assignment operation. 350 ExprResult 351 PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 352 BinaryOperatorKind opcode, 353 Expr *LHS, Expr *RHS) { 354 assert(BinaryOperator::isAssignmentOp(opcode)); 355 356 Expr *syntacticLHS = rebuildAndCaptureObject(LHS); 357 OpaqueValueExpr *capturedRHS = capture(RHS); 358 359 Expr *syntactic; 360 361 ExprResult result; 362 if (opcode == BO_Assign) { 363 result = capturedRHS; 364 syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, 365 opcode, capturedRHS->getType(), 366 capturedRHS->getValueKind(), 367 OK_Ordinary, opcLoc, false); 368 } else { 369 ExprResult opLHS = buildGet(); 370 if (opLHS.isInvalid()) return ExprError(); 371 372 // Build an ordinary, non-compound operation. 373 BinaryOperatorKind nonCompound = 374 BinaryOperator::getOpForCompoundAssignment(opcode); 375 result = S.BuildBinOp(Sc, opcLoc, nonCompound, 376 opLHS.take(), capturedRHS); 377 if (result.isInvalid()) return ExprError(); 378 379 syntactic = 380 new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, 381 result.get()->getType(), 382 result.get()->getValueKind(), 383 OK_Ordinary, 384 opLHS.get()->getType(), 385 result.get()->getType(), 386 opcLoc, false); 387 } 388 389 // The result of the assignment, if not void, is the value set into 390 // the l-value. 391 result = buildSet(result.take(), opcLoc, /*captureSetValueAsResult*/ true); 392 if (result.isInvalid()) return ExprError(); 393 addSemanticExpr(result.take()); 394 395 return complete(syntactic); 396 } 397 398 /// The basic skeleton for building an increment or decrement 399 /// operation. 400 ExprResult 401 PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 402 UnaryOperatorKind opcode, 403 Expr *op) { 404 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 405 406 Expr *syntacticOp = rebuildAndCaptureObject(op); 407 408 // Load the value. 409 ExprResult result = buildGet(); 410 if (result.isInvalid()) return ExprError(); 411 412 QualType resultType = result.get()->getType(); 413 414 // That's the postfix result. 415 if (UnaryOperator::isPostfix(opcode) && CanCaptureValueOfType(resultType)) { 416 result = capture(result.take()); 417 setResultToLastSemantic(); 418 } 419 420 // Add or subtract a literal 1. 421 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); 422 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, 423 GenericLoc); 424 425 if (UnaryOperator::isIncrementOp(opcode)) { 426 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one); 427 } else { 428 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one); 429 } 430 if (result.isInvalid()) return ExprError(); 431 432 // Store that back into the result. The value stored is the result 433 // of a prefix operation. 434 result = buildSet(result.take(), opcLoc, UnaryOperator::isPrefix(opcode)); 435 if (result.isInvalid()) return ExprError(); 436 addSemanticExpr(result.take()); 437 438 UnaryOperator *syntactic = 439 new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, 440 VK_LValue, OK_Ordinary, opcLoc); 441 return complete(syntactic); 442 } 443 444 445 //===----------------------------------------------------------------------===// 446 // Objective-C @property and implicit property references 447 //===----------------------------------------------------------------------===// 448 449 /// Look up a method in the receiver type of an Objective-C property 450 /// reference. 451 static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 452 const ObjCPropertyRefExpr *PRE) { 453 if (PRE->isObjectReceiver()) { 454 const ObjCObjectPointerType *PT = 455 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 456 457 // Special case for 'self' in class method implementations. 458 if (PT->isObjCClassType() && 459 S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) { 460 // This cast is safe because isSelfExpr is only true within 461 // methods. 462 ObjCMethodDecl *method = 463 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); 464 return S.LookupMethodInObjectType(sel, 465 S.Context.getObjCInterfaceType(method->getClassInterface()), 466 /*instance*/ false); 467 } 468 469 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 470 } 471 472 if (PRE->isSuperReceiver()) { 473 if (const ObjCObjectPointerType *PT = 474 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 475 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 476 477 return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); 478 } 479 480 assert(PRE->isClassReceiver() && "Invalid expression"); 481 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 482 return S.LookupMethodInObjectType(sel, IT, false); 483 } 484 485 bool ObjCPropertyOpBuilder::isWeakProperty() const { 486 QualType T; 487 if (RefExpr->isExplicitProperty()) { 488 const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty(); 489 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) 490 return true; 491 492 T = Prop->getType(); 493 } else if (Getter) { 494 T = Getter->getResultType(); 495 } else { 496 return false; 497 } 498 499 return T.getObjCLifetime() == Qualifiers::OCL_Weak; 500 } 501 502 bool ObjCPropertyOpBuilder::findGetter() { 503 if (Getter) return true; 504 505 // For implicit properties, just trust the lookup we already did. 506 if (RefExpr->isImplicitProperty()) { 507 if ((Getter = RefExpr->getImplicitPropertyGetter())) { 508 GetterSelector = Getter->getSelector(); 509 return true; 510 } 511 else { 512 // Must build the getter selector the hard way. 513 ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter(); 514 assert(setter && "both setter and getter are null - cannot happen"); 515 IdentifierInfo *setterName = 516 setter->getSelector().getIdentifierInfoForSlot(0); 517 const char *compStr = setterName->getNameStart(); 518 compStr += 3; 519 IdentifierInfo *getterName = &S.Context.Idents.get(compStr); 520 GetterSelector = 521 S.PP.getSelectorTable().getNullarySelector(getterName); 522 return false; 523 524 } 525 } 526 527 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 528 Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); 529 return (Getter != 0); 530 } 531 532 /// Try to find the most accurate setter declaration for the property 533 /// reference. 534 /// 535 /// \return true if a setter was found, in which case Setter 536 bool ObjCPropertyOpBuilder::findSetter(bool warn) { 537 // For implicit properties, just trust the lookup we already did. 538 if (RefExpr->isImplicitProperty()) { 539 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 540 Setter = setter; 541 SetterSelector = setter->getSelector(); 542 return true; 543 } else { 544 IdentifierInfo *getterName = 545 RefExpr->getImplicitPropertyGetter()->getSelector() 546 .getIdentifierInfoForSlot(0); 547 SetterSelector = 548 SelectorTable::constructSetterName(S.PP.getIdentifierTable(), 549 S.PP.getSelectorTable(), 550 getterName); 551 return false; 552 } 553 } 554 555 // For explicit properties, this is more involved. 556 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 557 SetterSelector = prop->getSetterName(); 558 559 // Do a normal method lookup first. 560 if (ObjCMethodDecl *setter = 561 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 562 if (setter->isPropertyAccessor() && warn) 563 if (const ObjCInterfaceDecl *IFace = 564 dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { 565 const StringRef thisPropertyName(prop->getName()); 566 // Try flipping the case of the first character. 567 char front = thisPropertyName.front(); 568 front = isLowercase(front) ? toUppercase(front) : toLowercase(front); 569 SmallString<100> PropertyName = thisPropertyName; 570 PropertyName[0] = front; 571 IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); 572 if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember)) 573 if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) { 574 S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use) 575 << prop->getName() << prop1->getName() << setter->getSelector(); 576 S.Diag(prop->getLocation(), diag::note_property_declare); 577 S.Diag(prop1->getLocation(), diag::note_property_declare); 578 } 579 } 580 Setter = setter; 581 return true; 582 } 583 584 // That can fail in the somewhat crazy situation that we're 585 // type-checking a message send within the @interface declaration 586 // that declared the @property. But it's not clear that that's 587 // valuable to support. 588 589 return false; 590 } 591 592 /// Capture the base object of an Objective-C property expression. 593 Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 594 assert(InstanceReceiver == 0); 595 596 // If we have a base, capture it in an OVE and rebuild the syntactic 597 // form to use the OVE as its base. 598 if (RefExpr->isObjectReceiver()) { 599 InstanceReceiver = capture(RefExpr->getBase()); 600 601 syntacticBase = 602 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); 603 } 604 605 if (ObjCPropertyRefExpr * 606 refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens())) 607 SyntacticRefExpr = refE; 608 609 return syntacticBase; 610 } 611 612 /// Load from an Objective-C property reference. 613 ExprResult ObjCPropertyOpBuilder::buildGet() { 614 findGetter(); 615 assert(Getter); 616 617 if (SyntacticRefExpr) 618 SyntacticRefExpr->setIsMessagingGetter(); 619 620 QualType receiverType; 621 if (RefExpr->isClassReceiver()) { 622 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 623 } else if (RefExpr->isSuperReceiver()) { 624 receiverType = RefExpr->getSuperReceiverType(); 625 } else { 626 assert(InstanceReceiver); 627 receiverType = InstanceReceiver->getType(); 628 } 629 630 // Build a message-send. 631 ExprResult msg; 632 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 633 assert(InstanceReceiver || RefExpr->isSuperReceiver()); 634 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 635 GenericLoc, Getter->getSelector(), 636 Getter, MultiExprArg()); 637 } else { 638 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 639 GenericLoc, 640 Getter->getSelector(), Getter, 641 MultiExprArg()); 642 } 643 return msg; 644 } 645 646 /// Store to an Objective-C property reference. 647 /// 648 /// \param captureSetValueAsResult If true, capture the actual 649 /// value being set as the value of the property operation. 650 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 651 bool captureSetValueAsResult) { 652 bool hasSetter = findSetter(false); 653 assert(hasSetter); (void) hasSetter; 654 655 if (SyntacticRefExpr) 656 SyntacticRefExpr->setIsMessagingSetter(); 657 658 QualType receiverType; 659 if (RefExpr->isClassReceiver()) { 660 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 661 } else if (RefExpr->isSuperReceiver()) { 662 receiverType = RefExpr->getSuperReceiverType(); 663 } else { 664 assert(InstanceReceiver); 665 receiverType = InstanceReceiver->getType(); 666 } 667 668 // Use assignment constraints when possible; they give us better 669 // diagnostics. "When possible" basically means anything except a 670 // C++ class type. 671 if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) { 672 QualType paramType = (*Setter->param_begin())->getType(); 673 if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) { 674 ExprResult opResult = op; 675 Sema::AssignConvertType assignResult 676 = S.CheckSingleAssignmentConstraints(paramType, opResult); 677 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 678 op->getType(), opResult.get(), 679 Sema::AA_Assigning)) 680 return ExprError(); 681 682 op = opResult.take(); 683 assert(op && "successful assignment left argument invalid?"); 684 } 685 } 686 687 // Arguments. 688 Expr *args[] = { op }; 689 690 // Build a message-send. 691 ExprResult msg; 692 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 693 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 694 GenericLoc, SetterSelector, Setter, 695 MultiExprArg(args, 1)); 696 } else { 697 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 698 GenericLoc, 699 SetterSelector, Setter, 700 MultiExprArg(args, 1)); 701 } 702 703 if (!msg.isInvalid() && captureSetValueAsResult) { 704 ObjCMessageExpr *msgExpr = 705 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 706 Expr *arg = msgExpr->getArg(0); 707 if (CanCaptureValueOfType(arg->getType())) 708 msgExpr->setArg(0, captureValueAsResult(arg)); 709 } 710 711 return msg; 712 } 713 714 /// @property-specific behavior for doing lvalue-to-rvalue conversion. 715 ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 716 // Explicit properties always have getters, but implicit ones don't. 717 // Check that before proceeding. 718 if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) { 719 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 720 << RefExpr->getSourceRange(); 721 return ExprError(); 722 } 723 724 ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 725 if (result.isInvalid()) return ExprError(); 726 727 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 728 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 729 Getter, RefExpr->getLocation()); 730 731 // As a special case, if the method returns 'id', try to get 732 // a better type from the property. 733 if (RefExpr->isExplicitProperty() && result.get()->isRValue() && 734 result.get()->getType()->isObjCIdType()) { 735 QualType propType = RefExpr->getExplicitProperty()->getType(); 736 if (const ObjCObjectPointerType *ptr 737 = propType->getAs<ObjCObjectPointerType>()) { 738 if (!ptr->isObjCIdType()) 739 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 740 } 741 } 742 743 return result; 744 } 745 746 /// Try to build this as a call to a getter that returns a reference. 747 /// 748 /// \return true if it was possible, whether or not it actually 749 /// succeeded 750 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 751 ExprResult &result) { 752 if (!S.getLangOpts().CPlusPlus) return false; 753 754 findGetter(); 755 assert(Getter && "property has no setter and no getter!"); 756 757 // Only do this if the getter returns an l-value reference type. 758 QualType resultType = Getter->getResultType(); 759 if (!resultType->isLValueReferenceType()) return false; 760 761 result = buildRValueOperation(op); 762 return true; 763 } 764 765 /// @property-specific behavior for doing assignments. 766 ExprResult 767 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 768 SourceLocation opcLoc, 769 BinaryOperatorKind opcode, 770 Expr *LHS, Expr *RHS) { 771 assert(BinaryOperator::isAssignmentOp(opcode)); 772 773 // If there's no setter, we have no choice but to try to assign to 774 // the result of the getter. 775 if (!findSetter()) { 776 ExprResult result; 777 if (tryBuildGetOfReference(LHS, result)) { 778 if (result.isInvalid()) return ExprError(); 779 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); 780 } 781 782 // Otherwise, it's an error. 783 S.Diag(opcLoc, diag::err_nosetter_property_assignment) 784 << unsigned(RefExpr->isImplicitProperty()) 785 << SetterSelector 786 << LHS->getSourceRange() << RHS->getSourceRange(); 787 return ExprError(); 788 } 789 790 // If there is a setter, we definitely want to use it. 791 792 // Verify that we can do a compound assignment. 793 if (opcode != BO_Assign && !findGetter()) { 794 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 795 << LHS->getSourceRange() << RHS->getSourceRange(); 796 return ExprError(); 797 } 798 799 ExprResult result = 800 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 801 if (result.isInvalid()) return ExprError(); 802 803 // Various warnings about property assignments in ARC. 804 if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) { 805 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 806 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 807 } 808 809 return result; 810 } 811 812 /// @property-specific behavior for doing increments and decrements. 813 ExprResult 814 ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 815 UnaryOperatorKind opcode, 816 Expr *op) { 817 // If there's no setter, we have no choice but to try to assign to 818 // the result of the getter. 819 if (!findSetter()) { 820 ExprResult result; 821 if (tryBuildGetOfReference(op, result)) { 822 if (result.isInvalid()) return ExprError(); 823 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); 824 } 825 826 // Otherwise, it's an error. 827 S.Diag(opcLoc, diag::err_nosetter_property_incdec) 828 << unsigned(RefExpr->isImplicitProperty()) 829 << unsigned(UnaryOperator::isDecrementOp(opcode)) 830 << SetterSelector 831 << op->getSourceRange(); 832 return ExprError(); 833 } 834 835 // If there is a setter, we definitely want to use it. 836 837 // We also need a getter. 838 if (!findGetter()) { 839 assert(RefExpr->isImplicitProperty()); 840 S.Diag(opcLoc, diag::err_nogetter_property_incdec) 841 << unsigned(UnaryOperator::isDecrementOp(opcode)) 842 << GetterSelector 843 << op->getSourceRange(); 844 return ExprError(); 845 } 846 847 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 848 } 849 850 ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { 851 if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) { 852 DiagnosticsEngine::Level Level = 853 S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, 854 SyntacticForm->getLocStart()); 855 if (Level != DiagnosticsEngine::Ignored) 856 S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, 857 SyntacticRefExpr->isMessagingGetter()); 858 } 859 860 return PseudoOpBuilder::complete(SyntacticForm); 861 } 862 863 // ObjCSubscript build stuff. 864 // 865 866 /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue 867 /// conversion. 868 /// FIXME. Remove this routine if it is proven that no additional 869 /// specifity is needed. 870 ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) { 871 ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 872 if (result.isInvalid()) return ExprError(); 873 return result; 874 } 875 876 /// objective-c subscripting-specific behavior for doing assignments. 877 ExprResult 878 ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc, 879 SourceLocation opcLoc, 880 BinaryOperatorKind opcode, 881 Expr *LHS, Expr *RHS) { 882 assert(BinaryOperator::isAssignmentOp(opcode)); 883 // There must be a method to do the Index'ed assignment. 884 if (!findAtIndexSetter()) 885 return ExprError(); 886 887 // Verify that we can do a compound assignment. 888 if (opcode != BO_Assign && !findAtIndexGetter()) 889 return ExprError(); 890 891 ExprResult result = 892 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 893 if (result.isInvalid()) return ExprError(); 894 895 // Various warnings about objc Index'ed assignments in ARC. 896 if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) { 897 S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS); 898 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 899 } 900 901 return result; 902 } 903 904 /// Capture the base object of an Objective-C Index'ed expression. 905 Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 906 assert(InstanceBase == 0); 907 908 // Capture base expression in an OVE and rebuild the syntactic 909 // form to use the OVE as its base expression. 910 InstanceBase = capture(RefExpr->getBaseExpr()); 911 InstanceKey = capture(RefExpr->getKeyExpr()); 912 913 syntacticBase = 914 ObjCSubscriptRefRebuilder(S, InstanceBase, 915 InstanceKey).rebuild(syntacticBase); 916 917 return syntacticBase; 918 } 919 920 /// CheckSubscriptingKind - This routine decide what type 921 /// of indexing represented by "FromE" is being done. 922 Sema::ObjCSubscriptKind 923 Sema::CheckSubscriptingKind(Expr *FromE) { 924 // If the expression already has integral or enumeration type, we're golden. 925 QualType T = FromE->getType(); 926 if (T->isIntegralOrEnumerationType()) 927 return OS_Array; 928 929 // If we don't have a class type in C++, there's no way we can get an 930 // expression of integral or enumeration type. 931 const RecordType *RecordTy = T->getAs<RecordType>(); 932 if (!RecordTy && T->isObjCObjectPointerType()) 933 // All other scalar cases are assumed to be dictionary indexing which 934 // caller handles, with diagnostics if needed. 935 return OS_Dictionary; 936 if (!getLangOpts().CPlusPlus || 937 !RecordTy || RecordTy->isIncompleteType()) { 938 // No indexing can be done. Issue diagnostics and quit. 939 const Expr *IndexExpr = FromE->IgnoreParenImpCasts(); 940 if (isa<StringLiteral>(IndexExpr)) 941 Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer) 942 << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@"); 943 else 944 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 945 << T; 946 return OS_Error; 947 } 948 949 // We must have a complete class type. 950 if (RequireCompleteType(FromE->getExprLoc(), T, 951 diag::err_objc_index_incomplete_class_type, FromE)) 952 return OS_Error; 953 954 // Look for a conversion to an integral, enumeration type, or 955 // objective-C pointer type. 956 UnresolvedSet<4> ViableConversions; 957 UnresolvedSet<4> ExplicitConversions; 958 std::pair<CXXRecordDecl::conversion_iterator, 959 CXXRecordDecl::conversion_iterator> Conversions 960 = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); 961 962 int NoIntegrals=0, NoObjCIdPointers=0; 963 SmallVector<CXXConversionDecl *, 4> ConversionDecls; 964 965 for (CXXRecordDecl::conversion_iterator 966 I = Conversions.first, E = Conversions.second; I != E; ++I) { 967 if (CXXConversionDecl *Conversion 968 = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { 969 QualType CT = Conversion->getConversionType().getNonReferenceType(); 970 if (CT->isIntegralOrEnumerationType()) { 971 ++NoIntegrals; 972 ConversionDecls.push_back(Conversion); 973 } 974 else if (CT->isObjCIdType() ||CT->isBlockPointerType()) { 975 ++NoObjCIdPointers; 976 ConversionDecls.push_back(Conversion); 977 } 978 } 979 } 980 if (NoIntegrals ==1 && NoObjCIdPointers == 0) 981 return OS_Array; 982 if (NoIntegrals == 0 && NoObjCIdPointers == 1) 983 return OS_Dictionary; 984 if (NoIntegrals == 0 && NoObjCIdPointers == 0) { 985 // No conversion function was found. Issue diagnostic and return. 986 Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion) 987 << FromE->getType(); 988 return OS_Error; 989 } 990 Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion) 991 << FromE->getType(); 992 for (unsigned int i = 0; i < ConversionDecls.size(); i++) 993 Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at); 994 995 return OS_Error; 996 } 997 998 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF 999 /// objects used as dictionary subscript key objects. 1000 static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, 1001 Expr *Key) { 1002 if (ContainerT.isNull()) 1003 return; 1004 // dictionary subscripting. 1005 // - (id)objectForKeyedSubscript:(id)key; 1006 IdentifierInfo *KeyIdents[] = { 1007 &S.Context.Idents.get("objectForKeyedSubscript") 1008 }; 1009 Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1010 ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT, 1011 true /*instance*/); 1012 if (!Getter) 1013 return; 1014 QualType T = Getter->param_begin()[0]->getType(); 1015 S.CheckObjCARCConversion(Key->getSourceRange(), 1016 T, Key, Sema::CCK_ImplicitConversion); 1017 } 1018 1019 bool ObjCSubscriptOpBuilder::findAtIndexGetter() { 1020 if (AtIndexGetter) 1021 return true; 1022 1023 Expr *BaseExpr = RefExpr->getBaseExpr(); 1024 QualType BaseT = BaseExpr->getType(); 1025 1026 QualType ResultType; 1027 if (const ObjCObjectPointerType *PTy = 1028 BaseT->getAs<ObjCObjectPointerType>()) { 1029 ResultType = PTy->getPointeeType(); 1030 if (const ObjCObjectType *iQFaceTy = 1031 ResultType->getAsObjCQualifiedInterfaceType()) 1032 ResultType = iQFaceTy->getBaseType(); 1033 } 1034 Sema::ObjCSubscriptKind Res = 1035 S.CheckSubscriptingKind(RefExpr->getKeyExpr()); 1036 if (Res == Sema::OS_Error) { 1037 if (S.getLangOpts().ObjCAutoRefCount) 1038 CheckKeyForObjCARCConversion(S, ResultType, 1039 RefExpr->getKeyExpr()); 1040 return false; 1041 } 1042 bool arrayRef = (Res == Sema::OS_Array); 1043 1044 if (ResultType.isNull()) { 1045 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 1046 << BaseExpr->getType() << arrayRef; 1047 return false; 1048 } 1049 if (!arrayRef) { 1050 // dictionary subscripting. 1051 // - (id)objectForKeyedSubscript:(id)key; 1052 IdentifierInfo *KeyIdents[] = { 1053 &S.Context.Idents.get("objectForKeyedSubscript") 1054 }; 1055 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1056 } 1057 else { 1058 // - (id)objectAtIndexedSubscript:(size_t)index; 1059 IdentifierInfo *KeyIdents[] = { 1060 &S.Context.Idents.get("objectAtIndexedSubscript") 1061 }; 1062 1063 AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); 1064 } 1065 1066 AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType, 1067 true /*instance*/); 1068 bool receiverIdType = (BaseT->isObjCIdType() || 1069 BaseT->isObjCQualifiedIdType()); 1070 1071 if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { 1072 AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), 1073 SourceLocation(), AtIndexGetterSelector, 1074 S.Context.getObjCIdType() /*ReturnType*/, 1075 0 /*TypeSourceInfo */, 1076 S.Context.getTranslationUnitDecl(), 1077 true /*Instance*/, false/*isVariadic*/, 1078 /*isPropertyAccessor=*/false, 1079 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 1080 ObjCMethodDecl::Required, 1081 false); 1082 ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, 1083 SourceLocation(), SourceLocation(), 1084 arrayRef ? &S.Context.Idents.get("index") 1085 : &S.Context.Idents.get("key"), 1086 arrayRef ? S.Context.UnsignedLongTy 1087 : S.Context.getObjCIdType(), 1088 /*TInfo=*/0, 1089 SC_None, 1090 SC_None, 1091 0); 1092 AtIndexGetter->setMethodParams(S.Context, Argument, 1093 ArrayRef<SourceLocation>()); 1094 } 1095 1096 if (!AtIndexGetter) { 1097 if (!receiverIdType) { 1098 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found) 1099 << BaseExpr->getType() << 0 << arrayRef; 1100 return false; 1101 } 1102 AtIndexGetter = 1103 S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector, 1104 RefExpr->getSourceRange(), 1105 true, false); 1106 } 1107 1108 if (AtIndexGetter) { 1109 QualType T = AtIndexGetter->param_begin()[0]->getType(); 1110 if ((arrayRef && !T->isIntegralOrEnumerationType()) || 1111 (!arrayRef && !T->isObjCObjectPointerType())) { 1112 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1113 arrayRef ? diag::err_objc_subscript_index_type 1114 : diag::err_objc_subscript_key_type) << T; 1115 S.Diag(AtIndexGetter->param_begin()[0]->getLocation(), 1116 diag::note_parameter_type) << T; 1117 return false; 1118 } 1119 QualType R = AtIndexGetter->getResultType(); 1120 if (!R->isObjCObjectPointerType()) { 1121 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1122 diag::err_objc_indexing_method_result_type) << R << arrayRef; 1123 S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) << 1124 AtIndexGetter->getDeclName(); 1125 } 1126 } 1127 return true; 1128 } 1129 1130 bool ObjCSubscriptOpBuilder::findAtIndexSetter() { 1131 if (AtIndexSetter) 1132 return true; 1133 1134 Expr *BaseExpr = RefExpr->getBaseExpr(); 1135 QualType BaseT = BaseExpr->getType(); 1136 1137 QualType ResultType; 1138 if (const ObjCObjectPointerType *PTy = 1139 BaseT->getAs<ObjCObjectPointerType>()) { 1140 ResultType = PTy->getPointeeType(); 1141 if (const ObjCObjectType *iQFaceTy = 1142 ResultType->getAsObjCQualifiedInterfaceType()) 1143 ResultType = iQFaceTy->getBaseType(); 1144 } 1145 1146 Sema::ObjCSubscriptKind Res = 1147 S.CheckSubscriptingKind(RefExpr->getKeyExpr()); 1148 if (Res == Sema::OS_Error) { 1149 if (S.getLangOpts().ObjCAutoRefCount) 1150 CheckKeyForObjCARCConversion(S, ResultType, 1151 RefExpr->getKeyExpr()); 1152 return false; 1153 } 1154 bool arrayRef = (Res == Sema::OS_Array); 1155 1156 if (ResultType.isNull()) { 1157 S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type) 1158 << BaseExpr->getType() << arrayRef; 1159 return false; 1160 } 1161 1162 if (!arrayRef) { 1163 // dictionary subscripting. 1164 // - (void)setObject:(id)object forKeyedSubscript:(id)key; 1165 IdentifierInfo *KeyIdents[] = { 1166 &S.Context.Idents.get("setObject"), 1167 &S.Context.Idents.get("forKeyedSubscript") 1168 }; 1169 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 1170 } 1171 else { 1172 // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 1173 IdentifierInfo *KeyIdents[] = { 1174 &S.Context.Idents.get("setObject"), 1175 &S.Context.Idents.get("atIndexedSubscript") 1176 }; 1177 AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents); 1178 } 1179 AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType, 1180 true /*instance*/); 1181 1182 bool receiverIdType = (BaseT->isObjCIdType() || 1183 BaseT->isObjCQualifiedIdType()); 1184 1185 if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) { 1186 TypeSourceInfo *ResultTInfo = 0; 1187 QualType ReturnType = S.Context.VoidTy; 1188 AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), 1189 SourceLocation(), AtIndexSetterSelector, 1190 ReturnType, 1191 ResultTInfo, 1192 S.Context.getTranslationUnitDecl(), 1193 true /*Instance*/, false/*isVariadic*/, 1194 /*isPropertyAccessor=*/false, 1195 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 1196 ObjCMethodDecl::Required, 1197 false); 1198 SmallVector<ParmVarDecl *, 2> Params; 1199 ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter, 1200 SourceLocation(), SourceLocation(), 1201 &S.Context.Idents.get("object"), 1202 S.Context.getObjCIdType(), 1203 /*TInfo=*/0, 1204 SC_None, 1205 SC_None, 1206 0); 1207 Params.push_back(object); 1208 ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, 1209 SourceLocation(), SourceLocation(), 1210 arrayRef ? &S.Context.Idents.get("index") 1211 : &S.Context.Idents.get("key"), 1212 arrayRef ? S.Context.UnsignedLongTy 1213 : S.Context.getObjCIdType(), 1214 /*TInfo=*/0, 1215 SC_None, 1216 SC_None, 1217 0); 1218 Params.push_back(key); 1219 AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>()); 1220 } 1221 1222 if (!AtIndexSetter) { 1223 if (!receiverIdType) { 1224 S.Diag(BaseExpr->getExprLoc(), 1225 diag::err_objc_subscript_method_not_found) 1226 << BaseExpr->getType() << 1 << arrayRef; 1227 return false; 1228 } 1229 AtIndexSetter = 1230 S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector, 1231 RefExpr->getSourceRange(), 1232 true, false); 1233 } 1234 1235 bool err = false; 1236 if (AtIndexSetter && arrayRef) { 1237 QualType T = AtIndexSetter->param_begin()[1]->getType(); 1238 if (!T->isIntegralOrEnumerationType()) { 1239 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1240 diag::err_objc_subscript_index_type) << T; 1241 S.Diag(AtIndexSetter->param_begin()[1]->getLocation(), 1242 diag::note_parameter_type) << T; 1243 err = true; 1244 } 1245 T = AtIndexSetter->param_begin()[0]->getType(); 1246 if (!T->isObjCObjectPointerType()) { 1247 S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 1248 diag::err_objc_subscript_object_type) << T << arrayRef; 1249 S.Diag(AtIndexSetter->param_begin()[0]->getLocation(), 1250 diag::note_parameter_type) << T; 1251 err = true; 1252 } 1253 } 1254 else if (AtIndexSetter && !arrayRef) 1255 for (unsigned i=0; i <2; i++) { 1256 QualType T = AtIndexSetter->param_begin()[i]->getType(); 1257 if (!T->isObjCObjectPointerType()) { 1258 if (i == 1) 1259 S.Diag(RefExpr->getKeyExpr()->getExprLoc(), 1260 diag::err_objc_subscript_key_type) << T; 1261 else 1262 S.Diag(RefExpr->getBaseExpr()->getExprLoc(), 1263 diag::err_objc_subscript_dic_object_type) << T; 1264 S.Diag(AtIndexSetter->param_begin()[i]->getLocation(), 1265 diag::note_parameter_type) << T; 1266 err = true; 1267 } 1268 } 1269 1270 return !err; 1271 } 1272 1273 // Get the object at "Index" position in the container. 1274 // [BaseExpr objectAtIndexedSubscript : IndexExpr]; 1275 ExprResult ObjCSubscriptOpBuilder::buildGet() { 1276 if (!findAtIndexGetter()) 1277 return ExprError(); 1278 1279 QualType receiverType = InstanceBase->getType(); 1280 1281 // Build a message-send. 1282 ExprResult msg; 1283 Expr *Index = InstanceKey; 1284 1285 // Arguments. 1286 Expr *args[] = { Index }; 1287 assert(InstanceBase); 1288 msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, 1289 GenericLoc, 1290 AtIndexGetterSelector, AtIndexGetter, 1291 MultiExprArg(args, 1)); 1292 return msg; 1293 } 1294 1295 /// Store into the container the "op" object at "Index"'ed location 1296 /// by building this messaging expression: 1297 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; 1298 /// \param captureSetValueAsResult If true, capture the actual 1299 /// value being set as the value of the property operation. 1300 ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 1301 bool captureSetValueAsResult) { 1302 if (!findAtIndexSetter()) 1303 return ExprError(); 1304 1305 QualType receiverType = InstanceBase->getType(); 1306 Expr *Index = InstanceKey; 1307 1308 // Arguments. 1309 Expr *args[] = { op, Index }; 1310 1311 // Build a message-send. 1312 ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType, 1313 GenericLoc, 1314 AtIndexSetterSelector, 1315 AtIndexSetter, 1316 MultiExprArg(args, 2)); 1317 1318 if (!msg.isInvalid() && captureSetValueAsResult) { 1319 ObjCMessageExpr *msgExpr = 1320 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 1321 Expr *arg = msgExpr->getArg(0); 1322 if (CanCaptureValueOfType(arg->getType())) 1323 msgExpr->setArg(0, captureValueAsResult(arg)); 1324 } 1325 1326 return msg; 1327 } 1328 1329 //===----------------------------------------------------------------------===// 1330 // General Sema routines. 1331 //===----------------------------------------------------------------------===// 1332 1333 ExprResult Sema::checkPseudoObjectRValue(Expr *E) { 1334 Expr *opaqueRef = E->IgnoreParens(); 1335 if (ObjCPropertyRefExpr *refExpr 1336 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1337 ObjCPropertyOpBuilder builder(*this, refExpr); 1338 return builder.buildRValueOperation(E); 1339 } 1340 else if (ObjCSubscriptRefExpr *refExpr 1341 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1342 ObjCSubscriptOpBuilder builder(*this, refExpr); 1343 return builder.buildRValueOperation(E); 1344 } else { 1345 llvm_unreachable("unknown pseudo-object kind!"); 1346 } 1347 } 1348 1349 /// Check an increment or decrement of a pseudo-object expression. 1350 ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, 1351 UnaryOperatorKind opcode, Expr *op) { 1352 // Do nothing if the operand is dependent. 1353 if (op->isTypeDependent()) 1354 return new (Context) UnaryOperator(op, opcode, Context.DependentTy, 1355 VK_RValue, OK_Ordinary, opcLoc); 1356 1357 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 1358 Expr *opaqueRef = op->IgnoreParens(); 1359 if (ObjCPropertyRefExpr *refExpr 1360 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1361 ObjCPropertyOpBuilder builder(*this, refExpr); 1362 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 1363 } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) { 1364 Diag(opcLoc, diag::err_illegal_container_subscripting_op); 1365 return ExprError(); 1366 } else { 1367 llvm_unreachable("unknown pseudo-object kind!"); 1368 } 1369 } 1370 1371 ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 1372 BinaryOperatorKind opcode, 1373 Expr *LHS, Expr *RHS) { 1374 // Do nothing if either argument is dependent. 1375 if (LHS->isTypeDependent() || RHS->isTypeDependent()) 1376 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, 1377 VK_RValue, OK_Ordinary, opcLoc, false); 1378 1379 // Filter out non-overload placeholder types in the RHS. 1380 if (RHS->getType()->isNonOverloadPlaceholderType()) { 1381 ExprResult result = CheckPlaceholderExpr(RHS); 1382 if (result.isInvalid()) return ExprError(); 1383 RHS = result.take(); 1384 } 1385 1386 Expr *opaqueRef = LHS->IgnoreParens(); 1387 if (ObjCPropertyRefExpr *refExpr 1388 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1389 ObjCPropertyOpBuilder builder(*this, refExpr); 1390 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 1391 } else if (ObjCSubscriptRefExpr *refExpr 1392 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1393 ObjCSubscriptOpBuilder builder(*this, refExpr); 1394 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 1395 } else { 1396 llvm_unreachable("unknown pseudo-object kind!"); 1397 } 1398 } 1399 1400 /// Given a pseudo-object reference, rebuild it without the opaque 1401 /// values. Basically, undo the behavior of rebuildAndCaptureObject. 1402 /// This should never operate in-place. 1403 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { 1404 Expr *opaqueRef = E->IgnoreParens(); 1405 if (ObjCPropertyRefExpr *refExpr 1406 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 1407 // Class and super property references don't have opaque values in them. 1408 if (refExpr->isClassReceiver() || refExpr->isSuperReceiver()) 1409 return E; 1410 1411 assert(refExpr->isObjectReceiver() && "Unknown receiver kind?"); 1412 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); 1413 return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); 1414 } else if (ObjCSubscriptRefExpr *refExpr 1415 = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) { 1416 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr()); 1417 OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr()); 1418 return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(), 1419 keyOVE->getSourceExpr()).rebuild(E); 1420 } else { 1421 llvm_unreachable("unknown pseudo-object kind!"); 1422 } 1423 } 1424 1425 /// Given a pseudo-object expression, recreate what it looks like 1426 /// syntactically without the attendant OpaqueValueExprs. 1427 /// 1428 /// This is a hack which should be removed when TreeTransform is 1429 /// capable of rebuilding a tree without stripping implicit 1430 /// operations. 1431 Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { 1432 Expr *syntax = E->getSyntacticForm(); 1433 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { 1434 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); 1435 return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), 1436 uop->getValueKind(), uop->getObjectKind(), 1437 uop->getOperatorLoc()); 1438 } else if (CompoundAssignOperator *cop 1439 = dyn_cast<CompoundAssignOperator>(syntax)) { 1440 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); 1441 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); 1442 return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), 1443 cop->getType(), 1444 cop->getValueKind(), 1445 cop->getObjectKind(), 1446 cop->getComputationLHSType(), 1447 cop->getComputationResultType(), 1448 cop->getOperatorLoc(), false); 1449 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { 1450 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); 1451 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); 1452 return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), 1453 bop->getType(), bop->getValueKind(), 1454 bop->getObjectKind(), 1455 bop->getOperatorLoc(), false); 1456 } else { 1457 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); 1458 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); 1459 } 1460 } 1461