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 38 using namespace clang; 39 using namespace sema; 40 41 namespace { 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. 221 OpaqueValueExpr *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 239 OpaqueValueExpr *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. 263 ExprResult 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. 269 ExprResult 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. 281 ExprResult 282 PseudoOpBuilder::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. 331 ExprResult 332 PseudoOpBuilder::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. 383 static 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 417 bool 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 435 bool 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. 474 Expr *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. 490 ExprResult ObjCPropertyOpBuilder::buildGet() { 491 findGetter(); 492 assert(Getter); 493 494 QualType receiverType; 495 if (RefExpr->isClassReceiver()) { 496 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 497 } else if (RefExpr->isSuperReceiver()) { 498 receiverType = RefExpr->getSuperReceiverType(); 499 } else { 500 assert(InstanceReceiver); 501 receiverType = InstanceReceiver->getType(); 502 } 503 504 // Build a message-send. 505 ExprResult msg; 506 if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 507 assert(InstanceReceiver || RefExpr->isSuperReceiver()); 508 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 509 GenericLoc, Getter->getSelector(), 510 Getter, MultiExprArg()); 511 } else { 512 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 513 GenericLoc, 514 Getter->getSelector(), Getter, 515 MultiExprArg()); 516 } 517 return msg; 518 } 519 520 /// Store to an Objective-C property reference. 521 /// 522 /// \param bindSetValueAsResult - If true, capture the actual 523 /// value being set as the value of the property operation. 524 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, 525 bool captureSetValueAsResult) { 526 bool hasSetter = findSetter(); 527 assert(hasSetter); (void) hasSetter; 528 529 QualType receiverType; 530 if (RefExpr->isClassReceiver()) { 531 receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver()); 532 } else if (RefExpr->isSuperReceiver()) { 533 receiverType = RefExpr->getSuperReceiverType(); 534 } else { 535 assert(InstanceReceiver); 536 receiverType = InstanceReceiver->getType(); 537 } 538 539 // Use assignment constraints when possible; they give us better 540 // diagnostics. "When possible" basically means anything except a 541 // C++ class type. 542 if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) { 543 QualType paramType = (*Setter->param_begin())->getType(); 544 if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) { 545 ExprResult opResult = op; 546 Sema::AssignConvertType assignResult 547 = S.CheckSingleAssignmentConstraints(paramType, opResult); 548 if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType, 549 op->getType(), opResult.get(), 550 Sema::AA_Assigning)) 551 return ExprError(); 552 553 op = opResult.take(); 554 assert(op && "successful assignment left argument invalid?"); 555 } 556 } 557 558 // Arguments. 559 Expr *args[] = { op }; 560 561 // Build a message-send. 562 ExprResult msg; 563 if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) { 564 msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, 565 GenericLoc, SetterSelector, Setter, 566 MultiExprArg(args, 1)); 567 } else { 568 msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(), 569 GenericLoc, 570 SetterSelector, Setter, 571 MultiExprArg(args, 1)); 572 } 573 574 if (!msg.isInvalid() && captureSetValueAsResult) { 575 ObjCMessageExpr *msgExpr = 576 cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); 577 Expr *arg = msgExpr->getArg(0); 578 msgExpr->setArg(0, captureValueAsResult(arg)); 579 } 580 581 return msg; 582 } 583 584 /// @property-specific behavior for doing lvalue-to-rvalue conversion. 585 ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { 586 // Explicit properties always have getters, but implicit ones don't. 587 // Check that before proceeding. 588 if (RefExpr->isImplicitProperty() && 589 !RefExpr->getImplicitPropertyGetter()) { 590 S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) 591 << RefExpr->getBase()->getType(); 592 return ExprError(); 593 } 594 595 ExprResult result = PseudoOpBuilder::buildRValueOperation(op); 596 if (result.isInvalid()) return ExprError(); 597 598 if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType()) 599 S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(), 600 Getter, RefExpr->getLocation()); 601 602 // As a special case, if the method returns 'id', try to get 603 // a better type from the property. 604 if (RefExpr->isExplicitProperty() && result.get()->isRValue() && 605 result.get()->getType()->isObjCIdType()) { 606 QualType propType = RefExpr->getExplicitProperty()->getType(); 607 if (const ObjCObjectPointerType *ptr 608 = propType->getAs<ObjCObjectPointerType>()) { 609 if (!ptr->isObjCIdType()) 610 result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); 611 } 612 } 613 614 return result; 615 } 616 617 /// Try to build this as a call to a getter that returns a reference. 618 /// 619 /// \return true if it was possible, whether or not it actually 620 /// succeeded 621 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op, 622 ExprResult &result) { 623 if (!S.getLangOptions().CPlusPlus) return false; 624 625 findGetter(); 626 assert(Getter && "property has no setter and no getter!"); 627 628 // Only do this if the getter returns an l-value reference type. 629 QualType resultType = Getter->getResultType(); 630 if (!resultType->isLValueReferenceType()) return false; 631 632 result = buildRValueOperation(op); 633 return true; 634 } 635 636 /// @property-specific behavior for doing assignments. 637 ExprResult 638 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc, 639 SourceLocation opcLoc, 640 BinaryOperatorKind opcode, 641 Expr *LHS, Expr *RHS) { 642 assert(BinaryOperator::isAssignmentOp(opcode)); 643 644 // If there's no setter, we have no choice but to try to assign to 645 // the result of the getter. 646 if (!findSetter()) { 647 ExprResult result; 648 if (tryBuildGetOfReference(LHS, result)) { 649 if (result.isInvalid()) return ExprError(); 650 return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS); 651 } 652 653 // Otherwise, it's an error. 654 S.Diag(opcLoc, diag::err_nosetter_property_assignment) 655 << unsigned(RefExpr->isImplicitProperty()) 656 << SetterSelector 657 << LHS->getSourceRange() << RHS->getSourceRange(); 658 return ExprError(); 659 } 660 661 // If there is a setter, we definitely want to use it. 662 663 // Verify that we can do a compound assignment. 664 if (opcode != BO_Assign && !findGetter()) { 665 S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment) 666 << LHS->getSourceRange() << RHS->getSourceRange(); 667 return ExprError(); 668 } 669 670 ExprResult result = 671 PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS); 672 if (result.isInvalid()) return ExprError(); 673 674 // Various warnings about property assignments in ARC. 675 if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) { 676 S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS); 677 S.checkUnsafeExprAssigns(opcLoc, LHS, RHS); 678 } 679 680 return result; 681 } 682 683 /// @property-specific behavior for doing increments and decrements. 684 ExprResult 685 ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, 686 UnaryOperatorKind opcode, 687 Expr *op) { 688 // If there's no setter, we have no choice but to try to assign to 689 // the result of the getter. 690 if (!findSetter()) { 691 ExprResult result; 692 if (tryBuildGetOfReference(op, result)) { 693 if (result.isInvalid()) return ExprError(); 694 return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take()); 695 } 696 697 // Otherwise, it's an error. 698 S.Diag(opcLoc, diag::err_nosetter_property_incdec) 699 << unsigned(RefExpr->isImplicitProperty()) 700 << unsigned(UnaryOperator::isDecrementOp(opcode)) 701 << SetterSelector 702 << op->getSourceRange(); 703 return ExprError(); 704 } 705 706 // If there is a setter, we definitely want to use it. 707 708 // We also need a getter. 709 if (!findGetter()) { 710 assert(RefExpr->isImplicitProperty()); 711 S.Diag(opcLoc, diag::err_nogetter_property_incdec) 712 << unsigned(UnaryOperator::isDecrementOp(opcode)) 713 << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME! 714 << op->getSourceRange(); 715 return ExprError(); 716 } 717 718 return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); 719 } 720 721 //===----------------------------------------------------------------------===// 722 // General Sema routines. 723 //===----------------------------------------------------------------------===// 724 725 ExprResult Sema::checkPseudoObjectRValue(Expr *E) { 726 Expr *opaqueRef = E->IgnoreParens(); 727 if (ObjCPropertyRefExpr *refExpr 728 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 729 ObjCPropertyOpBuilder builder(*this, refExpr); 730 return builder.buildRValueOperation(E); 731 } else { 732 llvm_unreachable("unknown pseudo-object kind!"); 733 } 734 } 735 736 /// Check an increment or decrement of a pseudo-object expression. 737 ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc, 738 UnaryOperatorKind opcode, Expr *op) { 739 // Do nothing if the operand is dependent. 740 if (op->isTypeDependent()) 741 return new (Context) UnaryOperator(op, opcode, Context.DependentTy, 742 VK_RValue, OK_Ordinary, opcLoc); 743 744 assert(UnaryOperator::isIncrementDecrementOp(opcode)); 745 Expr *opaqueRef = op->IgnoreParens(); 746 if (ObjCPropertyRefExpr *refExpr 747 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 748 ObjCPropertyOpBuilder builder(*this, refExpr); 749 return builder.buildIncDecOperation(Sc, opcLoc, opcode, op); 750 } else { 751 llvm_unreachable("unknown pseudo-object kind!"); 752 } 753 } 754 755 ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, 756 BinaryOperatorKind opcode, 757 Expr *LHS, Expr *RHS) { 758 // Do nothing if either argument is dependent. 759 if (LHS->isTypeDependent() || RHS->isTypeDependent()) 760 return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, 761 VK_RValue, OK_Ordinary, opcLoc); 762 763 // Filter out non-overload placeholder types in the RHS. 764 if (RHS->getType()->isNonOverloadPlaceholderType()) { 765 ExprResult result = CheckPlaceholderExpr(RHS); 766 if (result.isInvalid()) return ExprError(); 767 RHS = result.take(); 768 } 769 770 Expr *opaqueRef = LHS->IgnoreParens(); 771 if (ObjCPropertyRefExpr *refExpr 772 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 773 ObjCPropertyOpBuilder builder(*this, refExpr); 774 return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS); 775 } else { 776 llvm_unreachable("unknown pseudo-object kind!"); 777 } 778 } 779 780 /// Given a pseudo-object reference, rebuild it without the opaque 781 /// values. Basically, undo the behavior of rebuildAndCaptureObject. 782 /// This should never operate in-place. 783 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) { 784 Expr *opaqueRef = E->IgnoreParens(); 785 if (ObjCPropertyRefExpr *refExpr 786 = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) { 787 OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase()); 788 return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E); 789 } else { 790 llvm_unreachable("unknown pseudo-object kind!"); 791 } 792 } 793 794 /// Given a pseudo-object expression, recreate what it looks like 795 /// syntactically without the attendant OpaqueValueExprs. 796 /// 797 /// This is a hack which should be removed when TreeTransform is 798 /// capable of rebuilding a tree without stripping implicit 799 /// operations. 800 Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { 801 Expr *syntax = E->getSyntacticForm(); 802 if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) { 803 Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr()); 804 return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(), 805 uop->getValueKind(), uop->getObjectKind(), 806 uop->getOperatorLoc()); 807 } else if (CompoundAssignOperator *cop 808 = dyn_cast<CompoundAssignOperator>(syntax)) { 809 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS()); 810 Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr(); 811 return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(), 812 cop->getType(), 813 cop->getValueKind(), 814 cop->getObjectKind(), 815 cop->getComputationLHSType(), 816 cop->getComputationResultType(), 817 cop->getOperatorLoc()); 818 } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { 819 Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); 820 Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); 821 return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), 822 bop->getType(), bop->getValueKind(), 823 bop->getObjectKind(), 824 bop->getOperatorLoc()); 825 } else { 826 assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); 827 return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); 828 } 829 } 830