SemaPseudoObject.cpp revision ed7f727257b770b6db8a86a29590bb9cbeeb002f
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  Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr);
421  return (Getter != 0);
422}
423
424/// Try to find the most accurate setter declaration for the property
425/// reference.
426///
427/// \return true if a setter was found, in which case Setter
428bool ObjCPropertyOpBuilder::findSetter() {
429  // For implicit properties, just trust the lookup we already did.
430  if (RefExpr->isImplicitProperty()) {
431    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
432      Setter = setter;
433      SetterSelector = setter->getSelector();
434      return true;
435    } else {
436      IdentifierInfo *getterName =
437        RefExpr->getImplicitPropertyGetter()->getSelector()
438          .getIdentifierInfoForSlot(0);
439      SetterSelector =
440        SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
441                                           S.PP.getSelectorTable(),
442                                           getterName);
443      return false;
444    }
445  }
446
447  // For explicit properties, this is more involved.
448  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
449  SetterSelector = prop->getSetterName();
450
451  // Do a normal method lookup first.
452  if (ObjCMethodDecl *setter =
453        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
454    Setter = setter;
455    return true;
456  }
457
458  // That can fail in the somewhat crazy situation that we're
459  // type-checking a message send within the @interface declaration
460  // that declared the @property.  But it's not clear that that's
461  // valuable to support.
462
463  return false;
464}
465
466/// Capture the base object of an Objective-C property expression.
467Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
468  assert(InstanceReceiver == 0);
469
470  // If we have a base, capture it in an OVE and rebuild the syntactic
471  // form to use the OVE as its base.
472  if (RefExpr->isObjectReceiver()) {
473    InstanceReceiver = capture(RefExpr->getBase());
474
475    syntacticBase =
476      ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
477  }
478
479  return syntacticBase;
480}
481
482/// Load from an Objective-C property reference.
483ExprResult ObjCPropertyOpBuilder::buildGet() {
484  findGetter();
485  assert(Getter);
486
487  QualType receiverType;
488  SourceLocation superLoc;
489  if (RefExpr->isClassReceiver()) {
490    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
491  } else if (RefExpr->isSuperReceiver()) {
492    superLoc = RefExpr->getReceiverLocation();
493    receiverType = RefExpr->getSuperReceiverType();
494  } else {
495    assert(InstanceReceiver);
496    receiverType = InstanceReceiver->getType();
497  }
498
499  // Build a message-send.
500  ExprResult msg;
501  if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
502    assert(InstanceReceiver || RefExpr->isSuperReceiver());
503    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
504                                 Getter->getSelector(), Getter,
505                                 GenericLoc, GenericLoc, GenericLoc,
506                                 MultiExprArg());
507  } else {
508    TypeSourceInfo *receiverTypeInfo = 0;
509    if (!RefExpr->isSuperReceiver())
510      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
511
512    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
513                              Getter->getSelector(), Getter,
514                              GenericLoc, GenericLoc, GenericLoc,
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.
524ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
525                                           bool captureSetValueAsResult) {
526  bool hasSetter = findSetter();
527  assert(hasSetter); (void) hasSetter;
528
529  QualType receiverType;
530  SourceLocation superLoc;
531  if (RefExpr->isClassReceiver()) {
532    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
533  } else if (RefExpr->isSuperReceiver()) {
534    superLoc = RefExpr->getReceiverLocation();
535    receiverType = RefExpr->getSuperReceiverType();
536  } else {
537    assert(InstanceReceiver);
538    receiverType = InstanceReceiver->getType();
539  }
540
541  // Use assignment constraints when possible; they give us better
542  // diagnostics.  "When possible" basically means anything except a
543  // C++ class type.
544  if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {
545    QualType paramType = (*Setter->param_begin())->getType();
546    if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {
547      ExprResult opResult = op;
548      Sema::AssignConvertType assignResult
549        = S.CheckSingleAssignmentConstraints(paramType, opResult);
550      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
551                                     op->getType(), opResult.get(),
552                                     Sema::AA_Assigning))
553        return ExprError();
554
555      op = opResult.take();
556      assert(op && "successful assignment left argument invalid?");
557    }
558  }
559
560  // Arguments.
561  Expr *args[] = { op };
562
563  // Build a message-send.
564  ExprResult msg;
565  if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
566    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
567                                 SetterSelector, Setter,
568                                 GenericLoc, GenericLoc, GenericLoc,
569                                 MultiExprArg(args, 1));
570  } else {
571    TypeSourceInfo *receiverTypeInfo = 0;
572    if (!RefExpr->isSuperReceiver())
573      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
574
575    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
576                              SetterSelector, Setter,
577                              GenericLoc, GenericLoc, GenericLoc,
578                              MultiExprArg(args, 1));
579  }
580
581  if (!msg.isInvalid() && captureSetValueAsResult) {
582    ObjCMessageExpr *msgExpr =
583      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
584    Expr *arg = msgExpr->getArg(0);
585    msgExpr->setArg(0, captureValueAsResult(arg));
586  }
587
588  return msg;
589}
590
591/// @property-specific behavior for doing lvalue-to-rvalue conversion.
592ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
593  // Explicit properties always have getters, but implicit ones don't.
594  // Check that before proceeding.
595  if (RefExpr->isImplicitProperty() &&
596      !RefExpr->getImplicitPropertyGetter()) {
597    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
598      << RefExpr->getBase()->getType();
599    return ExprError();
600  }
601
602  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
603  if (result.isInvalid()) return ExprError();
604
605  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
606    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
607                                       Getter, RefExpr->getLocation());
608
609  // As a special case, if the method returns 'id', try to get
610  // a better type from the property.
611  if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
612      result.get()->getType()->isObjCIdType()) {
613    QualType propType = RefExpr->getExplicitProperty()->getType();
614    if (const ObjCObjectPointerType *ptr
615          = propType->getAs<ObjCObjectPointerType>()) {
616      if (!ptr->isObjCIdType())
617        result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
618    }
619  }
620
621  return result;
622}
623
624/// Try to build this as a call to a getter that returns a reference.
625///
626/// \return true if it was possible, whether or not it actually
627///   succeeded
628bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
629                                                   ExprResult &result) {
630  if (!S.getLangOptions().CPlusPlus) return false;
631
632  findGetter();
633  assert(Getter && "property has no setter and no getter!");
634
635  // Only do this if the getter returns an l-value reference type.
636  QualType resultType = Getter->getResultType();
637  if (!resultType->isLValueReferenceType()) return false;
638
639  result = buildRValueOperation(op);
640  return true;
641}
642
643/// @property-specific behavior for doing assignments.
644ExprResult
645ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
646                                                SourceLocation opcLoc,
647                                                BinaryOperatorKind opcode,
648                                                Expr *LHS, Expr *RHS) {
649  assert(BinaryOperator::isAssignmentOp(opcode));
650
651  // If there's no setter, we have no choice but to try to assign to
652  // the result of the getter.
653  if (!findSetter()) {
654    ExprResult result;
655    if (tryBuildGetOfReference(LHS, result)) {
656      if (result.isInvalid()) return ExprError();
657      return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
658    }
659
660    // Otherwise, it's an error.
661    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
662      << unsigned(RefExpr->isImplicitProperty())
663      << SetterSelector
664      << LHS->getSourceRange() << RHS->getSourceRange();
665    return ExprError();
666  }
667
668  // If there is a setter, we definitely want to use it.
669
670  // Verify that we can do a compound assignment.
671  if (opcode != BO_Assign && !findGetter()) {
672    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
673      << LHS->getSourceRange() << RHS->getSourceRange();
674    return ExprError();
675  }
676
677  ExprResult result =
678    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
679  if (result.isInvalid()) return ExprError();
680
681  // Various warnings about property assignments in ARC.
682  if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
683    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
684    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
685  }
686
687  return result;
688}
689
690/// @property-specific behavior for doing increments and decrements.
691ExprResult
692ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
693                                            UnaryOperatorKind opcode,
694                                            Expr *op) {
695  // If there's no setter, we have no choice but to try to assign to
696  // the result of the getter.
697  if (!findSetter()) {
698    ExprResult result;
699    if (tryBuildGetOfReference(op, result)) {
700      if (result.isInvalid()) return ExprError();
701      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
702    }
703
704    // Otherwise, it's an error.
705    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
706      << unsigned(RefExpr->isImplicitProperty())
707      << unsigned(UnaryOperator::isDecrementOp(opcode))
708      << SetterSelector
709      << op->getSourceRange();
710    return ExprError();
711  }
712
713  // If there is a setter, we definitely want to use it.
714
715  // We also need a getter.
716  if (!findGetter()) {
717    assert(RefExpr->isImplicitProperty());
718    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
719      << unsigned(UnaryOperator::isDecrementOp(opcode))
720      << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
721      << op->getSourceRange();
722    return ExprError();
723  }
724
725  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
726}
727
728//===----------------------------------------------------------------------===//
729//  General Sema routines.
730//===----------------------------------------------------------------------===//
731
732ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
733  Expr *opaqueRef = E->IgnoreParens();
734  if (ObjCPropertyRefExpr *refExpr
735        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
736    ObjCPropertyOpBuilder builder(*this, refExpr);
737    return builder.buildRValueOperation(E);
738  } else {
739    llvm_unreachable("unknown pseudo-object kind!");
740  }
741}
742
743/// Check an increment or decrement of a pseudo-object expression.
744ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
745                                         UnaryOperatorKind opcode, Expr *op) {
746  // Do nothing if the operand is dependent.
747  if (op->isTypeDependent())
748    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
749                                       VK_RValue, OK_Ordinary, opcLoc);
750
751  assert(UnaryOperator::isIncrementDecrementOp(opcode));
752  Expr *opaqueRef = op->IgnoreParens();
753  if (ObjCPropertyRefExpr *refExpr
754        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
755    ObjCPropertyOpBuilder builder(*this, refExpr);
756    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
757  } else {
758    llvm_unreachable("unknown pseudo-object kind!");
759  }
760}
761
762ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
763                                             BinaryOperatorKind opcode,
764                                             Expr *LHS, Expr *RHS) {
765  // Do nothing if either argument is dependent.
766  if (LHS->isTypeDependent() || RHS->isTypeDependent())
767    return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
768                                        VK_RValue, OK_Ordinary, opcLoc);
769
770  // Filter out non-overload placeholder types in the RHS.
771  if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
772    if (PTy->getKind() != BuiltinType::Overload) {
773      ExprResult result = CheckPlaceholderExpr(RHS);
774      if (result.isInvalid()) return ExprError();
775      RHS = result.take();
776    }
777  }
778
779  Expr *opaqueRef = LHS->IgnoreParens();
780  if (ObjCPropertyRefExpr *refExpr
781        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
782    ObjCPropertyOpBuilder builder(*this, refExpr);
783    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
784  } else {
785    llvm_unreachable("unknown pseudo-object kind!");
786  }
787}
788