SemaPseudoObject.cpp revision 8cacea57b6cd288f7578200e4884ab56bafc1a32
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/Sema/Initialization.h" 35#include "clang/AST/ExprObjC.h" 36#include "clang/Lex/Preprocessor.h" 37 38using namespace clang; 39using namespace sema; 40 41namespace { 42 // Basically just a very focused copy of TreeTransform. 43 template <class T> struct Rebuilder { 44 Sema &S; 45 Rebuilder(Sema &S) : S(S) {} 46 47 T &getDerived() { return static_cast<T&>(*this); } 48 49 Expr *rebuild(Expr *e) { 50 // Fast path: nothing to look through. 51 if (typename T::specific_type *specific 52 = dyn_cast<typename T::specific_type>(e)) 53 return getDerived().rebuildSpecific(specific); 54 55 // Otherwise, we should look through and rebuild anything that 56 // IgnoreParens would. 57 58 if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) { 59 e = rebuild(parens->getSubExpr()); 60 return new (S.Context) ParenExpr(parens->getLParen(), 61 parens->getRParen(), 62 e); 63 } 64 65 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { 66 assert(uop->getOpcode() == UO_Extension); 67 e = rebuild(uop->getSubExpr()); 68 return new (S.Context) UnaryOperator(e, uop->getOpcode(), 69 uop->getType(), 70 uop->getValueKind(), 71 uop->getObjectKind(), 72 uop->getOperatorLoc()); 73 } 74 75 if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) { 76 assert(!gse->isResultDependent()); 77 unsigned resultIndex = gse->getResultIndex(); 78 unsigned numAssocs = gse->getNumAssocs(); 79 80 SmallVector<Expr*, 8> assocs(numAssocs); 81 SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs); 82 83 for (unsigned i = 0; i != numAssocs; ++i) { 84 Expr *assoc = gse->getAssocExpr(i); 85 if (i == resultIndex) assoc = rebuild(assoc); 86 assocs[i] = assoc; 87 assocTypes[i] = gse->getAssocTypeSourceInfo(i); 88 } 89 90 return new (S.Context) GenericSelectionExpr(S.Context, 91 gse->getGenericLoc(), 92 gse->getControllingExpr(), 93 assocTypes.data(), 94 assocs.data(), 95 numAssocs, 96 gse->getDefaultLoc(), 97 gse->getRParenLoc(), 98 gse->containsUnexpandedParameterPack(), 99 resultIndex); 100 } 101 102 llvm_unreachable("bad expression to rebuild!"); 103 } 104 }; 105 106 struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> { 107 Expr *NewBase; 108 ObjCPropertyRefRebuilder(Sema &S, Expr *newBase) 109 : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {} 110 111 typedef ObjCPropertyRefExpr specific_type; 112 Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { 113 // Fortunately, the constraint that we're rebuilding something 114 // with a base limits the number of cases here. 115 assert(refExpr->getBase()); 116 117 if (refExpr->isExplicitProperty()) { 118 return new (S.Context) 119 ObjCPropertyRefExpr(refExpr->getExplicitProperty(), 120 refExpr->getType(), refExpr->getValueKind(), 121 refExpr->getObjectKind(), refExpr->getLocation(), 122 NewBase); 123 } 124 return new (S.Context) 125 ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(), 126 refExpr->getImplicitPropertySetter(), 127 refExpr->getType(), refExpr->getValueKind(), 128 refExpr->getObjectKind(),refExpr->getLocation(), 129 NewBase); 130 } 131 }; 132 133 class PseudoOpBuilder { 134 public: 135 Sema &S; 136 unsigned ResultIndex; 137 SourceLocation GenericLoc; 138 SmallVector<Expr *, 4> Semantics; 139 140 PseudoOpBuilder(Sema &S, SourceLocation genericLoc) 141 : S(S), ResultIndex(PseudoObjectExpr::NoResult), 142 GenericLoc(genericLoc) {} 143 144 /// Add a normal semantic expression. 145 void addSemanticExpr(Expr *semantic) { 146 Semantics.push_back(semantic); 147 } 148 149 /// Add the 'result' semantic expression. 150 void addResultSemanticExpr(Expr *resultExpr) { 151 assert(ResultIndex == PseudoObjectExpr::NoResult); 152 ResultIndex = Semantics.size(); 153 Semantics.push_back(resultExpr); 154 } 155 156 ExprResult buildRValueOperation(Expr *op); 157 ExprResult buildAssignmentOperation(Scope *Sc, 158 SourceLocation opLoc, 159 BinaryOperatorKind opcode, 160 Expr *LHS, Expr *RHS); 161 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 162 UnaryOperatorKind opcode, 163 Expr *op); 164 165 ExprResult complete(Expr *syntacticForm); 166 167 OpaqueValueExpr *capture(Expr *op); 168 OpaqueValueExpr *captureValueAsResult(Expr *op); 169 170 void setResultToLastSemantic() { 171 assert(ResultIndex == PseudoObjectExpr::NoResult); 172 ResultIndex = Semantics.size() - 1; 173 } 174 175 /// Return true if assignments have a non-void result. 176 virtual bool assignmentsHaveResult() { return true; } 177 178 virtual Expr *rebuildAndCaptureObject(Expr *) = 0; 179 virtual ExprResult buildGet() = 0; 180 virtual ExprResult buildSet(Expr *, SourceLocation, 181 bool captureSetValueAsResult) = 0; 182 183 protected: 184 ~PseudoOpBuilder() {} 185 }; 186 187 /// A PseudoOpBuilder for Objective-C @properties. 188 class ObjCPropertyOpBuilder : public PseudoOpBuilder { 189 ObjCPropertyRefExpr *RefExpr; 190 OpaqueValueExpr *InstanceReceiver; 191 ObjCMethodDecl *Getter; 192 193 ObjCMethodDecl *Setter; 194 Selector SetterSelector; 195 196 public: 197 ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) : 198 PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr), 199 InstanceReceiver(0), Getter(0), Setter(0) { 200 } 201 202 ExprResult buildRValueOperation(Expr *op); 203 ExprResult buildAssignmentOperation(Scope *Sc, 204 SourceLocation opLoc, 205 BinaryOperatorKind opcode, 206 Expr *LHS, Expr *RHS); 207 ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc, 208 UnaryOperatorKind opcode, 209 Expr *op); 210 211 bool tryBuildGetOfReference(Expr *op, ExprResult &result); 212 bool findSetter(); 213 bool findGetter(); 214 215 Expr *rebuildAndCaptureObject(Expr *syntacticBase); 216 ExprResult buildGet(); 217 ExprResult buildSet(Expr *op, SourceLocation, bool); 218 }; 219} 220 221/// Capture the given expression in an OpaqueValueExpr. 222OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { 223 // Make a new OVE whose source is the given expression. 224 OpaqueValueExpr *captured = 225 new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(), 226 e->getValueKind()); 227 captured->setSourceExpr(e); 228 229 // Make sure we bind that in the semantics. 230 addSemanticExpr(captured); 231 return captured; 232} 233 234/// Capture the given expression as the result of this pseudo-object 235/// operation. This routine is safe against expressions which may 236/// already be captured. 237/// 238/// \param Returns the captured expression, which will be the 239/// same as the input if the input was already captured 240OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { 241 assert(ResultIndex == PseudoObjectExpr::NoResult); 242 243 // If the expression hasn't already been captured, just capture it 244 // and set the new semantic 245 if (!isa<OpaqueValueExpr>(e)) { 246 OpaqueValueExpr *cap = capture(e); 247 setResultToLastSemantic(); 248 return cap; 249 } 250 251 // Otherwise, it must already be one of our semantic expressions; 252 // set ResultIndex to its index. 253 unsigned index = 0; 254 for (;; ++index) { 255 assert(index < Semantics.size() && 256 "captured expression not found in semantics!"); 257 if (e == Semantics[index]) break; 258 } 259 ResultIndex = index; 260 return cast<OpaqueValueExpr>(e); 261} 262 263/// The routine which creates the final PseudoObjectExpr. 264ExprResult PseudoOpBuilder::complete(Expr *syntactic) { 265 return PseudoObjectExpr::Create(S.Context, syntactic, 266 Semantics, ResultIndex); 267} 268 269/// The main skeleton for building an r-value operation. 270ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) { 271 Expr *syntacticBase = rebuildAndCaptureObject(op); 272 273 ExprResult getExpr = buildGet(); 274 if (getExpr.isInvalid()) return ExprError(); 275 addResultSemanticExpr(getExpr.take()); 276 277 return complete(syntacticBase); 278} 279 280/// The basic skeleton for building a simple or compound 281/// assignment operation. 282ExprResult 283PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, 284 BinaryOperatorKind opcode, 285 Expr *LHS, Expr *RHS) { 286 assert(BinaryOperator::isAssignmentOp(opcode)); 287 288 Expr *syntacticLHS = rebuildAndCaptureObject(LHS); 289 OpaqueValueExpr *capturedRHS = capture(RHS); 290 291 Expr *syntactic; 292 293 ExprResult result; 294 if (opcode == BO_Assign) { 295 result = capturedRHS; 296 syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, 297 opcode, capturedRHS->getType(), 298 capturedRHS->getValueKind(), 299 OK_Ordinary, opcLoc); 300 } else { 301 ExprResult opLHS = buildGet(); 302 if (opLHS.isInvalid()) return ExprError(); 303 304 // Build an ordinary, non-compound operation. 305 BinaryOperatorKind nonCompound = 306 BinaryOperator::getOpForCompoundAssignment(opcode); 307 result = S.BuildBinOp(Sc, opcLoc, nonCompound, 308 opLHS.take(), capturedRHS); 309 if (result.isInvalid()) return ExprError(); 310 311 syntactic = 312 new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode, 313 result.get()->getType(), 314 result.get()->getValueKind(), 315 OK_Ordinary, 316 opLHS.get()->getType(), 317 result.get()->getType(), 318 opcLoc); 319 } 320 321 // The result of the assignment, if not void, is the value set into 322 // the l-value. 323 result = buildSet(result.take(), opcLoc, assignmentsHaveResult()); 324 if (result.isInvalid()) return ExprError(); 325 addSemanticExpr(result.take()); 326 327 return complete(syntactic); 328} 329 330/// The basic skeleton for building an increment or decrement 331/// operation. 332ExprResult 333PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 334 UnaryOperatorKind opcode, 335 Expr *op) { 336 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 337 338 Expr *syntacticOp = rebuildAndCaptureObject(op); 339 340 // Load the value. 341 ExprResult result = buildGet(); 342 if (result.isInvalid()) return ExprError(); 343 344 QualType resultType = result.get()->getType(); 345 346 // That's the postfix result. 347 if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) { 348 result = capture(result.take()); 349 setResultToLastSemantic(); 350 } 351 352 // Add or subtract a literal 1. 353 llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1); 354 Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy, 355 GenericLoc); 356 357 if (UnaryOperator::isIncrementOp(opcode)) { 358 result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one); 359 } else { 360 result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one); 361 } 362 if (result.isInvalid()) return ExprError(); 363 364 // Store that back into the result. The value stored is the result 365 // of a prefix operation. 366 result = buildSet(result.take(), opcLoc, 367 UnaryOperator::isPrefix(opcode) && assignmentsHaveResult()); 368 if (result.isInvalid()) return ExprError(); 369 addSemanticExpr(result.take()); 370 371 UnaryOperator *syntactic = 372 new (S.Context) UnaryOperator(syntacticOp, opcode, resultType, 373 VK_LValue, OK_Ordinary, opcLoc); 374 return complete(syntactic); 375} 376 377 378//===----------------------------------------------------------------------===// 379// Objective-C @property and implicit property references 380//===----------------------------------------------------------------------===// 381 382/// Look up a method in the receiver type of an Objective-C property 383/// reference. 384static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, 385 const ObjCPropertyRefExpr *PRE) { 386 if (PRE->isObjectReceiver()) { 387 const ObjCObjectPointerType *PT = 388 PRE->getBase()->getType()->castAs<ObjCObjectPointerType>(); 389 390 // Special case for 'self' in class method implementations. 391 if (PT->isObjCClassType() && 392 S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) { 393 // This cast is safe because isSelfExpr is only true within 394 // methods. 395 ObjCMethodDecl *method = 396 cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor()); 397 return S.LookupMethodInObjectType(sel, 398 S.Context.getObjCInterfaceType(method->getClassInterface()), 399 /*instance*/ false); 400 } 401 402 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 403 } 404 405 if (PRE->isSuperReceiver()) { 406 if (const ObjCObjectPointerType *PT = 407 PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>()) 408 return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true); 409 410 return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false); 411 } 412 413 assert(PRE->isClassReceiver() && "Invalid expression"); 414 QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver()); 415 return S.LookupMethodInObjectType(sel, IT, false); 416} 417 418bool ObjCPropertyOpBuilder::findGetter() { 419 if (Getter) return true; 420 421 Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr); 422 return (Getter != 0); 423} 424 425/// Try to find the most accurate setter declaration for the property 426/// reference. 427/// 428/// \return true if a setter was found, in which case Setter 429bool ObjCPropertyOpBuilder::findSetter() { 430 // For implicit properties, just trust the lookup we already did. 431 if (RefExpr->isImplicitProperty()) { 432 if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { 433 Setter = setter; 434 SetterSelector = setter->getSelector(); 435 return true; 436 } else { 437 IdentifierInfo *getterName = 438 RefExpr->getImplicitPropertyGetter()->getSelector() 439 .getIdentifierInfoForSlot(0); 440 SetterSelector = 441 SelectorTable::constructSetterName(S.PP.getIdentifierTable(), 442 S.PP.getSelectorTable(), 443 getterName); 444 return false; 445 } 446 } 447 448 // For explicit properties, this is more involved. 449 ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); 450 SetterSelector = prop->getSetterName(); 451 452 // Do a normal method lookup first. 453 if (ObjCMethodDecl *setter = 454 LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { 455 Setter = setter; 456 return true; 457 } 458 459 // That can fail in the somewhat crazy situation that we're 460 // type-checking a message send within the @interface declaration 461 // that declared the @property. But it's not clear that that's 462 // valuable to support. 463 464 return false; 465} 466 467/// Capture the base object of an Objective-C property expression. 468Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { 469 assert(InstanceReceiver == 0); 470 471 // If we have a base, capture it in an OVE and rebuild the syntactic 472 // form to use the OVE as its base. 473 if (RefExpr->isObjectReceiver()) { 474 InstanceReceiver = capture(RefExpr->getBase()); 475 476 syntacticBase = 477 ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase); 478 } 479 480 return syntacticBase; 481} 482 483/// Load from an Objective-C property reference. 484ExprResult ObjCPropertyOpBuilder::buildGet() { 485 findGetter(); 486 assert(Getter); 487 488 QualType receiverType; 489 SourceLocation superLoc; 490 if (RefExpr->isClassReceiver()) { 491 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 492 } else if (RefExpr->isSuperReceiver()) { 493 superLoc = RefExpr->getReceiverLocation(); 494 receiverType = RefExpr->getSuperReceiverType(); 495 } else { 496 assert(InstanceReceiver); 497 receiverType = InstanceReceiver->getType(); 498 } 499 500 // Build a message-send. 501 ExprResult msg; 502 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 503 assert(InstanceReceiver || RefExpr->isSuperReceiver()); 504 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc, 505 Getter->getSelector(), Getter, 506 GenericLoc, GenericLoc, GenericLoc, 507 MultiExprArg()); 508 } else { 509 TypeSourceInfo *receiverTypeInfo = 0; 510 if (!RefExpr->isSuperReceiver()) 511 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType); 512 513 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc, 514 Getter->getSelector(), Getter, 515 GenericLoc, GenericLoc, GenericLoc, 516 MultiExprArg()); 517 } 518 return msg; 519} 520 521/// Store to an Objective-C property reference. 522/// 523/// \param bindSetValueAsResult - If true, capture the actual 524/// value being set as the value of the property operation. 525ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 526 bool captureSetValueAsResult) { 527 bool hasSetter = findSetter(); 528 assert(hasSetter); (void) hasSetter; 529 530 QualType receiverType; 531 SourceLocation superLoc; 532 if (RefExpr->isClassReceiver()) { 533 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 534 } else if (RefExpr->isSuperReceiver()) { 535 superLoc = RefExpr->getReceiverLocation(); 536 receiverType = RefExpr->getSuperReceiverType(); 537 } else { 538 assert(InstanceReceiver); 539 receiverType = InstanceReceiver->getType(); 540 } 541 542 // Use assignment constraints when possible; they give us better 543 // diagnostics. "When possible" basically means anything except a 544 // C++ class type. 545 if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) { 546 QualType paramType = (*Setter->param_begin())->getType(); 547 if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) { 548 ExprResult opResult = op; 549 Sema::AssignConvertType assignResult 550 = S.CheckSingleAssignmentConstraints(paramType, opResult); 551 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 552 op->getType(), opResult.get(), 553 Sema::AA_Assigning)) 554 return ExprError(); 555 556 op = opResult.take(); 557 assert(op && "successful assignment left argument invalid?"); 558 } 559 } 560 561 // Arguments. 562 Expr *args[] = { op }; 563 564 // Build a message-send. 565 ExprResult msg; 566 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 567 msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc, 568 SetterSelector, Setter, 569 GenericLoc, GenericLoc, GenericLoc, 570 MultiExprArg(args, 1)); 571 } else { 572 TypeSourceInfo *receiverTypeInfo = 0; 573 if (!RefExpr->isSuperReceiver()) 574 receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType); 575 576 msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc, 577 SetterSelector, Setter, 578 GenericLoc, GenericLoc, GenericLoc, 579 MultiExprArg(args, 1)); 580 } 581 582 if (!msg.isInvalid() && captureSetValueAsResult) { 583 ObjCMessageExpr *msgExpr = 584 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 585 Expr *arg = msgExpr->getArg(0); 586 msgExpr->setArg(0, captureValueAsResult(arg)); 587 } 588 589 return msg; 590} 591 592/// @property-specific behavior for doing lvalue-to-rvalue conversion. 593ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 594 // Explicit properties always have getters, but implicit ones don't. 595 // Check that before proceeding. 596 if (RefExpr->isImplicitProperty() && 597 !RefExpr->getImplicitPropertyGetter()) { 598 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 599 << RefExpr->getBase()->getType(); 600 return ExprError(); 601 } 602 603 ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 604 if (result.isInvalid()) return ExprError(); 605 606 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 607 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 608 Getter, RefExpr->getLocation()); 609 610 // As a special case, if the method returns 'id', try to get 611 // a better type from the property. 612 if (RefExpr->isExplicitProperty() && result.get()->isRValue() && 613 result.get()->getType()->isObjCIdType()) { 614 QualType propType = RefExpr->getExplicitProperty()->getType(); 615 if (const ObjCObjectPointerType *ptr 616 = propType->getAs<ObjCObjectPointerType>()) { 617 if (!ptr->isObjCIdType()) 618 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 619 } 620 } 621 622 return result; 623} 624 625/// Try to build this as a call to a getter that returns a reference. 626/// 627/// \return true if it was possible, whether or not it actually 628/// succeeded 629bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 630 ExprResult &result) { 631 if (!S.getLangOptions().CPlusPlus) return false; 632 633 findGetter(); 634 assert(Getter && "property has no setter and no getter!"); 635 636 // Only do this if the getter returns an l-value reference type. 637 QualType resultType = Getter->getResultType(); 638 if (!resultType->isLValueReferenceType()) return false; 639 640 result = buildRValueOperation(op); 641 return true; 642} 643 644/// @property-specific behavior for doing assignments. 645ExprResult 646ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 647 SourceLocation opcLoc, 648 BinaryOperatorKind opcode, 649 Expr *LHS, Expr *RHS) { 650 assert(BinaryOperator::isAssignmentOp(opcode)); 651 652 // If there's no setter, we have no choice but to try to assign to 653 // the result of the getter. 654 if (!findSetter()) { 655 ExprResult result; 656 if (tryBuildGetOfReference(LHS, result)) { 657 if (result.isInvalid()) return ExprError(); 658 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); 659 } 660 661 // Otherwise, it's an error. 662 S.Diag(opcLoc, diag::err_nosetter_property_assignment) 663 << unsigned(RefExpr->isImplicitProperty()) 664 << SetterSelector 665 << LHS->getSourceRange() << RHS->getSourceRange(); 666 return ExprError(); 667 } 668 669 // If there is a setter, we definitely want to use it. 670 671 // Verify that we can do a compound assignment. 672 if (opcode != BO_Assign && !findGetter()) { 673 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 674 << LHS->getSourceRange() << RHS->getSourceRange(); 675 return ExprError(); 676 } 677 678 ExprResult result = 679 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 680 if (result.isInvalid()) return ExprError(); 681 682 // Various warnings about property assignments in ARC. 683 if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) { 684 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 685 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 686 } 687 688 return result; 689} 690 691/// @property-specific behavior for doing increments and decrements. 692ExprResult 693ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 694 UnaryOperatorKind opcode, 695 Expr *op) { 696 // If there's no setter, we have no choice but to try to assign to 697 // the result of the getter. 698 if (!findSetter()) { 699 ExprResult result; 700 if (tryBuildGetOfReference(op, result)) { 701 if (result.isInvalid()) return ExprError(); 702 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); 703 } 704 705 // Otherwise, it's an error. 706 S.Diag(opcLoc, diag::err_nosetter_property_incdec) 707 << unsigned(RefExpr->isImplicitProperty()) 708 << unsigned(UnaryOperator::isDecrementOp(opcode)) 709 << SetterSelector 710 << op->getSourceRange(); 711 return ExprError(); 712 } 713 714 // If there is a setter, we definitely want to use it. 715 716 // We also need a getter. 717 if (!findGetter()) { 718 assert(RefExpr->isImplicitProperty()); 719 S.Diag(opcLoc, diag::err_nogetter_property_incdec) 720 << unsigned(UnaryOperator::isDecrementOp(opcode)) 721 << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME! 722 << op->getSourceRange(); 723 return ExprError(); 724 } 725 726 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 727} 728 729//===----------------------------------------------------------------------===// 730// General Sema routines. 731//===----------------------------------------------------------------------===// 732 733ExprResult Sema::checkPseudoObjectRValue(Expr *E) { 734 Expr *opaqueRef = E->IgnoreParens(); 735 if (ObjCPropertyRefExpr *refExpr 736 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 737 ObjCPropertyOpBuilder builder(*this, refExpr); 738 return builder.buildRValueOperation(E); 739 } else { 740 llvm_unreachable("unknown pseudo-object kind!"); 741 } 742} 743 744/// Check an increment or decrement of a pseudo-object expression. 745ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, 746 UnaryOperatorKind opcode, Expr *op) { 747 // Do nothing if the operand is dependent. 748 if (op->isTypeDependent()) 749 return new (Context) UnaryOperator(op, opcode, Context.DependentTy, 750 VK_RValue, OK_Ordinary, opcLoc); 751 752 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 753 Expr *opaqueRef = op->IgnoreParens(); 754 if (ObjCPropertyRefExpr *refExpr 755 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 756 ObjCPropertyOpBuilder builder(*this, refExpr); 757 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 758 } else { 759 llvm_unreachable("unknown pseudo-object kind!"); 760 } 761} 762 763ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 764 BinaryOperatorKind opcode, 765 Expr *LHS, Expr *RHS) { 766 // Do nothing if either argument is dependent. 767 if (LHS->isTypeDependent() || RHS->isTypeDependent()) 768 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, 769 VK_RValue, OK_Ordinary, opcLoc); 770 771 // Filter out non-overload placeholder types in the RHS. 772 if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) { 773 if (PTy->getKind() != BuiltinType::Overload) { 774 ExprResult result = CheckPlaceholderExpr(RHS); 775 if (result.isInvalid()) return ExprError(); 776 RHS = result.take(); 777 } 778 } 779 780 Expr *opaqueRef = LHS->IgnoreParens(); 781 if (ObjCPropertyRefExpr *refExpr 782 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 783 ObjCPropertyOpBuilder builder(*this, refExpr); 784 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 785 } else { 786 llvm_unreachable("unknown pseudo-object kind!"); 787 } 788} 789