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