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   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.
531 ExprResult 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.
599 ExprResult 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
635 bool 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.
651 ExprResult
652 ObjCPropertyOpBuilder::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.
698 ExprResult
699 ObjCPropertyOpBuilder::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 
739 ExprResult 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.
751 ExprResult 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 
769 ExprResult 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