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