SemaPseudoObject.cpp revision 4b9c2d235fb9449e249d74f48ecfec601650de93
13c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
23c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//
33c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//                     The LLVM Compiler Infrastructure
43c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//
53c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// This file is distributed under the University of Illinois Open Source
63c3b7f90a863af43fa63043d396553ecf205351cJohn McCall// License. See LICENSE.TXT for details.
73c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//
83c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===----------------------------------------------------------------------===//
93c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//
103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  This file implements semantic analysis for expressions involving
113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  pseudo-object references.  Pseudo-objects are conceptual objects
123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  whose storage is entirely abstract and all accesses to which are
133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  translated through some sort of abstraction barrier.
143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//
153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  For example, Objective-C objects can have "properties", either
163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  declared or undeclared.  A property may be accessed by writing
173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//    expr.prop
183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  where 'expr' is an r-value of Objective-C pointer type and 'prop'
193c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  is the name of the property.  If this expression is used in a context
203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  needing an r-value, it is treated as if it were a message-send
213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  of the associated 'getter' selector, typically:
223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//    [expr prop]
233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  If it is used as the LHS of a simple assignment, it is treated
243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  as a message-send of the associated 'setter' selector, typically:
253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//    [expr setProp: RHS]
263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  If it is used as the LHS of a compound assignment, or the operand
273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  of a unary increment or decrement, both are required;  for example,
283c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//  'expr.prop *= 100' would be translated to:
293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//    [expr setProp: [expr prop] * 100]
303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//
313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall//===----------------------------------------------------------------------===//
323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/SemaInternal.h"
343c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/Initialization.h"
353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/AST/ExprObjC.h"
363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Lex/Preprocessor.h"
373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
383c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace clang;
393c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace sema;
403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
414b9c2d235fb9449e249d74f48ecfec601650de93John McCallnamespace {
424b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Basically just a very focused copy of TreeTransform.
434b9c2d235fb9449e249d74f48ecfec601650de93John McCall  template <class T> struct Rebuilder {
444b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Sema &S;
454b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Rebuilder(Sema &S) : S(S) {}
464b9c2d235fb9449e249d74f48ecfec601650de93John McCall
474b9c2d235fb9449e249d74f48ecfec601650de93John McCall    T &getDerived() { return static_cast<T&>(*this); }
484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
494b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuild(Expr *e) {
504b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Fast path: nothing to look through.
514b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (typename T::specific_type *specific
524b9c2d235fb9449e249d74f48ecfec601650de93John McCall            = dyn_cast<typename T::specific_type>(e))
534b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return getDerived().rebuildSpecific(specific);
544b9c2d235fb9449e249d74f48ecfec601650de93John McCall
554b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Otherwise, we should look through and rebuild anything that
564b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // IgnoreParens would.
574b9c2d235fb9449e249d74f48ecfec601650de93John McCall
584b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
594b9c2d235fb9449e249d74f48ecfec601650de93John McCall        e = rebuild(parens->getSubExpr());
604b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) ParenExpr(parens->getLParen(),
614b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         parens->getRParen(),
624b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         e);
634b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
644b9c2d235fb9449e249d74f48ecfec601650de93John McCall
654b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
664b9c2d235fb9449e249d74f48ecfec601650de93John McCall        assert(uop->getOpcode() == UO_Extension);
674b9c2d235fb9449e249d74f48ecfec601650de93John McCall        e = rebuild(uop->getSubExpr());
684b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) UnaryOperator(e, uop->getOpcode(),
694b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getType(),
704b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getValueKind(),
714b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getObjectKind(),
724b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getOperatorLoc());
734b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
744b9c2d235fb9449e249d74f48ecfec601650de93John McCall
754b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
764b9c2d235fb9449e249d74f48ecfec601650de93John McCall        assert(!gse->isResultDependent());
774b9c2d235fb9449e249d74f48ecfec601650de93John McCall        unsigned resultIndex = gse->getResultIndex();
784b9c2d235fb9449e249d74f48ecfec601650de93John McCall        unsigned numAssocs = gse->getNumAssocs();
794b9c2d235fb9449e249d74f48ecfec601650de93John McCall
804b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SmallVector<Expr*, 8> assocs(numAssocs);
814b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
824b9c2d235fb9449e249d74f48ecfec601650de93John McCall
834b9c2d235fb9449e249d74f48ecfec601650de93John McCall        for (unsigned i = 0; i != numAssocs; ++i) {
844b9c2d235fb9449e249d74f48ecfec601650de93John McCall          Expr *assoc = gse->getAssocExpr(i);
854b9c2d235fb9449e249d74f48ecfec601650de93John McCall          if (i == resultIndex) assoc = rebuild(assoc);
864b9c2d235fb9449e249d74f48ecfec601650de93John McCall          assocs[i] = assoc;
874b9c2d235fb9449e249d74f48ecfec601650de93John McCall          assocTypes[i] = gse->getAssocTypeSourceInfo(i);
884b9c2d235fb9449e249d74f48ecfec601650de93John McCall        }
894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
904b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) GenericSelectionExpr(S.Context,
914b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getGenericLoc(),
924b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getControllingExpr(),
934b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    assocTypes.data(),
944b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    assocs.data(),
954b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    numAssocs,
964b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getDefaultLoc(),
974b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getRParenLoc(),
984b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      gse->containsUnexpandedParameterPack(),
994b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    resultIndex);
1004b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1014b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1024b9c2d235fb9449e249d74f48ecfec601650de93John McCall      llvm_unreachable("bad expression to rebuild!");
1034b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1044b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
1054b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1064b9c2d235fb9449e249d74f48ecfec601650de93John McCall  struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
1074b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *NewBase;
1084b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
1094b9c2d235fb9449e249d74f48ecfec601650de93John McCall      : Rebuilder(S), NewBase(newBase) {}
1104b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1114b9c2d235fb9449e249d74f48ecfec601650de93John McCall    typedef ObjCPropertyRefExpr specific_type;
1124b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
1134b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Fortunately, the constraint that we're rebuilding something
1144b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // with a base limits the number of cases here.
1154b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(refExpr->getBase());
1164b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1174b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (refExpr->isExplicitProperty()) {
1184b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context)
1194b9c2d235fb9449e249d74f48ecfec601650de93John McCall          ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
1204b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              refExpr->getType(), refExpr->getValueKind(),
1214b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              refExpr->getObjectKind(), refExpr->getLocation(),
1224b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              NewBase);
1234b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1244b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return new (S.Context)
1254b9c2d235fb9449e249d74f48ecfec601650de93John McCall        ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
1264b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            refExpr->getImplicitPropertySetter(),
1274b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            refExpr->getType(), refExpr->getValueKind(),
1284b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            refExpr->getObjectKind(),refExpr->getLocation(),
1294b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            NewBase);
1304b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
1324b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1334b9c2d235fb9449e249d74f48ecfec601650de93John McCall  class PseudoOpBuilder {
1344b9c2d235fb9449e249d74f48ecfec601650de93John McCall  public:
1354b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Sema &S;
1364b9c2d235fb9449e249d74f48ecfec601650de93John McCall    unsigned ResultIndex;
1374b9c2d235fb9449e249d74f48ecfec601650de93John McCall    SourceLocation GenericLoc;
1384b9c2d235fb9449e249d74f48ecfec601650de93John McCall    SmallVector<Expr *, 4> Semantics;
1394b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1404b9c2d235fb9449e249d74f48ecfec601650de93John McCall    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
1414b9c2d235fb9449e249d74f48ecfec601650de93John McCall      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
1424b9c2d235fb9449e249d74f48ecfec601650de93John McCall        GenericLoc(genericLoc) {}
1434b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1444b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Add a normal semantic expression.
1454b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void addSemanticExpr(Expr *semantic) {
1464b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Semantics.push_back(semantic);
1474b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1494b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Add the 'result' semantic expression.
1504b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void addResultSemanticExpr(Expr *resultExpr) {
1514b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(ResultIndex == PseudoObjectExpr::NoResult);
1524b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ResultIndex = Semantics.size();
1534b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Semantics.push_back(resultExpr);
1544b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1554b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1564b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildRValueOperation(Expr *op);
1574b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildAssignmentOperation(Scope *Sc,
1584b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        SourceLocation opLoc,
1594b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        BinaryOperatorKind opcode,
1604b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        Expr *LHS, Expr *RHS);
1614b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
1624b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    UnaryOperatorKind opcode,
1634b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    Expr *op);
1644b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1654b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult complete(Expr *syntacticForm);
1664b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1674b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *capture(Expr *op);
1684b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *captureValueAsResult(Expr *op);
1694b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1704b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void setResultToLastSemantic() {
1714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(ResultIndex == PseudoObjectExpr::NoResult);
1724b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ResultIndex = Semantics.size() - 1;
1734b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1744b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1754b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Return true if assignments have a non-void result.
1764b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual bool assignmentsHaveResult() { return true; }
1774b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1784b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
1794b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual ExprResult buildGet() = 0;
1804b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual ExprResult buildSet(Expr *, SourceLocation,
1814b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                bool captureSetValueAsResult) = 0;
1824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
1834b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  /// A PseudoOpBuilder for Objective-C @properties.
1854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  class ObjCPropertyOpBuilder : public PseudoOpBuilder {
1864b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyRefExpr *RefExpr;
1874b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *InstanceReceiver;
1884b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMethodDecl *Getter;
1894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1904b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMethodDecl *Setter;
1914b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Selector SetterSelector;
1924b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1934b9c2d235fb9449e249d74f48ecfec601650de93John McCall  public:
1944b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
1954b9c2d235fb9449e249d74f48ecfec601650de93John McCall      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
1964b9c2d235fb9449e249d74f48ecfec601650de93John McCall      InstanceReceiver(0), Getter(0), Setter(0) {
1974b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1984b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1994b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildRValueOperation(Expr *op);
2004b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildAssignmentOperation(Scope *Sc,
2014b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        SourceLocation opLoc,
2024b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        BinaryOperatorKind opcode,
2034b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        Expr *LHS, Expr *RHS);
2044b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
2054b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    UnaryOperatorKind opcode,
2064b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    Expr *op);
2074b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2084b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool tryBuildGetOfReference(Expr *op, ExprResult &result);
2094b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool findSetter();
2104b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool findGetter();
2114b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2124b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuildAndCaptureObject(Expr *syntacticBase);
2134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildGet();
2144b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildSet(Expr *op, SourceLocation, bool);
2154b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
2164b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2174b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2184b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression in an OpaqueValueExpr.
2194b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
2204b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Make a new OVE whose source is the given expression.
2214b9c2d235fb9449e249d74f48ecfec601650de93John McCall  OpaqueValueExpr *captured =
2224b9c2d235fb9449e249d74f48ecfec601650de93John McCall    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
2234b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    e->getValueKind());
2244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  captured->setSourceExpr(e);
2254b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2264b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Make sure we bind that in the semantics.
2274b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(captured);
2284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return captured;
2294b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2304b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2314b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression as the result of this pseudo-object
2324b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation.  This routine is safe against expressions which may
2334b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// already be captured.
2344b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
2354b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \param Returns the captured expression, which will be the
2364b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   same as the input if the input was already captured
2374b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
2384b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(ResultIndex == PseudoObjectExpr::NoResult);
2394b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2404b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If the expression hasn't already been captured, just capture it
2414b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // and set the new semantic
2424b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!isa<OpaqueValueExpr>(e)) {
2434b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *cap = capture(e);
2444b9c2d235fb9449e249d74f48ecfec601650de93John McCall    setResultToLastSemantic();
2454b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return cap;
2464b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
2474b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2484b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Otherwise, it must already be one of our semantic expressions;
2494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // set ResultIndex to its index.
2504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  unsigned index = 0;
2514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  for (;; ++index) {
2524b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(index < Semantics.size() &&
2534b9c2d235fb9449e249d74f48ecfec601650de93John McCall           "captured expression not found in semantics!");
2544b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (e == Semantics[index]) break;
2554b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
2564b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ResultIndex = index;
2574b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return cast<OpaqueValueExpr>(e);
2584b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2594b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2604b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The routine which creates the final PseudoObjectExpr.
2614b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::complete(Expr *syntactic) {
2624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return PseudoObjectExpr::Create(S.Context, syntactic,
2634b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                  Semantics, ResultIndex);
2644b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2654b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2664b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The main skeleton for building an r-value operation.
2674b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
2684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticBase = rebuildAndCaptureObject(op);
2694b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2704b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult getExpr = buildGet();
2714b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (getExpr.isInvalid()) return ExprError();
2724b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addResultSemanticExpr(getExpr.take());
2734b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2744b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntacticBase);
2754b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2764b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2774b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building a simple or compound
2784b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// assignment operation.
2794b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
2804b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
2814b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                          BinaryOperatorKind opcode,
2824b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                          Expr *LHS, Expr *RHS) {
2834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(BinaryOperator::isAssignmentOp(opcode));
2844b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
2864b9c2d235fb9449e249d74f48ecfec601650de93John McCall  OpaqueValueExpr *capturedRHS = capture(RHS);
2874b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2884b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntactic;
2894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2904b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result;
2914b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (opcode == BO_Assign) {
2924b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = capturedRHS;
2934b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
2944b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               opcode, capturedRHS->getType(),
2954b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               capturedRHS->getValueKind(),
2964b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               OK_Ordinary, opcLoc);
2974b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
2984b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult opLHS = buildGet();
2994b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (opLHS.isInvalid()) return ExprError();
3004b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3014b9c2d235fb9449e249d74f48ecfec601650de93John McCall    // Build an ordinary, non-compound operation.
3024b9c2d235fb9449e249d74f48ecfec601650de93John McCall    BinaryOperatorKind nonCompound =
3034b9c2d235fb9449e249d74f48ecfec601650de93John McCall      BinaryOperator::getOpForCompoundAssignment(opcode);
3044b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = S.BuildBinOp(Sc, opcLoc, nonCompound,
3054b9c2d235fb9449e249d74f48ecfec601650de93John McCall                          opLHS.take(), capturedRHS);
3064b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (result.isInvalid()) return ExprError();
3074b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3084b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntactic =
3094b9c2d235fb9449e249d74f48ecfec601650de93John McCall      new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
3104b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getType(),
3114b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getValueKind(),
3124b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             OK_Ordinary,
3134b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             opLHS.get()->getType(),
3144b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getType(),
3154b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             opcLoc);
3164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3174b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3184b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // The result of the assignment, if not void, is the value set into
3194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // the l-value.
3204b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
3214b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
3224b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(result.take());
3234b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntactic);
3254b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3264b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3274b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building an increment or decrement
3284b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation.
3294b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
3304b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
3314b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      UnaryOperatorKind opcode,
3324b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      Expr *op) {
3334b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(UnaryOperator::isIncrementDecrementOp(opcode));
3344b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3354b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticOp = rebuildAndCaptureObject(op);
3364b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3374b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Load the value.
3384b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result = buildGet();
3394b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
3404b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3414b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType resultType = result.get()->getType();
3424b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3434b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // That's the postfix result.
3444b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
3454b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = capture(result.take());
3464b9c2d235fb9449e249d74f48ecfec601650de93John McCall    setResultToLastSemantic();
3474b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Add or subtract a literal 1.
3504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
3514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
3524b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     GenericLoc);
3534b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3544b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (UnaryOperator::isIncrementOp(opcode)) {
3554b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
3564b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
3574b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
3584b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3594b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
3604b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3614b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Store that back into the result.  The value stored is the result
3624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // of a prefix operation.
3634b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildSet(result.take(), opcLoc,
3644b9c2d235fb9449e249d74f48ecfec601650de93John McCall             UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
3654b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
3664b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(result.take());
3674b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  UnaryOperator *syntactic =
3694b9c2d235fb9449e249d74f48ecfec601650de93John McCall    new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
3704b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                  VK_LValue, OK_Ordinary, opcLoc);
3714b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntactic);
3724b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3734b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3744b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3754b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
3764b9c2d235fb9449e249d74f48ecfec601650de93John McCall//  Objective-C @property and implicit property references
3774b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
3784b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3794b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Look up a method in the receiver type of an Objective-C property
3804b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference.
3813c3b7f90a863af43fa63043d396553ecf205351cJohn McCallstatic ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
3823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall                                            const ObjCPropertyRefExpr *PRE) {
3833c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  if (PRE->isObjectReceiver()) {
384aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    const ObjCObjectPointerType *PT =
385aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
3864b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3874b9c2d235fb9449e249d74f48ecfec601650de93John McCall    // Special case for 'self' in class method implementations.
3884b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (PT->isObjCClassType() &&
3894b9c2d235fb9449e249d74f48ecfec601650de93John McCall        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
3904b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // This cast is safe because isSelfExpr is only true within
3914b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // methods.
3924b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ObjCMethodDecl *method =
3934b9c2d235fb9449e249d74f48ecfec601650de93John McCall        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
3944b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.LookupMethodInObjectType(sel,
3954b9c2d235fb9449e249d74f48ecfec601650de93John McCall                 S.Context.getObjCInterfaceType(method->getClassInterface()),
3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        /*instance*/ false);
3974b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
3984b9c2d235fb9449e249d74f48ecfec601650de93John McCall
399aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
4003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
4013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
402aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  if (PRE->isSuperReceiver()) {
403aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    if (const ObjCObjectPointerType *PT =
404aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
405aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer      return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
406aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer
407aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
408aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  }
409aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer
410aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  assert(PRE->isClassReceiver() && "Invalid expression");
411aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
412aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  return S.LookupMethodInObjectType(sel, IT, false);
4133c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
4143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
4154b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findGetter() {
4164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Getter) return true;
4174b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4184b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Getter = LookupMethodInReceiverType(S, RefExpr->getGetterSelector(), RefExpr);
4194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return (Getter != 0);
4204b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4214b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4224b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to find the most accurate setter declaration for the property
4234b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference.
4244b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
4254b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if a setter was found, in which case Setter
4264b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findSetter() {
4274b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // For implicit properties, just trust the lookup we already did.
4284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isImplicitProperty()) {
4294b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
4304b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Setter = setter;
4314b9c2d235fb9449e249d74f48ecfec601650de93John McCall      SetterSelector = setter->getSelector();
4324b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return true;
4333c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    } else {
4344b9c2d235fb9449e249d74f48ecfec601650de93John McCall      IdentifierInfo *getterName =
4354b9c2d235fb9449e249d74f48ecfec601650de93John McCall        RefExpr->getImplicitPropertyGetter()->getSelector()
4364b9c2d235fb9449e249d74f48ecfec601650de93John McCall          .getIdentifierInfoForSlot(0);
4374b9c2d235fb9449e249d74f48ecfec601650de93John McCall      SetterSelector =
4384b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
4394b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           S.PP.getSelectorTable(),
4404b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           getterName);
4414b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return false;
4423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
4433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
4443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
4454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // For explicit properties, this is more involved.
4464b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
4474b9c2d235fb9449e249d74f48ecfec601650de93John McCall  SetterSelector = prop->getSetterName();
4484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do a normal method lookup first.
4504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCMethodDecl *setter =
4514b9c2d235fb9449e249d74f48ecfec601650de93John McCall        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
4524b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Setter = setter;
4534b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return true;
4544b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
4554b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4564b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // That can fail in the somewhat crazy situation that we're
4574b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // type-checking a message send within the @interface declaration
4584b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // that declared the @property.  But it's not clear that that's
4594b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // valuable to support.
4604b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4614b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return false;
4624b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4634b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4644b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the base object of an Objective-C property expression.
4654b9c2d235fb9449e249d74f48ecfec601650de93John McCallExpr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
4664b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(InstanceReceiver == 0);
4674b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If we have a base, capture it in an OVE and rebuild the syntactic
4694b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // form to use the OVE as its base.
4704b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isObjectReceiver()) {
4714b9c2d235fb9449e249d74f48ecfec601650de93John McCall    InstanceReceiver = capture(RefExpr->getBase());
4724b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4734b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntacticBase =
4744b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
4754b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
4764b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return syntacticBase;
4784b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4794b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4804b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Load from an Objective-C property reference.
4814b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildGet() {
4824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  findGetter();
4834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(Getter);
4843c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
4854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType receiverType;
4864b9c2d235fb9449e249d74f48ecfec601650de93John McCall  SourceLocation superLoc;
4874b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isClassReceiver()) {
4884b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
4894b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else if (RefExpr->isSuperReceiver()) {
4904b9c2d235fb9449e249d74f48ecfec601650de93John McCall    superLoc = RefExpr->getReceiverLocation();
4914b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = RefExpr->getSuperReceiverType();
4924b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
4934b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver);
4944b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = InstanceReceiver->getType();
4954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
4963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
4974b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Build a message-send.
4984b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult msg;
4994b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
5004b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver || RefExpr->isSuperReceiver());
5014b9c2d235fb9449e249d74f48ecfec601650de93John McCall    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
5024b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                 Getter->getSelector(), Getter,
5034b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                 GenericLoc, GenericLoc, GenericLoc,
5044b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                 MultiExprArg());
5054b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
5064b9c2d235fb9449e249d74f48ecfec601650de93John McCall    TypeSourceInfo *receiverTypeInfo = 0;
5074b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (!RefExpr->isSuperReceiver())
5084b9c2d235fb9449e249d74f48ecfec601650de93John McCall      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
5094b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5104b9c2d235fb9449e249d74f48ecfec601650de93John McCall    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
5114b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              Getter->getSelector(), Getter,
5124b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              GenericLoc, GenericLoc, GenericLoc,
5134b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              MultiExprArg());
5144b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5154b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return msg;
5163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
5173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5184b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Store to an Objective-C property reference.
5194b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
5204b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \param bindSetValueAsResult - If true, capture the actual
5214b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   value being set as the value of the property operation.
5224b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
5234b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           bool captureSetValueAsResult) {
5244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  bool hasSetter = findSetter();
5254b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(hasSetter); (void) hasSetter;
5264b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5274b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType receiverType;
5284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  SourceLocation superLoc;
5294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isClassReceiver()) {
5304b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
5314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else if (RefExpr->isSuperReceiver()) {
5324b9c2d235fb9449e249d74f48ecfec601650de93John McCall    superLoc = RefExpr->getReceiverLocation();
5334b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = RefExpr->getSuperReceiverType();
5344b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
5354b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver);
5364b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = InstanceReceiver->getType();
5374b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5394b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Use assignment constraints when possible; they give us better
5404b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // diagnostics.  "When possible" basically means anything except a
5414b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // C++ class type.
5424b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!S.getLangOptions().CPlusPlus || !op->getType()->isRecordType()) {
5434b9c2d235fb9449e249d74f48ecfec601650de93John McCall    QualType paramType = (*Setter->param_begin())->getType();
5444b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (!S.getLangOptions().CPlusPlus || !paramType->isRecordType()) {
5454b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ExprResult opResult = op;
5464b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Sema::AssignConvertType assignResult
5474b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = S.CheckSingleAssignmentConstraints(paramType, opResult);
5484b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
5494b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     op->getType(), opResult.get(),
5504b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     Sema::AA_Assigning))
5514b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return ExprError();
5524b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5534b9c2d235fb9449e249d74f48ecfec601650de93John McCall      op = opResult.take();
5544b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(op && "successful assignment left argument invalid?");
5553c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
5564b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5584b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Arguments.
5594b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *args[] = { op };
5603c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5614b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Build a message-send.
5624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult msg;
5634b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
5644b9c2d235fb9449e249d74f48ecfec601650de93John McCall    msg = S.BuildInstanceMessage(InstanceReceiver, receiverType, superLoc,
5654b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                 SetterSelector, Setter,
5664b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                 GenericLoc, GenericLoc, GenericLoc,
5674b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                 MultiExprArg(args, 1));
5684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
5694b9c2d235fb9449e249d74f48ecfec601650de93John McCall    TypeSourceInfo *receiverTypeInfo = 0;
5704b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (!RefExpr->isSuperReceiver())
5714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      receiverTypeInfo = S.Context.getTrivialTypeSourceInfo(receiverType);
5724b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5734b9c2d235fb9449e249d74f48ecfec601650de93John McCall    msg = S.BuildClassMessage(receiverTypeInfo, receiverType, superLoc,
5744b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              SetterSelector, Setter,
5754b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              GenericLoc, GenericLoc, GenericLoc,
5764b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              MultiExprArg(args, 1));
5774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!msg.isInvalid() && captureSetValueAsResult) {
5804b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMessageExpr *msgExpr =
5814b9c2d235fb9449e249d74f48ecfec601650de93John McCall      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
5824b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *arg = msgExpr->getArg(0);
5834b9c2d235fb9449e249d74f48ecfec601650de93John McCall    msgExpr->setArg(0, captureValueAsResult(arg));
5844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5864b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return msg;
5874b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
5884b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5894b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing lvalue-to-rvalue conversion.
5904b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
5914b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Explicit properties always have getters, but implicit ones don't.
5924b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Check that before proceeding.
5934b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isImplicitProperty() &&
5944b9c2d235fb9449e249d74f48ecfec601650de93John McCall      !RefExpr->getImplicitPropertyGetter()) {
5954b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
5964b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << RefExpr->getBase()->getType();
5974b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return ExprError();
5984b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5994b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6004b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
6014b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
6024b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6034b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
6044b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
6054b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                       Getter, RefExpr->getLocation());
6064b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // As a special case, if the method returns 'id', try to get
6084b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // a better type from the property.
6094b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
6104b9c2d235fb9449e249d74f48ecfec601650de93John McCall      result.get()->getType()->isObjCIdType()) {
6114b9c2d235fb9449e249d74f48ecfec601650de93John McCall    QualType propType = RefExpr->getExplicitProperty()->getType();
6124b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (const ObjCObjectPointerType *ptr
6134b9c2d235fb9449e249d74f48ecfec601650de93John McCall          = propType->getAs<ObjCObjectPointerType>()) {
6144b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (!ptr->isObjCIdType())
6154b9c2d235fb9449e249d74f48ecfec601650de93John McCall        result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
6163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
6174b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6184b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return result;
6203c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
6213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6224b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to build this as a call to a getter that returns a reference.
6234b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
6244b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if it was possible, whether or not it actually
6254b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   succeeded
6264b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
6274b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                   ExprResult &result) {
6284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!S.getLangOptions().CPlusPlus) return false;
6294b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6304b9c2d235fb9449e249d74f48ecfec601650de93John McCall  findGetter();
6314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(Getter && "property has no setter and no getter!");
6324b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6334b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Only do this if the getter returns an l-value reference type.
6344b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType resultType = Getter->getResultType();
6354b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!resultType->isLValueReferenceType()) return false;
6364b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6374b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildRValueOperation(op);
6384b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return true;
6394b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
6404b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing assignments.
6424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
6434b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
6444b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                SourceLocation opcLoc,
6454b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                BinaryOperatorKind opcode,
6464b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                Expr *LHS, Expr *RHS) {
6474b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(BinaryOperator::isAssignmentOp(opcode));
6483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6493c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there's no setter, we have no choice but to try to assign to
6503c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // the result of the getter.
6514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findSetter()) {
6524b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult result;
6534b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (tryBuildGetOfReference(LHS, result)) {
6544b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
6554b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
6563c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
6573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6583c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    // Otherwise, it's an error.
6594b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
6604b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(RefExpr->isImplicitProperty())
6614b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << SetterSelector
6624b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << LHS->getSourceRange() << RHS->getSourceRange();
6633c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
6643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
6653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6664b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If there is a setter, we definitely want to use it.
6674b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Verify that we can do a compound assignment.
6694b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (opcode != BO_Assign && !findGetter()) {
6704b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
6714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << LHS->getSourceRange() << RHS->getSourceRange();
6723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
6733c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
6743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6754b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result =
6764b9c2d235fb9449e249d74f48ecfec601650de93John McCall    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
6773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  if (result.isInvalid()) return ExprError();
6783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Various warnings about property assignments in ARC.
6804b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (S.getLangOptions().ObjCAutoRefCount && InstanceReceiver) {
6814b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
6824b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
6834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6844b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  return result;
6863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
6873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6884b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing increments and decrements.
6894b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
6904b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
6914b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                            UnaryOperatorKind opcode,
6924b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                            Expr *op) {
6933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there's no setter, we have no choice but to try to assign to
6943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // the result of the getter.
6954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findSetter()) {
6964b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult result;
6974b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (tryBuildGetOfReference(op, result)) {
6984b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
6994b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
7003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
7013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    // Otherwise, it's an error.
7034b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
7044b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(RefExpr->isImplicitProperty())
7054b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(UnaryOperator::isDecrementOp(opcode))
7064b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << SetterSelector
7074b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << op->getSourceRange();
7083c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
7093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
7103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there is a setter, we definitely want to use it.
7123c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7134b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // We also need a getter.
7144b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findGetter()) {
7154b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(RefExpr->isImplicitProperty());
7164b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
7174b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(UnaryOperator::isDecrementOp(opcode))
7184b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
7194b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << op->getSourceRange();
7204b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return ExprError();
7214b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7234b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
7244b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
7253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7264b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
7274b9c2d235fb9449e249d74f48ecfec601650de93John McCall//  General Sema routines.
7284b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
7293c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7304b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectRValue(Expr *E) {
7314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = E->IgnoreParens();
7324b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
7334b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
7344b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
7354b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildRValueOperation(E);
7364b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
7374b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
7383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
7394b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
7403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Check an increment or decrement of a pseudo-object expression.
7424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
7434b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         UnaryOperatorKind opcode, Expr *op) {
7444b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do nothing if the operand is dependent.
7454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (op->isTypeDependent())
7464b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
7474b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                       VK_RValue, OK_Ordinary, opcLoc);
7484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(UnaryOperator::isIncrementDecrementOp(opcode));
7504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = op->IgnoreParens();
7514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
7524b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
7534b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
7544b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
7554b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
7564b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
7573c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
7584b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
7593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7604b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
7614b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             BinaryOperatorKind opcode,
7624b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             Expr *LHS, Expr *RHS) {
7634b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do nothing if either argument is dependent.
7644b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (LHS->isTypeDependent() || RHS->isTypeDependent())
7654b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
7664b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        VK_RValue, OK_Ordinary, opcLoc);
7674b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Filter out non-overload placeholder types in the RHS.
7694b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (const BuiltinType *PTy = RHS->getType()->getAsPlaceholderType()) {
7704b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (PTy->getKind() != BuiltinType::Overload) {
7714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ExprResult result = CheckPlaceholderExpr(RHS);
7724b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
7734b9c2d235fb9449e249d74f48ecfec601650de93John McCall      RHS = result.take();
7744b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
7754b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = LHS->IgnoreParens();
7784b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
7794b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
7804b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
7814b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
7824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
7834b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
7844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
786