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