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