SemaPseudoObject.cpp revision 1e4691b9d8e1bdcc8ef62b323969d702c51b3c08
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"
3458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose#include "clang/Sema/ScopeInfo.h"
353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Sema/Initialization.h"
363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/AST/ExprObjC.h"
373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Lex/Preprocessor.h"
38b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian#include "llvm/ADT/SmallString.h"
393c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
403c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace clang;
413c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace sema;
423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
434b9c2d235fb9449e249d74f48ecfec601650de93John McCallnamespace {
444b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Basically just a very focused copy of TreeTransform.
454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  template <class T> struct Rebuilder {
464b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Sema &S;
474b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Rebuilder(Sema &S) : S(S) {}
484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
494b9c2d235fb9449e249d74f48ecfec601650de93John McCall    T &getDerived() { return static_cast<T&>(*this); }
504b9c2d235fb9449e249d74f48ecfec601650de93John McCall
514b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuild(Expr *e) {
524b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Fast path: nothing to look through.
534b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (typename T::specific_type *specific
544b9c2d235fb9449e249d74f48ecfec601650de93John McCall            = dyn_cast<typename T::specific_type>(e))
554b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return getDerived().rebuildSpecific(specific);
564b9c2d235fb9449e249d74f48ecfec601650de93John McCall
574b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Otherwise, we should look through and rebuild anything that
584b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // IgnoreParens would.
594b9c2d235fb9449e249d74f48ecfec601650de93John McCall
604b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
614b9c2d235fb9449e249d74f48ecfec601650de93John McCall        e = rebuild(parens->getSubExpr());
624b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) ParenExpr(parens->getLParen(),
634b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         parens->getRParen(),
644b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         e);
654b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
664b9c2d235fb9449e249d74f48ecfec601650de93John McCall
674b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
684b9c2d235fb9449e249d74f48ecfec601650de93John McCall        assert(uop->getOpcode() == UO_Extension);
694b9c2d235fb9449e249d74f48ecfec601650de93John McCall        e = rebuild(uop->getSubExpr());
704b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) UnaryOperator(e, uop->getOpcode(),
714b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getType(),
724b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getValueKind(),
734b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getObjectKind(),
744b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getOperatorLoc());
754b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
764b9c2d235fb9449e249d74f48ecfec601650de93John McCall
774b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
784b9c2d235fb9449e249d74f48ecfec601650de93John McCall        assert(!gse->isResultDependent());
794b9c2d235fb9449e249d74f48ecfec601650de93John McCall        unsigned resultIndex = gse->getResultIndex();
804b9c2d235fb9449e249d74f48ecfec601650de93John McCall        unsigned numAssocs = gse->getNumAssocs();
814b9c2d235fb9449e249d74f48ecfec601650de93John McCall
824b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SmallVector<Expr*, 8> assocs(numAssocs);
834b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
844b9c2d235fb9449e249d74f48ecfec601650de93John McCall
854b9c2d235fb9449e249d74f48ecfec601650de93John McCall        for (unsigned i = 0; i != numAssocs; ++i) {
864b9c2d235fb9449e249d74f48ecfec601650de93John McCall          Expr *assoc = gse->getAssocExpr(i);
874b9c2d235fb9449e249d74f48ecfec601650de93John McCall          if (i == resultIndex) assoc = rebuild(assoc);
884b9c2d235fb9449e249d74f48ecfec601650de93John McCall          assocs[i] = assoc;
894b9c2d235fb9449e249d74f48ecfec601650de93John McCall          assocTypes[i] = gse->getAssocTypeSourceInfo(i);
904b9c2d235fb9449e249d74f48ecfec601650de93John McCall        }
914b9c2d235fb9449e249d74f48ecfec601650de93John McCall
924b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) GenericSelectionExpr(S.Context,
934b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getGenericLoc(),
944b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getControllingExpr(),
953b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer                                                    assocTypes,
963b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer                                                    assocs,
974b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getDefaultLoc(),
984b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getRParenLoc(),
994b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      gse->containsUnexpandedParameterPack(),
1004b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    resultIndex);
1014b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1024b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1034b9c2d235fb9449e249d74f48ecfec601650de93John McCall      llvm_unreachable("bad expression to rebuild!");
1044b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1054b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
1064b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  struct ObjCPropertyRefRebuilder : Rebuilder<ObjCPropertyRefRebuilder> {
1084b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *NewBase;
1094b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyRefRebuilder(Sema &S, Expr *newBase)
110acf9e82fd34c0a125bf2aa8be1ab868082a7f06aBenjamin Kramer      : Rebuilder<ObjCPropertyRefRebuilder>(S), NewBase(newBase) {}
1114b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1124b9c2d235fb9449e249d74f48ecfec601650de93John McCall    typedef ObjCPropertyRefExpr specific_type;
1134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) {
1144b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Fortunately, the constraint that we're rebuilding something
1154b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // with a base limits the number of cases here.
1164b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(refExpr->getBase());
1174b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1184b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (refExpr->isExplicitProperty()) {
1194b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context)
1204b9c2d235fb9449e249d74f48ecfec601650de93John McCall          ObjCPropertyRefExpr(refExpr->getExplicitProperty(),
1214b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              refExpr->getType(), refExpr->getValueKind(),
1224b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              refExpr->getObjectKind(), refExpr->getLocation(),
1234b9c2d235fb9449e249d74f48ecfec601650de93John McCall                              NewBase);
1244b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1254b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return new (S.Context)
1264b9c2d235fb9449e249d74f48ecfec601650de93John McCall        ObjCPropertyRefExpr(refExpr->getImplicitPropertyGetter(),
1274b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            refExpr->getImplicitPropertySetter(),
1284b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            refExpr->getType(), refExpr->getValueKind(),
1294b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            refExpr->getObjectKind(),refExpr->getLocation(),
1304b9c2d235fb9449e249d74f48ecfec601650de93John McCall                            NewBase);
1314b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1324b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
1334b9c2d235fb9449e249d74f48ecfec601650de93John McCall
134ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  struct ObjCSubscriptRefRebuilder : Rebuilder<ObjCSubscriptRefRebuilder> {
135ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Expr *NewBase;
136ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Expr *NewKeyExpr;
137ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptRefRebuilder(Sema &S, Expr *newBase, Expr *newKeyExpr)
138ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    : Rebuilder<ObjCSubscriptRefRebuilder>(S),
139ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      NewBase(newBase), NewKeyExpr(newKeyExpr) {}
140ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
141ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    typedef ObjCSubscriptRefExpr specific_type;
142ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Expr *rebuildSpecific(ObjCSubscriptRefExpr *refExpr) {
143ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      assert(refExpr->getBaseExpr());
144ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      assert(refExpr->getKeyExpr());
145ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
146ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return new (S.Context)
147ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ObjCSubscriptRefExpr(NewBase,
148ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                             NewKeyExpr,
149ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                             refExpr->getType(), refExpr->getValueKind(),
150ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                             refExpr->getObjectKind(),refExpr->getAtIndexMethodDecl(),
151ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                             refExpr->setAtIndexMethodDecl(),
152ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                             refExpr->getRBracket());
153ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
154ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  };
155ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1564b9c2d235fb9449e249d74f48ecfec601650de93John McCall  class PseudoOpBuilder {
1574b9c2d235fb9449e249d74f48ecfec601650de93John McCall  public:
1584b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Sema &S;
1594b9c2d235fb9449e249d74f48ecfec601650de93John McCall    unsigned ResultIndex;
1604b9c2d235fb9449e249d74f48ecfec601650de93John McCall    SourceLocation GenericLoc;
1614b9c2d235fb9449e249d74f48ecfec601650de93John McCall    SmallVector<Expr *, 4> Semantics;
1624b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1634b9c2d235fb9449e249d74f48ecfec601650de93John McCall    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
1644b9c2d235fb9449e249d74f48ecfec601650de93John McCall      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
1654b9c2d235fb9449e249d74f48ecfec601650de93John McCall        GenericLoc(genericLoc) {}
1664b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1671aa1721f14f2162811f5393dbd84e01eadc2c963Matt Beaumont-Gay    virtual ~PseudoOpBuilder() {}
1681aa1721f14f2162811f5393dbd84e01eadc2c963Matt Beaumont-Gay
1694b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Add a normal semantic expression.
1704b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void addSemanticExpr(Expr *semantic) {
1714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Semantics.push_back(semantic);
1724b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1734b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1744b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Add the 'result' semantic expression.
1754b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void addResultSemanticExpr(Expr *resultExpr) {
1764b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(ResultIndex == PseudoObjectExpr::NoResult);
1774b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ResultIndex = Semantics.size();
1784b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Semantics.push_back(resultExpr);
1794b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1804b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1814b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildRValueOperation(Expr *op);
1824b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildAssignmentOperation(Scope *Sc,
1834b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        SourceLocation opLoc,
1844b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        BinaryOperatorKind opcode,
1854b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        Expr *LHS, Expr *RHS);
1864b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
1874b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    UnaryOperatorKind opcode,
1884b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    Expr *op);
1894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
19058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    virtual ExprResult complete(Expr *syntacticForm);
1914b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1924b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *capture(Expr *op);
1934b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *captureValueAsResult(Expr *op);
1944b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1954b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void setResultToLastSemantic() {
1964b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(ResultIndex == PseudoObjectExpr::NoResult);
1974b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ResultIndex = Semantics.size() - 1;
1984b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1994b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2004b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Return true if assignments have a non-void result.
2014b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual bool assignmentsHaveResult() { return true; }
2024b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2034b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
2044b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual ExprResult buildGet() = 0;
2054b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual ExprResult buildSet(Expr *, SourceLocation,
2064b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                bool captureSetValueAsResult) = 0;
2074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
2084b9c2d235fb9449e249d74f48ecfec601650de93John McCall
209e23fb90712233bdfa04387e48b54a7168e23cb3eDmitri Gribenko  /// A PseudoOpBuilder for Objective-C \@properties.
2104b9c2d235fb9449e249d74f48ecfec601650de93John McCall  class ObjCPropertyOpBuilder : public PseudoOpBuilder {
2114b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyRefExpr *RefExpr;
212b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    ObjCPropertyRefExpr *SyntacticRefExpr;
2134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *InstanceReceiver;
2144b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMethodDecl *Getter;
2154b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2164b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMethodDecl *Setter;
2174b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Selector SetterSelector;
218a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    Selector GetterSelector;
2194b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2204b9c2d235fb9449e249d74f48ecfec601650de93John McCall  public:
2214b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
2224b9c2d235fb9449e249d74f48ecfec601650de93John McCall      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
223b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis      SyntacticRefExpr(0), InstanceReceiver(0), Getter(0), Setter(0) {
2244b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
2254b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2264b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildRValueOperation(Expr *op);
2274b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildAssignmentOperation(Scope *Sc,
2284b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        SourceLocation opLoc,
2294b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        BinaryOperatorKind opcode,
2304b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        Expr *LHS, Expr *RHS);
2314b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
2324b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    UnaryOperatorKind opcode,
2334b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    Expr *op);
2344b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2354b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool tryBuildGetOfReference(Expr *op, ExprResult &result);
236b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian    bool findSetter(bool warn=true);
2374b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool findGetter();
2384b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2394b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuildAndCaptureObject(Expr *syntacticBase);
2404b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildGet();
2414b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildSet(Expr *op, SourceLocation, bool);
24258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    ExprResult complete(Expr *SyntacticForm);
24358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
24458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    bool isWeakProperty() const;
2454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
246ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
247ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
248ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek class ObjCSubscriptOpBuilder : public PseudoOpBuilder {
249ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ObjCSubscriptRefExpr *RefExpr;
250ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   OpaqueValueExpr *InstanceBase;
251ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   OpaqueValueExpr *InstanceKey;
252ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ObjCMethodDecl *AtIndexGetter;
253ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   Selector AtIndexGetterSelector;
254ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
255ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ObjCMethodDecl *AtIndexSetter;
256ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   Selector AtIndexSetterSelector;
257ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
258ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek public:
259ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
260ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
261ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      RefExpr(refExpr),
262ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    InstanceBase(0), InstanceKey(0),
263ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetter(0), AtIndexSetter(0) { }
264ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
265ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ExprResult buildRValueOperation(Expr *op);
266ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ExprResult buildAssignmentOperation(Scope *Sc,
267ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       SourceLocation opLoc,
268ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       BinaryOperatorKind opcode,
269ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       Expr *LHS, Expr *RHS);
270ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   Expr *rebuildAndCaptureObject(Expr *syntacticBase);
271ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
272ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   bool findAtIndexGetter();
273ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   bool findAtIndexSetter();
274ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
275ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ExprResult buildGet();
276ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ExprResult buildSet(Expr *op, SourceLocation, bool);
277ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek };
278ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
2794b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2804b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2814b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression in an OpaqueValueExpr.
2824b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
2834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Make a new OVE whose source is the given expression.
2844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  OpaqueValueExpr *captured =
2854b9c2d235fb9449e249d74f48ecfec601650de93John McCall    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
28697df54e0c075bc8d6a869597e771dad0c11a2180Douglas Gregor                                    e->getValueKind(), e->getObjectKind(),
28797df54e0c075bc8d6a869597e771dad0c11a2180Douglas Gregor                                    e);
2884b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2894b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Make sure we bind that in the semantics.
2904b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(captured);
2914b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return captured;
2924b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
2934b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2944b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression as the result of this pseudo-object
2954b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation.  This routine is safe against expressions which may
2964b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// already be captured.
2974b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
29870517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \returns the captured expression, which will be the
2994b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   same as the input if the input was already captured
3004b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
3014b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(ResultIndex == PseudoObjectExpr::NoResult);
3024b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3034b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If the expression hasn't already been captured, just capture it
3044b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // and set the new semantic
3054b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!isa<OpaqueValueExpr>(e)) {
3064b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *cap = capture(e);
3074b9c2d235fb9449e249d74f48ecfec601650de93John McCall    setResultToLastSemantic();
3084b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return cap;
3094b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3104b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3114b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Otherwise, it must already be one of our semantic expressions;
3124b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // set ResultIndex to its index.
3134b9c2d235fb9449e249d74f48ecfec601650de93John McCall  unsigned index = 0;
3144b9c2d235fb9449e249d74f48ecfec601650de93John McCall  for (;; ++index) {
3154b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(index < Semantics.size() &&
3164b9c2d235fb9449e249d74f48ecfec601650de93John McCall           "captured expression not found in semantics!");
3174b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (e == Semantics[index]) break;
3184b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ResultIndex = index;
3204b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return cast<OpaqueValueExpr>(e);
3214b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3224b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3234b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The routine which creates the final PseudoObjectExpr.
3244b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::complete(Expr *syntactic) {
3254b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return PseudoObjectExpr::Create(S.Context, syntactic,
3264b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                  Semantics, ResultIndex);
3274b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3284b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3294b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The main skeleton for building an r-value operation.
3304b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
3314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticBase = rebuildAndCaptureObject(op);
3324b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3334b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult getExpr = buildGet();
3344b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (getExpr.isInvalid()) return ExprError();
3354b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addResultSemanticExpr(getExpr.take());
3364b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3374b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntacticBase);
3384b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3394b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3404b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building a simple or compound
3414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// assignment operation.
3424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
3434b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
3444b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                          BinaryOperatorKind opcode,
3454b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                          Expr *LHS, Expr *RHS) {
3464b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(BinaryOperator::isAssignmentOp(opcode));
3474b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3484b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
3494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  OpaqueValueExpr *capturedRHS = capture(RHS);
3504b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntactic;
3524b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3534b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result;
3544b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (opcode == BO_Assign) {
3554b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = capturedRHS;
3564b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
3574b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               opcode, capturedRHS->getType(),
3584b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               capturedRHS->getValueKind(),
359be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                               OK_Ordinary, opcLoc, false);
3604b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
3614b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult opLHS = buildGet();
3624b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (opLHS.isInvalid()) return ExprError();
3634b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3644b9c2d235fb9449e249d74f48ecfec601650de93John McCall    // Build an ordinary, non-compound operation.
3654b9c2d235fb9449e249d74f48ecfec601650de93John McCall    BinaryOperatorKind nonCompound =
3664b9c2d235fb9449e249d74f48ecfec601650de93John McCall      BinaryOperator::getOpForCompoundAssignment(opcode);
3674b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = S.BuildBinOp(Sc, opcLoc, nonCompound,
3684b9c2d235fb9449e249d74f48ecfec601650de93John McCall                          opLHS.take(), capturedRHS);
3694b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (result.isInvalid()) return ExprError();
3704b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3714b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntactic =
3724b9c2d235fb9449e249d74f48ecfec601650de93John McCall      new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
3734b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getType(),
3744b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getValueKind(),
3754b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             OK_Ordinary,
3764b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             opLHS.get()->getType(),
3774b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getType(),
378be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                             opcLoc, false);
3794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3804b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3814b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // The result of the assignment, if not void, is the value set into
3824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // the l-value.
3834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildSet(result.take(), opcLoc, assignmentsHaveResult());
3844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
3854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(result.take());
3864b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3874b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntactic);
3884b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3904b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building an increment or decrement
3914b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation.
3924b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
3934b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
3944b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      UnaryOperatorKind opcode,
3954b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      Expr *op) {
3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(UnaryOperator::isIncrementDecrementOp(opcode));
3974b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3984b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticOp = rebuildAndCaptureObject(op);
3994b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4004b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Load the value.
4014b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result = buildGet();
4024b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
4034b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4044b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType resultType = result.get()->getType();
4054b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4064b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // That's the postfix result.
4074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) {
4084b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = capture(result.take());
4094b9c2d235fb9449e249d74f48ecfec601650de93John McCall    setResultToLastSemantic();
4104b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
4114b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4124b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Add or subtract a literal 1.
4134b9c2d235fb9449e249d74f48ecfec601650de93John McCall  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
4144b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
4154b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     GenericLoc);
4164b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4174b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (UnaryOperator::isIncrementOp(opcode)) {
4184b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.take(), one);
4194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
4204b9c2d235fb9449e249d74f48ecfec601650de93John McCall    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.take(), one);
4214b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
4224b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
4234b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Store that back into the result.  The value stored is the result
4254b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // of a prefix operation.
4264b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildSet(result.take(), opcLoc,
4274b9c2d235fb9449e249d74f48ecfec601650de93John McCall             UnaryOperator::isPrefix(opcode) && assignmentsHaveResult());
4284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
4294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(result.take());
4304b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  UnaryOperator *syntactic =
4324b9c2d235fb9449e249d74f48ecfec601650de93John McCall    new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
4334b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                  VK_LValue, OK_Ordinary, opcLoc);
4344b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntactic);
4354b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4364b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4374b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4384b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
4394b9c2d235fb9449e249d74f48ecfec601650de93John McCall//  Objective-C @property and implicit property references
4404b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
4414b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4424b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Look up a method in the receiver type of an Objective-C property
4434b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference.
4443c3b7f90a863af43fa63043d396553ecf205351cJohn McCallstatic ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
4453c3b7f90a863af43fa63043d396553ecf205351cJohn McCall                                            const ObjCPropertyRefExpr *PRE) {
4463c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  if (PRE->isObjectReceiver()) {
447aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    const ObjCObjectPointerType *PT =
448aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
4494b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4504b9c2d235fb9449e249d74f48ecfec601650de93John McCall    // Special case for 'self' in class method implementations.
4514b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (PT->isObjCClassType() &&
4524b9c2d235fb9449e249d74f48ecfec601650de93John McCall        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
4534b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // This cast is safe because isSelfExpr is only true within
4544b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // methods.
4554b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ObjCMethodDecl *method =
4564b9c2d235fb9449e249d74f48ecfec601650de93John McCall        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
4574b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.LookupMethodInObjectType(sel,
4584b9c2d235fb9449e249d74f48ecfec601650de93John McCall                 S.Context.getObjCInterfaceType(method->getClassInterface()),
4594b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        /*instance*/ false);
4604b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
4614b9c2d235fb9449e249d74f48ecfec601650de93John McCall
462aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
4633c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
4643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
465aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  if (PRE->isSuperReceiver()) {
466aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    if (const ObjCObjectPointerType *PT =
467aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
468aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer      return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
469aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer
470aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
471aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  }
472aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer
473aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  assert(PRE->isClassReceiver() && "Invalid expression");
474aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
475aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  return S.LookupMethodInObjectType(sel, IT, false);
4763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
4773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
47858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosebool ObjCPropertyOpBuilder::isWeakProperty() const {
47958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  QualType T;
48058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  if (RefExpr->isExplicitProperty()) {
48158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();
48258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
48358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose      return true;
48458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
48558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    T = Prop->getType();
48658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  } else if (Getter) {
48758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    T = Getter->getResultType();
48858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  } else {
48958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    return false;
49058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  }
49158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
49258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  return T.getObjCLifetime() == Qualifiers::OCL_Weak;
49358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose}
49458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
4954b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findGetter() {
4964b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Getter) return true;
4974b9c2d235fb9449e249d74f48ecfec601650de93John McCall
498dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  // For implicit properties, just trust the lookup we already did.
499dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  if (RefExpr->isImplicitProperty()) {
500a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    if ((Getter = RefExpr->getImplicitPropertyGetter())) {
501a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      GetterSelector = Getter->getSelector();
502a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      return true;
503a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    }
504a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    else {
505a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      // Must build the getter selector the hard way.
506a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
507a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      assert(setter && "both setter and getter are null - cannot happen");
508a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      IdentifierInfo *setterName =
509a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian        setter->getSelector().getIdentifierInfoForSlot(0);
510a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      const char *compStr = setterName->getNameStart();
511a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      compStr += 3;
512a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
513a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      GetterSelector =
514a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian        S.PP.getSelectorTable().getNullarySelector(getterName);
515a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      return false;
516a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian
517a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    }
518dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  }
519dc4df51d32dea56fbec79037570832dffbcc14e6John McCall
520dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
521dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
5224b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return (Getter != 0);
5234b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
5244b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5254b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to find the most accurate setter declaration for the property
5264b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference.
5274b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
5284b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if a setter was found, in which case Setter
529b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanianbool ObjCPropertyOpBuilder::findSetter(bool warn) {
5304b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // For implicit properties, just trust the lookup we already did.
5314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isImplicitProperty()) {
5324b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
5334b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Setter = setter;
5344b9c2d235fb9449e249d74f48ecfec601650de93John McCall      SetterSelector = setter->getSelector();
5354b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return true;
5363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    } else {
5374b9c2d235fb9449e249d74f48ecfec601650de93John McCall      IdentifierInfo *getterName =
5384b9c2d235fb9449e249d74f48ecfec601650de93John McCall        RefExpr->getImplicitPropertyGetter()->getSelector()
5394b9c2d235fb9449e249d74f48ecfec601650de93John McCall          .getIdentifierInfoForSlot(0);
5404b9c2d235fb9449e249d74f48ecfec601650de93John McCall      SetterSelector =
5414b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
5424b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           S.PP.getSelectorTable(),
5434b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           getterName);
5444b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return false;
5453c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
5463c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
5473c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
5484b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // For explicit properties, this is more involved.
5494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
5504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  SetterSelector = prop->getSetterName();
5514b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5524b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do a normal method lookup first.
5534b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCMethodDecl *setter =
5544b9c2d235fb9449e249d74f48ecfec601650de93John McCall        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
5551e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose    if (setter->isPropertyAccessor() && warn)
556b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian      if (const ObjCInterfaceDecl *IFace =
557b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian          dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
558b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        const StringRef thisPropertyName(prop->getName());
559b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        char front = thisPropertyName.front();
560b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        front = islower(front) ? toupper(front) : tolower(front);
561b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        SmallString<100> PropertyName = thisPropertyName;
562b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        PropertyName[0] = front;
563b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
564b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember))
565b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian          if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
566cba0ebce65667f76e291346d377f402579743ceaFariborz Jahanian            S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
567b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian              << prop->getName() << prop1->getName() << setter->getSelector();
568b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian            S.Diag(prop->getLocation(), diag::note_property_declare);
569b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian            S.Diag(prop1->getLocation(), diag::note_property_declare);
570b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian          }
571b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian      }
5724b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Setter = setter;
5734b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return true;
5744b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5754b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5764b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // That can fail in the somewhat crazy situation that we're
5774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // type-checking a message send within the @interface declaration
5784b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // that declared the @property.  But it's not clear that that's
5794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // valuable to support.
5804b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5814b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return false;
5824b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
5834b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5844b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the base object of an Objective-C property expression.
5854b9c2d235fb9449e249d74f48ecfec601650de93John McCallExpr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
5864b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(InstanceReceiver == 0);
5874b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5884b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If we have a base, capture it in an OVE and rebuild the syntactic
5894b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // form to use the OVE as its base.
5904b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isObjectReceiver()) {
5914b9c2d235fb9449e249d74f48ecfec601650de93John McCall    InstanceReceiver = capture(RefExpr->getBase());
5924b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5934b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntacticBase =
5944b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ObjCPropertyRefRebuilder(S, InstanceReceiver).rebuild(syntacticBase);
5954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5964b9c2d235fb9449e249d74f48ecfec601650de93John McCall
597b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis  if (ObjCPropertyRefExpr *
598b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis        refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
599b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    SyntacticRefExpr = refE;
600b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
6014b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return syntacticBase;
6024b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
6034b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6044b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Load from an Objective-C property reference.
6054b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildGet() {
6064b9c2d235fb9449e249d74f48ecfec601650de93John McCall  findGetter();
6074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(Getter);
608b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
609b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis  if (SyntacticRefExpr)
610b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    SyntacticRefExpr->setIsMessagingGetter();
611b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
6124b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType receiverType;
6134b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isClassReceiver()) {
6144b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
6154b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else if (RefExpr->isSuperReceiver()) {
6164b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = RefExpr->getSuperReceiverType();
6174b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
6184b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver);
6194b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = InstanceReceiver->getType();
6204b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6213c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6224b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Build a message-send.
6234b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult msg;
6244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Getter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
6254b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver || RefExpr->isSuperReceiver());
626746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
627746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         GenericLoc, Getter->getSelector(),
628746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         Getter, MultiExprArg());
6294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
630746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
631746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      GenericLoc,
632746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      Getter->getSelector(), Getter,
633746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      MultiExprArg());
6344b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6354b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return msg;
6363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
6373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6384b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Store to an Objective-C property reference.
6394b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
64070517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \param captureSetValueAsResult If true, capture the actual
6414b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   value being set as the value of the property operation.
6424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
6434b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           bool captureSetValueAsResult) {
644b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian  bool hasSetter = findSetter(false);
6454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(hasSetter); (void) hasSetter;
6464b9c2d235fb9449e249d74f48ecfec601650de93John McCall
647b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis  if (SyntacticRefExpr)
648b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    SyntacticRefExpr->setIsMessagingSetter();
649b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
6504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType receiverType;
6514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isClassReceiver()) {
6524b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = S.Context.getObjCInterfaceType(RefExpr->getClassReceiver());
6534b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else if (RefExpr->isSuperReceiver()) {
6544b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = RefExpr->getSuperReceiverType();
6554b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
6564b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver);
6574b9c2d235fb9449e249d74f48ecfec601650de93John McCall    receiverType = InstanceReceiver->getType();
6584b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6604b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Use assignment constraints when possible; they give us better
6614b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // diagnostics.  "When possible" basically means anything except a
6624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // C++ class type.
6634e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
6644b9c2d235fb9449e249d74f48ecfec601650de93John McCall    QualType paramType = (*Setter->param_begin())->getType();
6654e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
6664b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ExprResult opResult = op;
6674b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Sema::AssignConvertType assignResult
6684b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = S.CheckSingleAssignmentConstraints(paramType, opResult);
6694b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
6704b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     op->getType(), opResult.get(),
6714b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     Sema::AA_Assigning))
6724b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return ExprError();
6734b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6744b9c2d235fb9449e249d74f48ecfec601650de93John McCall      op = opResult.take();
6754b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(op && "successful assignment left argument invalid?");
6763c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
6774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6783c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Arguments.
6804b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *args[] = { op };
6813c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Build a message-send.
6834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult msg;
6844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Setter->isInstanceMethod() || RefExpr->isObjectReceiver()) {
685746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
686746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         GenericLoc, SetterSelector, Setter,
687746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         MultiExprArg(args, 1));
6884b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
689746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
690746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      GenericLoc,
691746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      SetterSelector, Setter,
692746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      MultiExprArg(args, 1));
6934b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!msg.isInvalid() && captureSetValueAsResult) {
6964b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMessageExpr *msgExpr =
6974b9c2d235fb9449e249d74f48ecfec601650de93John McCall      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
6984b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *arg = msgExpr->getArg(0);
6994b9c2d235fb9449e249d74f48ecfec601650de93John McCall    msgExpr->setArg(0, captureValueAsResult(arg));
7004b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7024b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return msg;
7034b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
7044b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7054b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing lvalue-to-rvalue conversion.
7064b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
7074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Explicit properties always have getters, but implicit ones don't.
7084b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Check that before proceeding.
7094b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isImplicitProperty() &&
7104b9c2d235fb9449e249d74f48ecfec601650de93John McCall      !RefExpr->getImplicitPropertyGetter()) {
7114b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
7124b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << RefExpr->getBase()->getType();
7134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return ExprError();
7144b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7154b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
7174b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
7184b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
7204b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
7214b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                       Getter, RefExpr->getLocation());
7224b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7234b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // As a special case, if the method returns 'id', try to get
7244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // a better type from the property.
7254b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isExplicitProperty() && result.get()->isRValue() &&
7264b9c2d235fb9449e249d74f48ecfec601650de93John McCall      result.get()->getType()->isObjCIdType()) {
7274b9c2d235fb9449e249d74f48ecfec601650de93John McCall    QualType propType = RefExpr->getExplicitProperty()->getType();
7284b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (const ObjCObjectPointerType *ptr
7294b9c2d235fb9449e249d74f48ecfec601650de93John McCall          = propType->getAs<ObjCObjectPointerType>()) {
7304b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (!ptr->isObjCIdType())
7314b9c2d235fb9449e249d74f48ecfec601650de93John McCall        result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
7323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
7334b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7344b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7354b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return result;
7363c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
7373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7384b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to build this as a call to a getter that returns a reference.
7394b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
7404b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if it was possible, whether or not it actually
7414b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   succeeded
7424b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
7434b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                   ExprResult &result) {
7444e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!S.getLangOpts().CPlusPlus) return false;
7454b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7464b9c2d235fb9449e249d74f48ecfec601650de93John McCall  findGetter();
7474b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(Getter && "property has no setter and no getter!");
7484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Only do this if the getter returns an l-value reference type.
7504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType resultType = Getter->getResultType();
7514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!resultType->isLValueReferenceType()) return false;
7524b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7534b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildRValueOperation(op);
7544b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return true;
7554b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
7564b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7574b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing assignments.
7584b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
7594b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
7604b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                SourceLocation opcLoc,
7614b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                BinaryOperatorKind opcode,
7624b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                Expr *LHS, Expr *RHS) {
7634b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(BinaryOperator::isAssignmentOp(opcode));
7643c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7653c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there's no setter, we have no choice but to try to assign to
7663c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // the result of the getter.
7674b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findSetter()) {
7684b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult result;
7694b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (tryBuildGetOfReference(LHS, result)) {
7704b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
7714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.BuildBinOp(Sc, opcLoc, opcode, result.take(), RHS);
7723c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
7733c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    // Otherwise, it's an error.
7754b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
7764b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(RefExpr->isImplicitProperty())
7774b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << SetterSelector
7784b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << LHS->getSourceRange() << RHS->getSourceRange();
7793c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
7803c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
7813c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If there is a setter, we definitely want to use it.
7834b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Verify that we can do a compound assignment.
7854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (opcode != BO_Assign && !findGetter()) {
7864b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
7874b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << LHS->getSourceRange() << RHS->getSourceRange();
7883c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
7893c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
7903c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7914b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result =
7924b9c2d235fb9449e249d74f48ecfec601650de93John McCall    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
7933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  if (result.isInvalid()) return ExprError();
7943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Various warnings about property assignments in ARC.
7964e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
7974b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
7984b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
7994b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
8004b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  return result;
8023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
8033c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8044b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing increments and decrements.
8054b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
8064b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
8074b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                            UnaryOperatorKind opcode,
8084b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                            Expr *op) {
8093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there's no setter, we have no choice but to try to assign to
8103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // the result of the getter.
8114b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findSetter()) {
8124b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult result;
8134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (tryBuildGetOfReference(op, result)) {
8144b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
8154b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.take());
8163c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
8173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8183c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    // Otherwise, it's an error.
8194b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
8204b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(RefExpr->isImplicitProperty())
8214b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(UnaryOperator::isDecrementOp(opcode))
8224b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << SetterSelector
8234b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << op->getSourceRange();
8243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
8253c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
8263c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there is a setter, we definitely want to use it.
8283c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // We also need a getter.
8304b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findGetter()) {
8314b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(RefExpr->isImplicitProperty());
8324b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
8334b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(UnaryOperator::isDecrementOp(opcode))
834a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      << GetterSelector
8354b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << op->getSourceRange();
8364b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return ExprError();
8374b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
8383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8394b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
8404b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
8413c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
84258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan RoseExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
84358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) {
84458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    DiagnosticsEngine::Level Level =
84558b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose      S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
84658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose                                 SyntacticForm->getLocStart());
84758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    if (Level != DiagnosticsEngine::Ignored)
8487a2704800943fbb69207e125d28186278712af36Jordan Rose      S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
8497a2704800943fbb69207e125d28186278712af36Jordan Rose                                         SyntacticRefExpr->isMessagingGetter());
85058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  }
85158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
85258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  return PseudoOpBuilder::complete(SyntacticForm);
85358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose}
85458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
855ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// ObjCSubscript build stuff.
856ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek//
857ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
858ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
859ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// conversion.
860ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// FIXME. Remove this routine if it is proven that no additional
861ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// specifity is needed.
862ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
863ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
864ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (result.isInvalid()) return ExprError();
865ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return result;
866ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
867ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
868ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// objective-c subscripting-specific  behavior for doing assignments.
869ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult
870ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
871ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation opcLoc,
872ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                BinaryOperatorKind opcode,
873ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                Expr *LHS, Expr *RHS) {
874ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  assert(BinaryOperator::isAssignmentOp(opcode));
875ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // There must be a method to do the Index'ed assignment.
876ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!findAtIndexSetter())
877ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
878ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
879ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Verify that we can do a compound assignment.
880ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (opcode != BO_Assign && !findAtIndexGetter())
881ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
882ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
883ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult result =
884ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
885ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (result.isInvalid()) return ExprError();
886ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
887ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Various warnings about objc Index'ed assignments in ARC.
8884e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
889ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
890ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
891ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
892ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
893ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return result;
894ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
895ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
896ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// Capture the base object of an Objective-C Index'ed expression.
897ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExpr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
898ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  assert(InstanceBase == 0);
899ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
900ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Capture base expression in an OVE and rebuild the syntactic
901ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // form to use the OVE as its base expression.
902ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  InstanceBase = capture(RefExpr->getBaseExpr());
903ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  InstanceKey = capture(RefExpr->getKeyExpr());
904ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
905ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  syntacticBase =
906ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptRefRebuilder(S, InstanceBase,
907ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                              InstanceKey).rebuild(syntacticBase);
908ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
909ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return syntacticBase;
910ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
911ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
912ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// CheckSubscriptingKind - This routine decide what type
913ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// of indexing represented by "FromE" is being done.
914ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekSema::ObjCSubscriptKind
915ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Sema::CheckSubscriptingKind(Expr *FromE) {
916ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // If the expression already has integral or enumeration type, we're golden.
917ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType T = FromE->getType();
918ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (T->isIntegralOrEnumerationType())
919ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Array;
920ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
921ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // If we don't have a class type in C++, there's no way we can get an
922ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // expression of integral or enumeration type.
923ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  const RecordType *RecordTy = T->getAs<RecordType>();
924a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian  if (!RecordTy && T->isObjCObjectPointerType())
925ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // All other scalar cases are assumed to be dictionary indexing which
926ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // caller handles, with diagnostics if needed.
927ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Dictionary;
928a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian  if (!getLangOpts().CPlusPlus ||
929a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian      !RecordTy || RecordTy->isIncompleteType()) {
930ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // No indexing can be done. Issue diagnostics and quit.
931a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian    const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
932a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian    if (isa<StringLiteral>(IndexExpr))
933a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian      Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
934a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian        << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
935a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian    else
936a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian      Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
937a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian        << T;
938ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Error;
939ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
940ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
941ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // We must have a complete class type.
942ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (RequireCompleteType(FromE->getExprLoc(), T,
943d10099e5c8238fa0327f03921cf2e3c8975c881eDouglas Gregor                          diag::err_objc_index_incomplete_class_type, FromE))
944ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Error;
945ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
946ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Look for a conversion to an integral, enumeration type, or
947ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // objective-C pointer type.
948ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  UnresolvedSet<4> ViableConversions;
949ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  UnresolvedSet<4> ExplicitConversions;
950ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  const UnresolvedSetImpl *Conversions
951ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
952ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
953ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  int NoIntegrals=0, NoObjCIdPointers=0;
954ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  SmallVector<CXXConversionDecl *, 4> ConversionDecls;
955ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
956ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  for (UnresolvedSetImpl::iterator I = Conversions->begin(),
957ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek       E = Conversions->end();
958ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek       I != E;
959ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek       ++I) {
960ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (CXXConversionDecl *Conversion
961ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
962ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      QualType CT = Conversion->getConversionType().getNonReferenceType();
963ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      if (CT->isIntegralOrEnumerationType()) {
964ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ++NoIntegrals;
965ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ConversionDecls.push_back(Conversion);
966ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      }
967ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
968ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ++NoObjCIdPointers;
969ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ConversionDecls.push_back(Conversion);
970ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      }
971ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
972ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
973ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (NoIntegrals ==1 && NoObjCIdPointers == 0)
974ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Array;
975ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (NoIntegrals == 0 && NoObjCIdPointers == 1)
976ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Dictionary;
977ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
978ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // No conversion function was found. Issue diagnostic and return.
979ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
980ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << FromE->getType();
981ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Error;
982ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
983ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
984ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << FromE->getType();
985ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  for (unsigned int i = 0; i < ConversionDecls.size(); i++)
986ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
987ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
988ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return OS_Error;
989ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
990ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
991dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
992dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian/// objects used as dictionary subscript key objects.
993dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanianstatic void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
994dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                         Expr *Key) {
995dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (ContainerT.isNull())
996dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    return;
997dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  // dictionary subscripting.
998dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  // - (id)objectForKeyedSubscript:(id)key;
999dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  IdentifierInfo *KeyIdents[] = {
1000dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    &S.Context.Idents.get("objectForKeyedSubscript")
1001dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  };
1002dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1003dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
1004dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                                      true /*instance*/);
1005dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (!Getter)
1006dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    return;
1007dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  QualType T = Getter->param_begin()[0]->getType();
1008dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  S.CheckObjCARCConversion(Key->getSourceRange(),
1009dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                         T, Key, Sema::CCK_ImplicitConversion);
1010dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian}
1011dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian
1012ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenekbool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1013ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexGetter)
1014ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return true;
1015ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1016ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *BaseExpr = RefExpr->getBaseExpr();
1017ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType BaseT = BaseExpr->getType();
1018ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1019ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType ResultType;
1020ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (const ObjCObjectPointerType *PTy =
1021ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      BaseT->getAs<ObjCObjectPointerType>()) {
1022ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ResultType = PTy->getPointeeType();
1023ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (const ObjCObjectType *iQFaceTy =
1024ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ResultType->getAsObjCQualifiedInterfaceType())
1025ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      ResultType = iQFaceTy->getBaseType();
1026ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1027ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Sema::ObjCSubscriptKind Res =
1028ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1029dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (Res == Sema::OS_Error) {
1030dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    if (S.getLangOpts().ObjCAutoRefCount)
1031dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian      CheckKeyForObjCARCConversion(S, ResultType,
1032dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                   RefExpr->getKeyExpr());
1033ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1034dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  }
1035ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool arrayRef = (Res == Sema::OS_Array);
1036ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1037ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (ResultType.isNull()) {
1038ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1039ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << arrayRef;
1040ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1041ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1042ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!arrayRef) {
1043ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // dictionary subscripting.
1044ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (id)objectForKeyedSubscript:(id)key;
1045ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1046ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("objectForKeyedSubscript")
1047ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1048ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1049ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1050ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else {
1051ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (id)objectAtIndexedSubscript:(size_t)index;
1052ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1053ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("objectAtIndexedSubscript")
1054ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1055ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1056ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1057ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1058ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1059ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
1060ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                             true /*instance*/);
1061ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool receiverIdType = (BaseT->isObjCIdType() ||
1062ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                         BaseT->isObjCQualifiedIdType());
1063ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
10644e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
1065ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1066ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           SourceLocation(), AtIndexGetterSelector,
1067ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           S.Context.getObjCIdType() /*ReturnType*/,
1068ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           0 /*TypeSourceInfo */,
1069ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           S.Context.getTranslationUnitDecl(),
1070ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           true /*Instance*/, false/*isVariadic*/,
10711e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose                           /*isPropertyAccessor=*/false,
1072ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1073ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           ObjCMethodDecl::Required,
1074ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           false);
1075ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1076ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation(), SourceLocation(),
1077ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ? &S.Context.Idents.get("index")
1078ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         : &S.Context.Idents.get("key"),
1079ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ? S.Context.UnsignedLongTy
1080ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         : S.Context.getObjCIdType(),
1081ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                /*TInfo=*/0,
1082ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
1083ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
1084ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                0);
1085ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetter->setMethodParams(S.Context, Argument,
1086ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                   ArrayRef<SourceLocation>());
1087ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1088ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1089ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!AtIndexGetter) {
1090ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!receiverIdType) {
1091ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1092ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << 0 << arrayRef;
1093ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return false;
1094ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1095ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetter =
1096ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
1097ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                         RefExpr->getSourceRange(),
1098ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                         true, false);
1099ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1100ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1101ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexGetter) {
1102ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    QualType T = AtIndexGetter->param_begin()[0]->getType();
1103ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1104ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        (!arrayRef && !T->isObjCObjectPointerType())) {
1105ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1106ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             arrayRef ? diag::err_objc_subscript_index_type
1107ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                      : diag::err_objc_subscript_key_type) << T;
1108ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(AtIndexGetter->param_begin()[0]->getLocation(),
1109ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::note_parameter_type) << T;
1110ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return false;
1111ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1112ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    QualType R = AtIndexGetter->getResultType();
1113ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!R->isObjCObjectPointerType()) {
1114ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1115ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_indexing_method_result_type) << R << arrayRef;
1116ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1117ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        AtIndexGetter->getDeclName();
1118ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1119ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1120ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return true;
1121ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1122ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1123ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenekbool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1124ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexSetter)
1125ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return true;
1126ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1127ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *BaseExpr = RefExpr->getBaseExpr();
1128ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType BaseT = BaseExpr->getType();
1129ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1130ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType ResultType;
1131ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (const ObjCObjectPointerType *PTy =
1132ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      BaseT->getAs<ObjCObjectPointerType>()) {
1133ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ResultType = PTy->getPointeeType();
1134ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (const ObjCObjectType *iQFaceTy =
1135ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ResultType->getAsObjCQualifiedInterfaceType())
1136ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      ResultType = iQFaceTy->getBaseType();
1137ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1138ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1139ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Sema::ObjCSubscriptKind Res =
1140ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1141dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (Res == Sema::OS_Error) {
1142dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    if (S.getLangOpts().ObjCAutoRefCount)
1143dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian      CheckKeyForObjCARCConversion(S, ResultType,
1144dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                   RefExpr->getKeyExpr());
1145ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1146dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  }
1147ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool arrayRef = (Res == Sema::OS_Array);
1148ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1149ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (ResultType.isNull()) {
1150ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1151ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << arrayRef;
1152ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1153ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1154ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1155ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!arrayRef) {
1156ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // dictionary subscripting.
1157ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1158ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1159ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("setObject"),
1160ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("forKeyedSubscript")
1161ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1162ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1163ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1164ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else {
1165ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1166ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1167ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("setObject"),
1168ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("atIndexedSubscript")
1169ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1170ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1171ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1172ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
1173ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                             true /*instance*/);
1174ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1175ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool receiverIdType = (BaseT->isObjCIdType() ||
1176ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                         BaseT->isObjCQualifiedIdType());
1177ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
11784e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
1179ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    TypeSourceInfo *ResultTInfo = 0;
1180ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    QualType ReturnType = S.Context.VoidTy;
1181ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1182ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           SourceLocation(), AtIndexSetterSelector,
1183ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           ReturnType,
1184ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           ResultTInfo,
1185ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           S.Context.getTranslationUnitDecl(),
1186ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           true /*Instance*/, false/*isVariadic*/,
11871e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose                           /*isPropertyAccessor=*/false,
1188ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1189ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           ObjCMethodDecl::Required,
1190ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           false);
1191ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    SmallVector<ParmVarDecl *, 2> Params;
1192ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1193ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation(), SourceLocation(),
1194ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                &S.Context.Idents.get("object"),
1195ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                S.Context.getObjCIdType(),
1196ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                /*TInfo=*/0,
1197ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
1198ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
1199ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                0);
1200ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Params.push_back(object);
1201ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1202ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation(), SourceLocation(),
1203ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ?  &S.Context.Idents.get("index")
1204ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         :  &S.Context.Idents.get("key"),
1205ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ? S.Context.UnsignedLongTy
1206ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         : S.Context.getObjCIdType(),
1207ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                /*TInfo=*/0,
1208ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
1209ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
1210ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                0);
1211ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Params.push_back(key);
1212ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>());
1213ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1214ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1215ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!AtIndexSetter) {
1216ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!receiverIdType) {
1217ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(BaseExpr->getExprLoc(),
1218ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_subscript_method_not_found)
1219ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << 1 << arrayRef;
1220ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return false;
1221ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1222ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetter =
1223ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
1224ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                         RefExpr->getSourceRange(),
1225ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                         true, false);
1226ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1227ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1228ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool err = false;
1229ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexSetter && arrayRef) {
1230ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    QualType T = AtIndexSetter->param_begin()[1]->getType();
1231ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!T->isIntegralOrEnumerationType()) {
1232ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1233ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_subscript_index_type) << T;
1234ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(AtIndexSetter->param_begin()[1]->getLocation(),
1235ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::note_parameter_type) << T;
1236ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      err = true;
1237ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1238ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    T = AtIndexSetter->param_begin()[0]->getType();
1239ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!T->isObjCObjectPointerType()) {
1240ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1241ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_subscript_object_type) << T << arrayRef;
1242ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(AtIndexSetter->param_begin()[0]->getLocation(),
1243ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::note_parameter_type) << T;
1244ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      err = true;
1245ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1246ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1247ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else if (AtIndexSetter && !arrayRef)
1248ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    for (unsigned i=0; i <2; i++) {
1249ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      QualType T = AtIndexSetter->param_begin()[i]->getType();
1250ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      if (!T->isObjCObjectPointerType()) {
1251ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        if (i == 1)
1252ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek          S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1253ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                 diag::err_objc_subscript_key_type) << T;
1254ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        else
1255ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek          S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1256ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                 diag::err_objc_subscript_dic_object_type) << T;
1257ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        S.Diag(AtIndexSetter->param_begin()[i]->getLocation(),
1258ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek               diag::note_parameter_type) << T;
1259ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        err = true;
1260ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      }
1261ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1262ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1263ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return !err;
1264ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1265ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1266ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// Get the object at "Index" position in the container.
1267ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// [BaseExpr objectAtIndexedSubscript : IndexExpr];
1268ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildGet() {
1269ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!findAtIndexGetter())
1270ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
1271ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1272ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType receiverType = InstanceBase->getType();
1273ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1274ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Build a message-send.
1275ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult msg;
1276ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *Index = InstanceKey;
1277ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1278ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Arguments.
1279ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *args[] = { Index };
1280ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  assert(InstanceBase);
1281ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1282ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       GenericLoc,
1283ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       AtIndexGetterSelector, AtIndexGetter,
1284ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       MultiExprArg(args, 1));
1285ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return msg;
1286ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1287ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1288ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// Store into the container the "op" object at "Index"'ed location
1289ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// by building this messaging expression:
1290ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
129170517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \param captureSetValueAsResult If true, capture the actual
1292ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek///   value being set as the value of the property operation.
1293ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
1294ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                           bool captureSetValueAsResult) {
1295ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!findAtIndexSetter())
1296ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
1297ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1298ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType receiverType = InstanceBase->getType();
1299ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *Index = InstanceKey;
1300ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1301ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Arguments.
1302ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *args[] = { op, Index };
1303ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1304ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Build a message-send.
1305ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1306ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  GenericLoc,
1307ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  AtIndexSetterSelector,
1308ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  AtIndexSetter,
1309ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  MultiExprArg(args, 2));
1310ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1311ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!msg.isInvalid() && captureSetValueAsResult) {
1312ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCMessageExpr *msgExpr =
1313ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1314ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Expr *arg = msgExpr->getArg(0);
1315ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    msgExpr->setArg(0, captureValueAsResult(arg));
1316ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1317ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1318ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return msg;
1319ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1320ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
13214b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
13224b9c2d235fb9449e249d74f48ecfec601650de93John McCall//  General Sema routines.
13234b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
13243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
13254b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectRValue(Expr *E) {
13264b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = E->IgnoreParens();
13274b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
13284b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
13294b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
13304b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildRValueOperation(E);
1331ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1332ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else if (ObjCSubscriptRefExpr *refExpr
1333ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek           = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1334ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptOpBuilder builder(*this, refExpr);
1335ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return builder.buildRValueOperation(E);
13364b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
13374b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
13383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
13394b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
13403c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
13414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Check an increment or decrement of a pseudo-object expression.
13424b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
13434b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         UnaryOperatorKind opcode, Expr *op) {
13444b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do nothing if the operand is dependent.
13454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (op->isTypeDependent())
13464b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
13474b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                       VK_RValue, OK_Ordinary, opcLoc);
13484b9c2d235fb9449e249d74f48ecfec601650de93John McCall
13494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(UnaryOperator::isIncrementDecrementOp(opcode));
13504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = op->IgnoreParens();
13514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
13524b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
13534b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
13544b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1355ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1356ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1357ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
13584b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
13594b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
13603c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
13614b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
13623c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
13634b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
13644b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             BinaryOperatorKind opcode,
13654b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             Expr *LHS, Expr *RHS) {
13664b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do nothing if either argument is dependent.
13674b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (LHS->isTypeDependent() || RHS->isTypeDependent())
13684b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
1369be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                        VK_RValue, OK_Ordinary, opcLoc, false);
13704b9c2d235fb9449e249d74f48ecfec601650de93John McCall
13714b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Filter out non-overload placeholder types in the RHS.
137232509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall  if (RHS->getType()->isNonOverloadPlaceholderType()) {
137332509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall    ExprResult result = CheckPlaceholderExpr(RHS);
137432509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall    if (result.isInvalid()) return ExprError();
137532509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall    RHS = result.take();
13764b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
13773c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
13784b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = LHS->IgnoreParens();
13794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
13804b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
13814b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
13824b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1383ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  } else if (ObjCSubscriptRefExpr *refExpr
1384ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1385ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptOpBuilder builder(*this, refExpr);
1386ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
13874b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
13884b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
13894b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
13903c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
139101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall
139201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// Given a pseudo-object reference, rebuild it without the opaque
139301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// values.  Basically, undo the behavior of rebuildAndCaptureObject.
139401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// This should never operate in-place.
139501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCallstatic Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
139601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  Expr *opaqueRef = E->IgnoreParens();
139701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  if (ObjCPropertyRefExpr *refExpr
139801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
139988507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor    // Class and super property references don't have opaque values in them.
140088507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor    if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
140188507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor      return E;
140288507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor
140388507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor    assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
140488507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
140588507ddf6f83b929454c04470924cf56b4b8147aDouglas Gregor    return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
1406ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  } else if (ObjCSubscriptRefExpr *refExpr
1407ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek               = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1408ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBaseExpr());
1409ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    OpaqueValueExpr *keyOVE = cast<OpaqueValueExpr>(refExpr->getKeyExpr());
1410ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ObjCSubscriptRefRebuilder(S, baseOVE->getSourceExpr(),
1411ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                     keyOVE->getSourceExpr()).rebuild(E);
141201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else {
141301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    llvm_unreachable("unknown pseudo-object kind!");
141401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  }
141501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall}
141601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall
141701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// Given a pseudo-object expression, recreate what it looks like
141801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// syntactically without the attendant OpaqueValueExprs.
141901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall///
142001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// This is a hack which should be removed when TreeTransform is
142101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// capable of rebuilding a tree without stripping implicit
142201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// operations.
142301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCallExpr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
142401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  Expr *syntax = E->getSyntacticForm();
142501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
142601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
142701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
142801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                       uop->getValueKind(), uop->getObjectKind(),
142901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                       uop->getOperatorLoc());
143001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else if (CompoundAssignOperator *cop
143101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall               = dyn_cast<CompoundAssignOperator>(syntax)) {
143201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
143301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
143401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
143501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getType(),
143601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getValueKind(),
143701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getObjectKind(),
143801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getComputationLHSType(),
143901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getComputationResultType(),
1440be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                                cop->getOperatorLoc(), false);
144101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
144201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
144301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
144401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
144501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                        bop->getType(), bop->getValueKind(),
144601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                        bop->getObjectKind(),
1447be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                        bop->getOperatorLoc(), false);
144801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else {
144901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
145001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
145101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  }
145201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall}
1453