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"
346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines#include "clang/AST/ExprCXX.h"
353c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/AST/ExprObjC.h"
363f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose#include "clang/Basic/CharInfo.h"
373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall#include "clang/Lex/Preprocessor.h"
3855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/Initialization.h"
3955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Sema/ScopeInfo.h"
40b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian#include "llvm/ADT/SmallString.h"
413c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
423c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace clang;
433c3b7f90a863af43fa63043d396553ecf205351cJohn McCallusing namespace sema;
443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
454b9c2d235fb9449e249d74f48ecfec601650de93John McCallnamespace {
464b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Basically just a very focused copy of TreeTransform.
4787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  struct Rebuilder {
484b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Sema &S;
4987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    unsigned MSPropertySubscriptCount;
5087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;
5187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    const SpecificRebuilderRefTy &SpecificCallback;
5287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)
5387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        : S(S), MSPropertySubscriptCount(0),
5487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          SpecificCallback(SpecificCallback) {}
5587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
5687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {
5787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // Fortunately, the constraint that we're rebuilding something
5887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      // with a base limits the number of cases here.
5987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
6087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return refExpr;
6187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
6287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (refExpr->isExplicitProperty()) {
6387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return new (S.Context) ObjCPropertyRefExpr(
6487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            refExpr->getExplicitProperty(), refExpr->getType(),
6587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            refExpr->getValueKind(), refExpr->getObjectKind(),
6687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar            refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
6787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      }
6887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return new (S.Context) ObjCPropertyRefExpr(
6987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getImplicitPropertyGetter(),
7087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getImplicitPropertySetter(), refExpr->getType(),
7187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getValueKind(), refExpr->getObjectKind(),
7287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
7387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    }
7487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {
7587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      assert(refExpr->getBaseExpr());
7687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      assert(refExpr->getKeyExpr());
774b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return new (S.Context) ObjCSubscriptRefExpr(
7987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          SpecificCallback(refExpr->getBaseExpr(), 0),
8087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),
8187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getValueKind(), refExpr->getObjectKind(),
8287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),
8387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getRBracket());
8487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    }
8587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {
8687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      assert(refExpr->getBaseExpr());
8787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
8887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return new (S.Context) MSPropertyRefExpr(
8987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          SpecificCallback(refExpr->getBaseExpr(), 0),
9087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),
9187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getValueKind(), refExpr->getQualifierLoc(),
9287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getMemberLoc());
9387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    }
9487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {
9587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      assert(refExpr->getBase());
9687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      assert(refExpr->getIdx());
9787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
9887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      auto *NewBase = rebuild(refExpr->getBase());
9987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      ++MSPropertySubscriptCount;
10087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return new (S.Context) MSPropertySubscriptExpr(
10187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          NewBase,
10287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),
10387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),
10487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          refExpr->getRBracketLoc());
10587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    }
1064b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1074b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *rebuild(Expr *e) {
1084b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Fast path: nothing to look through.
10987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))
11087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return rebuildObjCPropertyRefExpr(PRE);
11187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))
11287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return rebuildObjCSubscriptRefExpr(SRE);
11387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))
11487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return rebuildMSPropertyRefExpr(MSPRE);
11587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))
11687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        return rebuildMSPropertySubscriptExpr(MSPSE);
1174b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1184b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // Otherwise, we should look through and rebuild anything that
1194b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // IgnoreParens would.
1204b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1214b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
1224b9c2d235fb9449e249d74f48ecfec601650de93John McCall        e = rebuild(parens->getSubExpr());
1234b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) ParenExpr(parens->getLParen(),
1244b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         parens->getRParen(),
1254b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         e);
1264b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1274b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1284b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
1294b9c2d235fb9449e249d74f48ecfec601650de93John McCall        assert(uop->getOpcode() == UO_Extension);
1304b9c2d235fb9449e249d74f48ecfec601650de93John McCall        e = rebuild(uop->getSubExpr());
1314b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) UnaryOperator(e, uop->getOpcode(),
1324b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getType(),
1334b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getValueKind(),
1344b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getObjectKind(),
1354b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             uop->getOperatorLoc());
1364b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1374b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1384b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
1394b9c2d235fb9449e249d74f48ecfec601650de93John McCall        assert(!gse->isResultDependent());
1404b9c2d235fb9449e249d74f48ecfec601650de93John McCall        unsigned resultIndex = gse->getResultIndex();
1414b9c2d235fb9449e249d74f48ecfec601650de93John McCall        unsigned numAssocs = gse->getNumAssocs();
1424b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1434b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SmallVector<Expr*, 8> assocs(numAssocs);
1444b9c2d235fb9449e249d74f48ecfec601650de93John McCall        SmallVector<TypeSourceInfo*, 8> assocTypes(numAssocs);
1454b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1464b9c2d235fb9449e249d74f48ecfec601650de93John McCall        for (unsigned i = 0; i != numAssocs; ++i) {
1474b9c2d235fb9449e249d74f48ecfec601650de93John McCall          Expr *assoc = gse->getAssocExpr(i);
1484b9c2d235fb9449e249d74f48ecfec601650de93John McCall          if (i == resultIndex) assoc = rebuild(assoc);
1494b9c2d235fb9449e249d74f48ecfec601650de93John McCall          assocs[i] = assoc;
1504b9c2d235fb9449e249d74f48ecfec601650de93John McCall          assocTypes[i] = gse->getAssocTypeSourceInfo(i);
1514b9c2d235fb9449e249d74f48ecfec601650de93John McCall        }
1524b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1534b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return new (S.Context) GenericSelectionExpr(S.Context,
1544b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getGenericLoc(),
1554b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getControllingExpr(),
1563b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer                                                    assocTypes,
1573b6bef9a213249c6ab6d67c07b1ac6380961be3eBenjamin Kramer                                                    assocs,
1584b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getDefaultLoc(),
1594b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    gse->getRParenLoc(),
1604b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      gse->containsUnexpandedParameterPack(),
1614b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                    resultIndex);
1624b9c2d235fb9449e249d74f48ecfec601650de93John McCall      }
1634b9c2d235fb9449e249d74f48ecfec601650de93John McCall
164a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman      if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {
165a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman        assert(!ce->isConditionDependent());
166a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman
167a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman        Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();
168a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman        Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;
169a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman        rebuiltExpr = rebuild(rebuiltExpr);
170a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman
171a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman        return new (S.Context) ChooseExpr(ce->getBuiltinLoc(),
172a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          ce->getCond(),
173a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          LHS, RHS,
174a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          rebuiltExpr->getType(),
175a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          rebuiltExpr->getValueKind(),
176a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          rebuiltExpr->getObjectKind(),
177a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          ce->getRParenLoc(),
178a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          ce->isConditionTrue(),
179a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          rebuiltExpr->isTypeDependent(),
180a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman                                          rebuiltExpr->isValueDependent());
181a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman      }
182a5e660188a3c654cf0c88ed1093b28207e870b2bEli Friedman
1834b9c2d235fb9449e249d74f48ecfec601650de93John McCall      llvm_unreachable("bad expression to rebuild!");
1844b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
1854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
1864b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1874b9c2d235fb9449e249d74f48ecfec601650de93John McCall  class PseudoOpBuilder {
1884b9c2d235fb9449e249d74f48ecfec601650de93John McCall  public:
1894b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Sema &S;
1904b9c2d235fb9449e249d74f48ecfec601650de93John McCall    unsigned ResultIndex;
1914b9c2d235fb9449e249d74f48ecfec601650de93John McCall    SourceLocation GenericLoc;
1924b9c2d235fb9449e249d74f48ecfec601650de93John McCall    SmallVector<Expr *, 4> Semantics;
1934b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1944b9c2d235fb9449e249d74f48ecfec601650de93John McCall    PseudoOpBuilder(Sema &S, SourceLocation genericLoc)
1954b9c2d235fb9449e249d74f48ecfec601650de93John McCall      : S(S), ResultIndex(PseudoObjectExpr::NoResult),
1964b9c2d235fb9449e249d74f48ecfec601650de93John McCall        GenericLoc(genericLoc) {}
1974b9c2d235fb9449e249d74f48ecfec601650de93John McCall
1981aa1721f14f2162811f5393dbd84e01eadc2c963Matt Beaumont-Gay    virtual ~PseudoOpBuilder() {}
1991aa1721f14f2162811f5393dbd84e01eadc2c963Matt Beaumont-Gay
2004b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Add a normal semantic expression.
2014b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void addSemanticExpr(Expr *semantic) {
2024b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Semantics.push_back(semantic);
2034b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
2044b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2054b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Add the 'result' semantic expression.
2064b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void addResultSemanticExpr(Expr *resultExpr) {
2074b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(ResultIndex == PseudoObjectExpr::NoResult);
2084b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ResultIndex = Semantics.size();
2094b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Semantics.push_back(resultExpr);
2104b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
2114b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2124b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildRValueOperation(Expr *op);
2134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildAssignmentOperation(Scope *Sc,
2144b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        SourceLocation opLoc,
2154b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        BinaryOperatorKind opcode,
2164b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        Expr *LHS, Expr *RHS);
2174b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
2184b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    UnaryOperatorKind opcode,
2194b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    Expr *op);
2204b9c2d235fb9449e249d74f48ecfec601650de93John McCall
22158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    virtual ExprResult complete(Expr *syntacticForm);
2224b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2234b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *capture(Expr *op);
2244b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *captureValueAsResult(Expr *op);
2254b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2264b9c2d235fb9449e249d74f48ecfec601650de93John McCall    void setResultToLastSemantic() {
2274b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(ResultIndex == PseudoObjectExpr::NoResult);
2284b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ResultIndex = Semantics.size() - 1;
2294b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
2304b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2314b9c2d235fb9449e249d74f48ecfec601650de93John McCall    /// Return true if assignments have a non-void result.
23287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    static bool CanCaptureValue(Expr *exp) {
233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (exp->isGLValue())
234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return true;
235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      QualType ty = exp->getType();
23625f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman      assert(!ty->isIncompleteType());
23725f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman      assert(!ty->isDependentType());
23825f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman
23925f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman      if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())
24025f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman        return ClassDecl->isTriviallyCopyable();
24125f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman      return true;
24225f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman    }
2434b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2444b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;
2454b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual ExprResult buildGet() = 0;
2464b9c2d235fb9449e249d74f48ecfec601650de93John McCall    virtual ExprResult buildSet(Expr *, SourceLocation,
2474b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                bool captureSetValueAsResult) = 0;
24887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// \brief Should the result of an assignment be the formal result of the
24987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// setter call or the value that was passed to the setter?
25087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    ///
25187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// Different pseudo-object language features use different language rules
25287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// for this.
25387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// The default is to use the set value.  Currently, this affects the
25487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// behavior of simple assignments, compound assignments, and prefix
25587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// increment and decrement.
25687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// Postfix increment and decrement always use the getter result as the
25787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// expression result.
25887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    ///
25987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// If this method returns true, and the set value isn't capturable for
26087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    /// some reason, the result of the expression will be void.
26187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    virtual bool captureSetValueAsResult() const { return true; }
2624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
2634b9c2d235fb9449e249d74f48ecfec601650de93John McCall
264e23fb90712233bdfa04387e48b54a7168e23cb3eDmitri Gribenko  /// A PseudoOpBuilder for Objective-C \@properties.
2654b9c2d235fb9449e249d74f48ecfec601650de93John McCall  class ObjCPropertyOpBuilder : public PseudoOpBuilder {
2664b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyRefExpr *RefExpr;
267b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    ObjCPropertyRefExpr *SyntacticRefExpr;
2684b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *InstanceReceiver;
2694b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMethodDecl *Getter;
2704b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2714b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMethodDecl *Setter;
2724b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Selector SetterSelector;
273a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    Selector GetterSelector;
2744b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2754b9c2d235fb9449e249d74f48ecfec601650de93John McCall  public:
2764b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
2774b9c2d235fb9449e249d74f48ecfec601650de93John McCall      PseudoOpBuilder(S, refExpr->getLocation()), RefExpr(refExpr),
2786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      SyntacticRefExpr(nullptr), InstanceReceiver(nullptr), Getter(nullptr),
2796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Setter(nullptr) {
2804b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
2814b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2824b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildRValueOperation(Expr *op);
2834b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildAssignmentOperation(Scope *Sc,
2844b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        SourceLocation opLoc,
2854b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        BinaryOperatorKind opcode,
2864b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        Expr *LHS, Expr *RHS);
2874b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,
2884b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    UnaryOperatorKind opcode,
2894b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                    Expr *op);
2904b9c2d235fb9449e249d74f48ecfec601650de93John McCall
2914b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool tryBuildGetOfReference(Expr *op, ExprResult &result);
292b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian    bool findSetter(bool warn=true);
2934b9c2d235fb9449e249d74f48ecfec601650de93John McCall    bool findGetter();
294176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    void DiagnoseUnsupportedPropertyUse();
2954b9c2d235fb9449e249d74f48ecfec601650de93John McCall
296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ExprResult buildGet() override;
298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ExprResult buildSet(Expr *op, SourceLocation, bool) override;
299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    ExprResult complete(Expr *SyntacticForm) override;
30058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
30158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    bool isWeakProperty() const;
3024b9c2d235fb9449e249d74f48ecfec601650de93John McCall  };
303ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
304ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek /// A PseudoOpBuilder for Objective-C array/dictionary indexing.
305ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek class ObjCSubscriptOpBuilder : public PseudoOpBuilder {
306ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ObjCSubscriptRefExpr *RefExpr;
307ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   OpaqueValueExpr *InstanceBase;
308ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   OpaqueValueExpr *InstanceKey;
309ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ObjCMethodDecl *AtIndexGetter;
310ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   Selector AtIndexGetterSelector;
311ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
312ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ObjCMethodDecl *AtIndexSetter;
313ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   Selector AtIndexSetterSelector;
314ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
315ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek public:
316ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr) :
317ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
318ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      RefExpr(refExpr),
3196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      InstanceBase(nullptr), InstanceKey(nullptr),
3206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}
3216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
322ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ExprResult buildRValueOperation(Expr *op);
323ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   ExprResult buildAssignmentOperation(Scope *Sc,
324ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       SourceLocation opLoc,
325ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       BinaryOperatorKind opcode,
326ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       Expr *LHS, Expr *RHS);
327651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;
328651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
329ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   bool findAtIndexGetter();
330ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek   bool findAtIndexSetter();
331651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
332651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   ExprResult buildGet() override;
333651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   ExprResult buildSet(Expr *op, SourceLocation, bool) override;
334ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek };
335ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
33676da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall class MSPropertyOpBuilder : public PseudoOpBuilder {
33776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall   MSPropertyRefExpr *RefExpr;
33887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar   OpaqueValueExpr *InstanceBase;
33987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar   SmallVector<Expr *, 4> CallArgs;
34087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
34187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar   MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);
34276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
34376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall public:
34476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall   MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr) :
34576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall     PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
34687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar     RefExpr(refExpr), InstanceBase(nullptr) {}
34787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar   MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr)
34887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin()),
34987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar         InstanceBase(nullptr) {
35087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar     RefExpr = getBaseMSProperty(refExpr);
35187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar   }
35276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
353651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   Expr *rebuildAndCaptureObject(Expr *) override;
354651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   ExprResult buildGet() override;
355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines   ExprResult buildSet(Expr *op, SourceLocation, bool) override;
35687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar   bool captureSetValueAsResult() const override { return false; }
35776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall };
3584b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3594b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3604b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression in an OpaqueValueExpr.
3614b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {
3624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Make a new OVE whose source is the given expression.
3634b9c2d235fb9449e249d74f48ecfec601650de93John McCall  OpaqueValueExpr *captured =
3644b9c2d235fb9449e249d74f48ecfec601650de93John McCall    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),
36597df54e0c075bc8d6a869597e771dad0c11a2180Douglas Gregor                                    e->getValueKind(), e->getObjectKind(),
36697df54e0c075bc8d6a869597e771dad0c11a2180Douglas Gregor                                    e);
3674b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3684b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Make sure we bind that in the semantics.
3694b9c2d235fb9449e249d74f48ecfec601650de93John McCall  addSemanticExpr(captured);
3704b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return captured;
3714b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
3724b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3734b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the given expression as the result of this pseudo-object
3744b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation.  This routine is safe against expressions which may
3754b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// already be captured.
3764b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
37770517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \returns the captured expression, which will be the
3784b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   same as the input if the input was already captured
3794b9c2d235fb9449e249d74f48ecfec601650de93John McCallOpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {
3804b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(ResultIndex == PseudoObjectExpr::NoResult);
3814b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3824b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If the expression hasn't already been captured, just capture it
3834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // and set the new semantic
3844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!isa<OpaqueValueExpr>(e)) {
3854b9c2d235fb9449e249d74f48ecfec601650de93John McCall    OpaqueValueExpr *cap = capture(e);
3864b9c2d235fb9449e249d74f48ecfec601650de93John McCall    setResultToLastSemantic();
3874b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return cap;
3884b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
3904b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Otherwise, it must already be one of our semantic expressions;
3914b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // set ResultIndex to its index.
3924b9c2d235fb9449e249d74f48ecfec601650de93John McCall  unsigned index = 0;
3934b9c2d235fb9449e249d74f48ecfec601650de93John McCall  for (;; ++index) {
3944b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(index < Semantics.size() &&
3954b9c2d235fb9449e249d74f48ecfec601650de93John McCall           "captured expression not found in semantics!");
3964b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (e == Semantics[index]) break;
3974b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
3984b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ResultIndex = index;
3994b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return cast<OpaqueValueExpr>(e);
4004b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4014b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4024b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The routine which creates the final PseudoObjectExpr.
4034b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::complete(Expr *syntactic) {
4044b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return PseudoObjectExpr::Create(S.Context, syntactic,
4054b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                  Semantics, ResultIndex);
4064b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4074b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4084b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The main skeleton for building an r-value operation.
4094b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {
4104b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticBase = rebuildAndCaptureObject(op);
4114b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4124b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult getExpr = buildGet();
4134b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (getExpr.isInvalid()) return ExprError();
414c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  addResultSemanticExpr(getExpr.get());
4154b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntacticBase);
4174b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4184b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4194b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building a simple or compound
4204b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// assignment operation.
4214b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
4224b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,
4234b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                          BinaryOperatorKind opcode,
4244b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                          Expr *LHS, Expr *RHS) {
4254b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(BinaryOperator::isAssignmentOp(opcode));
4264b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4274b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);
4284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  OpaqueValueExpr *capturedRHS = capture(RHS);
4294b9c2d235fb9449e249d74f48ecfec601650de93John McCall
43087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  // In some very specific cases, semantic analysis of the RHS as an
43187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  // expression may require it to be rewritten.  In these cases, we
43287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  // cannot safely keep the OVE around.  Fortunately, we don't really
43387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  // need to: we don't use this particular OVE in multiple places, and
43487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  // no clients rely that closely on matching up expressions in the
43587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  // semantic expression with expressions from the syntactic form.
43687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Expr *semanticRHS = capturedRHS;
43787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) {
43887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    semanticRHS = RHS;
43987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Semantics.pop_back();
44087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  }
44187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
4424b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntactic;
4434b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4444b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result;
4454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (opcode == BO_Assign) {
44687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    result = semanticRHS;
4474b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS,
4484b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               opcode, capturedRHS->getType(),
4494b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                               capturedRHS->getValueKind(),
450be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                               OK_Ordinary, opcLoc, false);
4514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
4524b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult opLHS = buildGet();
4534b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (opLHS.isInvalid()) return ExprError();
4544b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4554b9c2d235fb9449e249d74f48ecfec601650de93John McCall    // Build an ordinary, non-compound operation.
4564b9c2d235fb9449e249d74f48ecfec601650de93John McCall    BinaryOperatorKind nonCompound =
4574b9c2d235fb9449e249d74f48ecfec601650de93John McCall      BinaryOperator::getOpForCompoundAssignment(opcode);
45887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);
4594b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (result.isInvalid()) return ExprError();
4604b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4614b9c2d235fb9449e249d74f48ecfec601650de93John McCall    syntactic =
4624b9c2d235fb9449e249d74f48ecfec601650de93John McCall      new (S.Context) CompoundAssignOperator(syntacticLHS, capturedRHS, opcode,
4634b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getType(),
4644b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getValueKind(),
4654b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             OK_Ordinary,
4664b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             opLHS.get()->getType(),
4674b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             result.get()->getType(),
468be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                             opcLoc, false);
4694b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
4704b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4714b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // The result of the assignment, if not void, is the value set into
4724b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // the l-value.
47387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  result = buildSet(result.get(), opcLoc, captureSetValueAsResult());
4744b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
475c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  addSemanticExpr(result.get());
47687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&
47787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
47887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    setResultToLastSemantic();
4794b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4804b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntactic);
4814b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
4824b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4834b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// The basic skeleton for building an increment or decrement
4844b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// operation.
4854b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
4864b9c2d235fb9449e249d74f48ecfec601650de93John McCallPseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
4874b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      UnaryOperatorKind opcode,
4884b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                      Expr *op) {
4894b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(UnaryOperator::isIncrementDecrementOp(opcode));
4904b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4914b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *syntacticOp = rebuildAndCaptureObject(op);
4924b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4934b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Load the value.
4944b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result = buildGet();
4954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
4964b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4974b9c2d235fb9449e249d74f48ecfec601650de93John McCall  QualType resultType = result.get()->getType();
4984b9c2d235fb9449e249d74f48ecfec601650de93John McCall
4994b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // That's the postfix result.
500d314abeffba04dffc101e4e71cc3a32ddeed4ae6John McCall  if (UnaryOperator::isPostfix(opcode) &&
501651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {
502c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    result = capture(result.get());
5034b9c2d235fb9449e249d74f48ecfec601650de93John McCall    setResultToLastSemantic();
5044b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5054b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5064b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Add or subtract a literal 1.
5074b9c2d235fb9449e249d74f48ecfec601650de93John McCall  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
5084b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
5094b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     GenericLoc);
5104b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5114b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (UnaryOperator::isIncrementOp(opcode)) {
512c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one);
5134b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
514c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one);
5154b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
5164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
5174b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5184b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Store that back into the result.  The value stored is the result
5194b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // of a prefix operation.
52087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&
52187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                                              captureSetValueAsResult());
5224b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
523c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  addSemanticExpr(result.get());
52487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&
52587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      !result.get()->getType()->isVoidType() &&
52687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
52787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    setResultToLastSemantic();
5284b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  UnaryOperator *syntactic =
5304b9c2d235fb9449e249d74f48ecfec601650de93John McCall    new (S.Context) UnaryOperator(syntacticOp, opcode, resultType,
5314b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                  VK_LValue, OK_Ordinary, opcLoc);
5324b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return complete(syntactic);
5334b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
5344b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5354b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5364b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
5374b9c2d235fb9449e249d74f48ecfec601650de93John McCall//  Objective-C @property and implicit property references
5384b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
5394b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5404b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Look up a method in the receiver type of an Objective-C property
5414b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference.
5423c3b7f90a863af43fa63043d396553ecf205351cJohn McCallstatic ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
5433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall                                            const ObjCPropertyRefExpr *PRE) {
5443c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  if (PRE->isObjectReceiver()) {
545aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    const ObjCObjectPointerType *PT =
546aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
5474b9c2d235fb9449e249d74f48ecfec601650de93John McCall
5484b9c2d235fb9449e249d74f48ecfec601650de93John McCall    // Special case for 'self' in class method implementations.
5494b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (PT->isObjCClassType() &&
5504b9c2d235fb9449e249d74f48ecfec601650de93John McCall        S.isSelfExpr(const_cast<Expr*>(PRE->getBase()))) {
5514b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // This cast is safe because isSelfExpr is only true within
5524b9c2d235fb9449e249d74f48ecfec601650de93John McCall      // methods.
5534b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ObjCMethodDecl *method =
5544b9c2d235fb9449e249d74f48ecfec601650de93John McCall        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
5554b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return S.LookupMethodInObjectType(sel,
5564b9c2d235fb9449e249d74f48ecfec601650de93John McCall                 S.Context.getObjCInterfaceType(method->getClassInterface()),
5574b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                        /*instance*/ false);
5584b9c2d235fb9449e249d74f48ecfec601650de93John McCall    }
5594b9c2d235fb9449e249d74f48ecfec601650de93John McCall
560aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
5613c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
5623c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
563aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  if (PRE->isSuperReceiver()) {
564aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    if (const ObjCObjectPointerType *PT =
565aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
566aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer      return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
567aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer
568aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer    return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
569aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  }
570aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer
571aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  assert(PRE->isClassReceiver() && "Invalid expression");
572aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
573aa9807a85959ffbdc5d9f649d7b24b9b2056d2cdBenjamin Kramer  return S.LookupMethodInObjectType(sel, IT, false);
5743c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
5753c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
57658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rosebool ObjCPropertyOpBuilder::isWeakProperty() const {
57758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  QualType T;
57858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  if (RefExpr->isExplicitProperty()) {
57958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();
58058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
5814967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar      return true;
58258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
58358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    T = Prop->getType();
58458b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  } else if (Getter) {
585651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    T = Getter->getReturnType();
58658b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  } else {
58758b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose    return false;
58858b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  }
58958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
59058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  return T.getObjCLifetime() == Qualifiers::OCL_Weak;
59158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose}
59258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
5934b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::findGetter() {
5944b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (Getter) return true;
5954b9c2d235fb9449e249d74f48ecfec601650de93John McCall
596dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  // For implicit properties, just trust the lookup we already did.
597dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  if (RefExpr->isImplicitProperty()) {
598a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    if ((Getter = RefExpr->getImplicitPropertyGetter())) {
599a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      GetterSelector = Getter->getSelector();
600a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      return true;
601a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    }
602a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    else {
603a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      // Must build the getter selector the hard way.
604a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
605a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      assert(setter && "both setter and getter are null - cannot happen");
606a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      IdentifierInfo *setterName =
607a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian        setter->getSelector().getIdentifierInfoForSlot(0);
608c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      IdentifierInfo *getterName =
609c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          &S.Context.Idents.get(setterName->getName().substr(3));
610a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      GetterSelector =
611a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian        S.PP.getSelectorTable().getNullarySelector(getterName);
612a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      return false;
613a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian    }
614dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  }
615dc4df51d32dea56fbec79037570832dffbcc14e6John McCall
616dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
617dc4df51d32dea56fbec79037570832dffbcc14e6John McCall  Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);
6186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  return (Getter != nullptr);
6194b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
6204b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6214b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to find the most accurate setter declaration for the property
6224b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// reference.
6234b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
6244b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if a setter was found, in which case Setter
625b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanianbool ObjCPropertyOpBuilder::findSetter(bool warn) {
6264b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // For implicit properties, just trust the lookup we already did.
6274b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isImplicitProperty()) {
6284b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
6294b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Setter = setter;
6304b9c2d235fb9449e249d74f48ecfec601650de93John McCall      SetterSelector = setter->getSelector();
6314b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return true;
6323c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    } else {
6334b9c2d235fb9449e249d74f48ecfec601650de93John McCall      IdentifierInfo *getterName =
6344b9c2d235fb9449e249d74f48ecfec601650de93John McCall        RefExpr->getImplicitPropertyGetter()->getSelector()
6354b9c2d235fb9449e249d74f48ecfec601650de93John McCall          .getIdentifierInfoForSlot(0);
6364b9c2d235fb9449e249d74f48ecfec601650de93John McCall      SetterSelector =
63780e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl        SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),
63880e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl                                               S.PP.getSelectorTable(),
63980e8ea92d6dcaa05165dcb4730485db82dcd4629Adrian Prantl                                               getterName);
6404b9c2d235fb9449e249d74f48ecfec601650de93John McCall      return false;
6413c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
6423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
6433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
6444b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // For explicit properties, this is more involved.
6454b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
6464b9c2d235fb9449e249d74f48ecfec601650de93John McCall  SetterSelector = prop->getSetterName();
6474b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6484b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do a normal method lookup first.
6494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCMethodDecl *setter =
6504b9c2d235fb9449e249d74f48ecfec601650de93John McCall        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
6511e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose    if (setter->isPropertyAccessor() && warn)
652b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian      if (const ObjCInterfaceDecl *IFace =
653b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian          dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {
654176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines        StringRef thisPropertyName = prop->getName();
6553f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose        // Try flipping the case of the first character.
656b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        char front = thisPropertyName.front();
6573f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose        front = isLowercase(front) ? toUppercase(front) : toLowercase(front);
658b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        SmallString<100> PropertyName = thisPropertyName;
659b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        PropertyName[0] = front;
660b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian        IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName);
6614967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar        if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(
6624967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar                AltMember, prop->getQueryKind()))
663b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian          if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
664cba0ebce65667f76e291346d377f402579743ceaFariborz Jahanian            S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
665651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines              << prop << prop1 << setter->getSelector();
666b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian            S.Diag(prop->getLocation(), diag::note_property_declare);
667b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian            S.Diag(prop1->getLocation(), diag::note_property_declare);
668b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian          }
669b5b155cb8bd2460693572bab5ce14dabf1a27d2fFariborz Jahanian      }
6704b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Setter = setter;
6714b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return true;
6724b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
6734b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6744b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // That can fail in the somewhat crazy situation that we're
6754b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // type-checking a message send within the @interface declaration
6764b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // that declared the @property.  But it's not clear that that's
6774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // valuable to support.
6784b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6794b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return false;
6804b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
6814b9c2d235fb9449e249d74f48ecfec601650de93John McCall
682176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesvoid ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
683c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (S.getCurLexicalContext()->isObjCContainer() &&
684c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&
685c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {
686c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {
687c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        S.Diag(RefExpr->getLocation(),
688c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines               diag::err_property_function_in_objc_container);
689c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        S.Diag(prop->getLocation(), diag::note_property_declare);
690c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
691c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  }
692c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines}
693c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines
6944b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Capture the base object of an Objective-C property expression.
6954b9c2d235fb9449e249d74f48ecfec601650de93John McCallExpr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
6966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(InstanceReceiver == nullptr);
6974b9c2d235fb9449e249d74f48ecfec601650de93John McCall
6984b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If we have a base, capture it in an OVE and rebuild the syntactic
6994b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // form to use the OVE as its base.
7004b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isObjectReceiver()) {
7014b9c2d235fb9449e249d74f48ecfec601650de93John McCall    InstanceReceiver = capture(RefExpr->getBase());
70287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
70387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                      return InstanceReceiver;
70487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                    }).rebuild(syntacticBase);
7054b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7064b9c2d235fb9449e249d74f48ecfec601650de93John McCall
707b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis  if (ObjCPropertyRefExpr *
708b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis        refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
709b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    SyntacticRefExpr = refE;
710b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
7114b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return syntacticBase;
7124b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
7134b9c2d235fb9449e249d74f48ecfec601650de93John McCall
7144b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Load from an Objective-C property reference.
7154b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildGet() {
7164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  findGetter();
717176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!Getter) {
718176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    DiagnoseUnsupportedPropertyUse();
719176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return ExprError();
720176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
721b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
722b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis  if (SyntacticRefExpr)
723b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    SyntacticRefExpr->setIsMessagingGetter();
724b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
72587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  QualType receiverType = RefExpr->getReceiverType(S.Context);
726c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!Getter->isImplicit())
727c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
7284b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Build a message-send.
7294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult msg;
7306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
7316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      RefExpr->isObjectReceiver()) {
7324b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(InstanceReceiver || RefExpr->isSuperReceiver());
733746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
734746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         GenericLoc, Getter->getSelector(),
73562ed889272d7e9da8e367d8682fdcdeeec0d83b5Dmitri Gribenko                                         Getter, None);
7364b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
737746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
73862ed889272d7e9da8e367d8682fdcdeeec0d83b5Dmitri Gribenko                                      GenericLoc, Getter->getSelector(),
73962ed889272d7e9da8e367d8682fdcdeeec0d83b5Dmitri Gribenko                                      Getter, None);
7404b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7414b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return msg;
7423c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
7433c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7444b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Store to an Objective-C property reference.
7454b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
74670517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \param captureSetValueAsResult If true, capture the actual
7474b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   value being set as the value of the property operation.
7484b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
7494b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                           bool captureSetValueAsResult) {
750176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!findSetter(false)) {
751176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    DiagnoseUnsupportedPropertyUse();
752176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return ExprError();
753176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
7544b9c2d235fb9449e249d74f48ecfec601650de93John McCall
755b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis  if (SyntacticRefExpr)
756b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis    SyntacticRefExpr->setIsMessagingSetter();
757b085d898bdfe35097eba45f4072b0f6865f561dcArgyrios Kyrtzidis
75887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  QualType receiverType = RefExpr->getReceiverType(S.Context);
7593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7604b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Use assignment constraints when possible; they give us better
7614b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // diagnostics.  "When possible" basically means anything except a
7624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // C++ class type.
7634e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
76487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    QualType paramType = (*Setter->param_begin())->getType()
76587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                           .substObjCMemberType(
76687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                             receiverType,
76787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                             Setter->getDeclContext(),
76887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                             ObjCSubstitutionContext::Parameter);
7694e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie    if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
7704b9c2d235fb9449e249d74f48ecfec601650de93John McCall      ExprResult opResult = op;
7714b9c2d235fb9449e249d74f48ecfec601650de93John McCall      Sema::AssignConvertType assignResult
7724b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = S.CheckSingleAssignmentConstraints(paramType, opResult);
7734b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
7744b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     op->getType(), opResult.get(),
7754b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                     Sema::AA_Assigning))
7764b9c2d235fb9449e249d74f48ecfec601650de93John McCall        return ExprError();
7774b9c2d235fb9449e249d74f48ecfec601650de93John McCall
778c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      op = opResult.get();
7794b9c2d235fb9449e249d74f48ecfec601650de93John McCall      assert(op && "successful assignment left argument invalid?");
7803c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
7814b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
7823c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7834b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Arguments.
7844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *args[] = { op };
7853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
7864b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Build a message-send.
7874b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult msg;
788c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (!Setter->isImplicit())
789c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);
7906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
7916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      RefExpr->isObjectReceiver()) {
792746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
793746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         GenericLoc, SetterSelector, Setter,
794746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                         MultiExprArg(args, 1));
7954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
796746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis    msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
797746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      GenericLoc,
798746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      SetterSelector, Setter,
799746f5bcbfde5b25269169c63c66492311673b67dArgyrios Kyrtzidis                                      MultiExprArg(args, 1));
8004b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
8013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8024b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!msg.isInvalid() && captureSetValueAsResult) {
8034b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCMessageExpr *msgExpr =
8044b9c2d235fb9449e249d74f48ecfec601650de93John McCall      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
8054b9c2d235fb9449e249d74f48ecfec601650de93John McCall    Expr *arg = msgExpr->getArg(0);
806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (CanCaptureValue(arg))
80725f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman      msgExpr->setArg(0, captureValueAsResult(arg));
8084b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
8093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8104b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return msg;
8114b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
8124b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8134b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing lvalue-to-rvalue conversion.
8144b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
8154b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Explicit properties always have getters, but implicit ones don't.
8164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Check that before proceeding.
817a70779f6b9a8135c3459bdeb1f0197b82ea0cb2aEli Friedman  if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {
8184b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
819a70779f6b9a8135c3459bdeb1f0197b82ea0cb2aEli Friedman        << RefExpr->getSourceRange();
8204b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return ExprError();
8214b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
8224b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8234b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
8244b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (result.isInvalid()) return ExprError();
8254b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8264b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
8274b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
8284b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                       Getter, RefExpr->getLocation());
8294b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8304b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // As a special case, if the method returns 'id', try to get
8314b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // a better type from the property.
832c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (RefExpr->isExplicitProperty() && result.get()->isRValue()) {
83387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    QualType receiverType = RefExpr->getReceiverType(S.Context);
83487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    QualType propType = RefExpr->getExplicitProperty()
83587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                          ->getUsageType(receiverType);
836c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (result.get()->getType()->isObjCIdType()) {
837c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (const ObjCObjectPointerType *ptr
838c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines            = propType->getAs<ObjCObjectPointerType>()) {
839c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (!ptr->isObjCIdType())
840c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines          result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
841c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      }
842c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    }
843c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    if (S.getLangOpts().ObjCAutoRefCount) {
844c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      Qualifiers::ObjCLifetime LT = propType.getObjCLifetime();
845c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      if (LT == Qualifiers::OCL_Weak)
846c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation()))
847c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines              S.getCurFunction()->markSafeWeakUse(RefExpr);
8483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
8494b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
8504b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return result;
8523c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
8533c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8544b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Try to build this as a call to a getter that returns a reference.
8554b9c2d235fb9449e249d74f48ecfec601650de93John McCall///
8564b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// \return true if it was possible, whether or not it actually
8574b9c2d235fb9449e249d74f48ecfec601650de93John McCall///   succeeded
8584b9c2d235fb9449e249d74f48ecfec601650de93John McCallbool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
8594b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                   ExprResult &result) {
8604e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!S.getLangOpts().CPlusPlus) return false;
8614b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  findGetter();
863176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!Getter) {
864176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // The property has no setter and no getter! This can happen if the type is
865176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    // invalid. Error have already been reported.
866176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    result = ExprError();
867176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines    return true;
868176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  }
8694b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8704b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Only do this if the getter returns an l-value reference type.
871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  QualType resultType = Getter->getReturnType();
8724b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!resultType->isLValueReferenceType()) return false;
8734b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8744b9c2d235fb9449e249d74f48ecfec601650de93John McCall  result = buildRValueOperation(op);
8754b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return true;
8764b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
8774b9c2d235fb9449e249d74f48ecfec601650de93John McCall
8784b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing assignments.
8794b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
8804b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
8814b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                SourceLocation opcLoc,
8824b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                BinaryOperatorKind opcode,
8834b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                                Expr *LHS, Expr *RHS) {
8844b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(BinaryOperator::isAssignmentOp(opcode));
8853c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8863c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there's no setter, we have no choice but to try to assign to
8873c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // the result of the getter.
8884b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findSetter()) {
8894b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult result;
8904b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (tryBuildGetOfReference(LHS, result)) {
8914b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
892c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS);
8933c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
8943c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
8953c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    // Otherwise, it's an error.
8964b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nosetter_property_assignment)
8974b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(RefExpr->isImplicitProperty())
8984b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << SetterSelector
8994b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << LHS->getSourceRange() << RHS->getSourceRange();
9003c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
9013c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
9023c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9034b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // If there is a setter, we definitely want to use it.
9044b9c2d235fb9449e249d74f48ecfec601650de93John McCall
9054b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Verify that we can do a compound assignment.
9064b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (opcode != BO_Assign && !findGetter()) {
9074b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
9084b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << LHS->getSourceRange() << RHS->getSourceRange();
9093c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
9103c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
9113c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9124b9c2d235fb9449e249d74f48ecfec601650de93John McCall  ExprResult result =
9134b9c2d235fb9449e249d74f48ecfec601650de93John McCall    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
9143c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  if (result.isInvalid()) return ExprError();
9153c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Various warnings about property assignments in ARC.
9174e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
9184b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
9194b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
9204b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
9214b9c2d235fb9449e249d74f48ecfec601650de93John McCall
9223c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  return result;
9233c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
9243c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9254b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// @property-specific behavior for doing increments and decrements.
9264b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult
9274b9c2d235fb9449e249d74f48ecfec601650de93John McCallObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
9284b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                            UnaryOperatorKind opcode,
9294b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                            Expr *op) {
9303c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there's no setter, we have no choice but to try to assign to
9313c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // the result of the getter.
9324b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findSetter()) {
9334b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ExprResult result;
9344b9c2d235fb9449e249d74f48ecfec601650de93John McCall    if (tryBuildGetOfReference(op, result)) {
9354b9c2d235fb9449e249d74f48ecfec601650de93John McCall      if (result.isInvalid()) return ExprError();
936c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get());
9373c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    }
9383c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9393c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    // Otherwise, it's an error.
9404b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nosetter_property_incdec)
9414b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(RefExpr->isImplicitProperty())
9424b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(UnaryOperator::isDecrementOp(opcode))
9434b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << SetterSelector
9444b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << op->getSourceRange();
9453c3b7f90a863af43fa63043d396553ecf205351cJohn McCall    return ExprError();
9463c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
9473c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9483c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  // If there is a setter, we definitely want to use it.
9493c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9504b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // We also need a getter.
9514b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (!findGetter()) {
9524b9c2d235fb9449e249d74f48ecfec601650de93John McCall    assert(RefExpr->isImplicitProperty());
9534b9c2d235fb9449e249d74f48ecfec601650de93John McCall    S.Diag(opcLoc, diag::err_nogetter_property_incdec)
9544b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << unsigned(UnaryOperator::isDecrementOp(opcode))
955a2c91e75c944e3599fb108db600f91c47c8b4342Fariborz Jahanian      << GetterSelector
9564b9c2d235fb9449e249d74f48ecfec601650de93John McCall      << op->getSourceRange();
9574b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return ExprError();
9584b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
9593c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
9604b9c2d235fb9449e249d74f48ecfec601650de93John McCall  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
9614b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
9623c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
96358b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan RoseExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
964c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() &&
965c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
966c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines                         SyntacticForm->getLocStart()))
967569b4ad6506960f1a7f191107c185cb1566a7fbbFariborz Jahanian      S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
968569b4ad6506960f1a7f191107c185cb1566a7fbbFariborz Jahanian                                 SyntacticRefExpr->isMessagingGetter());
96958b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
97058b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose  return PseudoOpBuilder::complete(SyntacticForm);
97158b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose}
97258b6bdcdeb683a3504f2248a409e1f4e85876ceeJordan Rose
973ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// ObjCSubscript build stuff.
974ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek//
975ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
976ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
977ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// conversion.
978ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// FIXME. Remove this routine if it is proven that no additional
979ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// specifity is needed.
980ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
981ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
982ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (result.isInvalid()) return ExprError();
983ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return result;
984ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
985ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
986ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// objective-c subscripting-specific  behavior for doing assignments.
987ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult
988ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
989ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation opcLoc,
990ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                BinaryOperatorKind opcode,
991ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                Expr *LHS, Expr *RHS) {
992ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  assert(BinaryOperator::isAssignmentOp(opcode));
993ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // There must be a method to do the Index'ed assignment.
994ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!findAtIndexSetter())
995ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
996ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
997ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Verify that we can do a compound assignment.
998ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (opcode != BO_Assign && !findAtIndexGetter())
999ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
1000ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1001ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult result =
1002ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
1003ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (result.isInvalid()) return ExprError();
1004ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1005ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Various warnings about objc Index'ed assignments in ARC.
10064e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
1007ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
1008ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
1009ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1010ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1011ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return result;
1012ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1013ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1014ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// Capture the base object of an Objective-C Index'ed expression.
1015ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExpr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
10166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  assert(InstanceBase == nullptr);
10176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
1018ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Capture base expression in an OVE and rebuild the syntactic
1019ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // form to use the OVE as its base expression.
1020ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  InstanceBase = capture(RefExpr->getBaseExpr());
1021ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  InstanceKey = capture(RefExpr->getKeyExpr());
102287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
1023ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  syntacticBase =
102487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
102587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        switch (Idx) {
102687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        case 0:
102787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          return InstanceBase;
102887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        case 1:
102987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          return InstanceKey;
103087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        default:
103187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar          llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
103287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar        }
103387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      }).rebuild(syntacticBase);
103487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar
1035ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return syntacticBase;
1036ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1037ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1038ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// CheckSubscriptingKind - This routine decide what type
1039ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// of indexing represented by "FromE" is being done.
1040ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekSema::ObjCSubscriptKind
1041ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Sema::CheckSubscriptingKind(Expr *FromE) {
1042ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // If the expression already has integral or enumeration type, we're golden.
1043ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType T = FromE->getType();
1044ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (T->isIntegralOrEnumerationType())
1045ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Array;
1046ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1047ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // If we don't have a class type in C++, there's no way we can get an
1048ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // expression of integral or enumeration type.
1049ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  const RecordType *RecordTy = T->getAs<RecordType>();
1050176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  if (!RecordTy &&
1051176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines      (T->isObjCObjectPointerType() || T->isVoidPointerType()))
1052ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // All other scalar cases are assumed to be dictionary indexing which
1053ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // caller handles, with diagnostics if needed.
1054ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Dictionary;
1055a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian  if (!getLangOpts().CPlusPlus ||
1056a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian      !RecordTy || RecordTy->isIncompleteType()) {
1057ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // No indexing can be done. Issue diagnostics and quit.
1058a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian    const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
1059a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian    if (isa<StringLiteral>(IndexExpr))
1060a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian      Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
1061a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian        << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
1062a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian    else
1063a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian      Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
1064a78eca20429e55b041bffcea1938cd0df07a6ebdFariborz Jahanian        << T;
1065ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Error;
1066ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1067ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1068ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // We must have a complete class type.
1069ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (RequireCompleteType(FromE->getExprLoc(), T,
1070d10099e5c8238fa0327f03921cf2e3c8975c881eDouglas Gregor                          diag::err_objc_index_incomplete_class_type, FromE))
1071ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Error;
1072ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1073ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Look for a conversion to an integral, enumeration type, or
1074ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // objective-C pointer type.
1075ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  int NoIntegrals=0, NoObjCIdPointers=0;
1076ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  SmallVector<CXXConversionDecl *, 4> ConversionDecls;
10770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines
10780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines  for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
10790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines                          ->getVisibleConversionFunctions()) {
10800e2c34f92f00628d48968dfea096d36381f494cbStephen Hines    if (CXXConversionDecl *Conversion =
10810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines            dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
1082ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      QualType CT = Conversion->getConversionType().getNonReferenceType();
1083ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      if (CT->isIntegralOrEnumerationType()) {
1084ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ++NoIntegrals;
1085ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ConversionDecls.push_back(Conversion);
1086ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      }
1087ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
1088ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ++NoObjCIdPointers;
1089ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        ConversionDecls.push_back(Conversion);
1090ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      }
1091ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1092ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1093ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (NoIntegrals ==1 && NoObjCIdPointers == 0)
1094ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Array;
1095ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (NoIntegrals == 0 && NoObjCIdPointers == 1)
1096ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Dictionary;
1097ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
1098ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // No conversion function was found. Issue diagnostic and return.
1099ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
1100ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << FromE->getType();
1101ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return OS_Error;
1102ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1103ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
1104ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << FromE->getType();
1105ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  for (unsigned int i = 0; i < ConversionDecls.size(); i++)
1106ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
1107ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1108ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return OS_Error;
1109ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1110ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1111dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
1112dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian/// objects used as dictionary subscript key objects.
1113dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanianstatic void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
1114dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                         Expr *Key) {
1115dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (ContainerT.isNull())
1116dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    return;
1117dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  // dictionary subscripting.
1118dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  // - (id)objectForKeyedSubscript:(id)key;
1119dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  IdentifierInfo *KeyIdents[] = {
1120dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    &S.Context.Idents.get("objectForKeyedSubscript")
1121dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  };
1122dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1123dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
1124dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                                      true /*instance*/);
1125dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (!Getter)
1126dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    return;
1127c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  QualType T = Getter->parameters()[0]->getType();
1128dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  S.CheckObjCARCConversion(Key->getSourceRange(),
1129dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                         T, Key, Sema::CCK_ImplicitConversion);
1130dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian}
1131dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian
1132ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenekbool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1133ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexGetter)
1134ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return true;
1135ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1136ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *BaseExpr = RefExpr->getBaseExpr();
1137ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType BaseT = BaseExpr->getType();
1138ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1139ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType ResultType;
1140ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (const ObjCObjectPointerType *PTy =
1141ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      BaseT->getAs<ObjCObjectPointerType>()) {
1142ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ResultType = PTy->getPointeeType();
1143ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1144ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Sema::ObjCSubscriptKind Res =
1145ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1146dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (Res == Sema::OS_Error) {
1147dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    if (S.getLangOpts().ObjCAutoRefCount)
1148dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian      CheckKeyForObjCARCConversion(S, ResultType,
1149dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                   RefExpr->getKeyExpr());
1150ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1151dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  }
1152ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool arrayRef = (Res == Sema::OS_Array);
1153ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1154ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (ResultType.isNull()) {
1155ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1156ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << arrayRef;
1157ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1158ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1159ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!arrayRef) {
1160ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // dictionary subscripting.
1161ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (id)objectForKeyedSubscript:(id)key;
1162ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1163ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("objectForKeyedSubscript")
1164ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1165ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1166ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1167ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else {
1168ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (id)objectAtIndexedSubscript:(size_t)index;
1169ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1170ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("objectAtIndexedSubscript")
1171ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1172ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1173ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1174ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1175ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1176ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
1177ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                             true /*instance*/);
1178ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool receiverIdType = (BaseT->isObjCIdType() ||
1179ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                         BaseT->isObjCQualifiedIdType());
1180ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
11814e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
1182ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
1183ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           SourceLocation(), AtIndexGetterSelector,
1184ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           S.Context.getObjCIdType() /*ReturnType*/,
11856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                           nullptr /*TypeSourceInfo */,
1186ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           S.Context.getTranslationUnitDecl(),
1187ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           true /*Instance*/, false/*isVariadic*/,
11881e4691b9d8e1bdcc8ef62b323969d702c51b3c08Jordan Rose                           /*isPropertyAccessor=*/false,
1189ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1190ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           ObjCMethodDecl::Required,
1191ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                           false);
1192ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1193ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation(), SourceLocation(),
1194ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ? &S.Context.Idents.get("index")
1195ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         : &S.Context.Idents.get("key"),
1196ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ? S.Context.UnsignedLongTy
1197ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         : S.Context.getObjCIdType(),
11986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                /*TInfo=*/nullptr,
1199ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
12006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                nullptr);
12015543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko    AtIndexGetter->setMethodParams(S.Context, Argument, None);
1202ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1203ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1204ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!AtIndexGetter) {
1205ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!receiverIdType) {
1206ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1207ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << 0 << arrayRef;
1208ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return false;
1209ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1210ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexGetter =
1211ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
1212ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                         RefExpr->getSourceRange(),
121358878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                                         true);
1214ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1215ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1216ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexGetter) {
1217c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    QualType T = AtIndexGetter->parameters()[0]->getType();
1218ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1219ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        (!arrayRef && !T->isObjCObjectPointerType())) {
1220ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1221ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             arrayRef ? diag::err_objc_subscript_index_type
1222ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                      : diag::err_objc_subscript_key_type) << T;
1223c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
1224ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::note_parameter_type) << T;
1225ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return false;
1226ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    QualType R = AtIndexGetter->getReturnType();
1228ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!R->isObjCObjectPointerType()) {
1229ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1230ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_indexing_method_result_type) << R << arrayRef;
1231ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1232ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        AtIndexGetter->getDeclName();
1233ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1234ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1235ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return true;
1236ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1237ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1238ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenekbool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1239ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexSetter)
1240ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return true;
1241ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1242ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *BaseExpr = RefExpr->getBaseExpr();
1243ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType BaseT = BaseExpr->getType();
1244ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1245ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType ResultType;
1246ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (const ObjCObjectPointerType *PTy =
1247ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      BaseT->getAs<ObjCObjectPointerType>()) {
1248ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ResultType = PTy->getPointeeType();
1249ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1250ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1251ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Sema::ObjCSubscriptKind Res =
1252ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.CheckSubscriptingKind(RefExpr->getKeyExpr());
1253dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  if (Res == Sema::OS_Error) {
1254dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian    if (S.getLangOpts().ObjCAutoRefCount)
1255dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian      CheckKeyForObjCARCConversion(S, ResultType,
1256dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian                                   RefExpr->getKeyExpr());
1257ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1258dc48305e319c56f6f305c12b9faecdc378dfebdcFariborz Jahanian  }
1259ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool arrayRef = (Res == Sema::OS_Array);
1260ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1261ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (ResultType.isNull()) {
1262ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1263ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << arrayRef;
1264ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return false;
1265ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1266ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1267ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!arrayRef) {
1268ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // dictionary subscripting.
1269ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1270ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1271ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("setObject"),
1272ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("forKeyedSubscript")
1273ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1274ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1275ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1276ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else {
1277ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1278ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    IdentifierInfo *KeyIdents[] = {
1279ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("setObject"),
1280ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      &S.Context.Idents.get("atIndexedSubscript")
1281ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    };
1282ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1283ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1284ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
1285ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                             true /*instance*/);
1286ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1287ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool receiverIdType = (BaseT->isObjCIdType() ||
1288ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                         BaseT->isObjCQualifiedIdType());
1289ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
12904e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
12916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    TypeSourceInfo *ReturnTInfo = nullptr;
1292ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    QualType ReturnType = S.Context.VoidTy;
1293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    AtIndexSetter = ObjCMethodDecl::Create(
1294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
1295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
1296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        true /*Instance*/, false /*isVariadic*/,
1297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        /*isPropertyAccessor=*/false,
1298651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1299651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ObjCMethodDecl::Required, false);
1300ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    SmallVector<ParmVarDecl *, 2> Params;
1301ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1302ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation(), SourceLocation(),
1303ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                &S.Context.Idents.get("object"),
1304ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                S.Context.getObjCIdType(),
13056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                /*TInfo=*/nullptr,
1306ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
13076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                nullptr);
1308ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Params.push_back(object);
1309ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1310ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SourceLocation(), SourceLocation(),
1311ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ?  &S.Context.Idents.get("index")
1312ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         :  &S.Context.Idents.get("key"),
1313ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                arrayRef ? S.Context.UnsignedLongTy
1314ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                         : S.Context.getObjCIdType(),
13156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                /*TInfo=*/nullptr,
1316ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                SC_None,
13176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                                nullptr);
1318ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Params.push_back(key);
13195543169296beeb183b9c9392debc774fcf493eebDmitri Gribenko    AtIndexSetter->setMethodParams(S.Context, Params, None);
1320ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1321ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1322ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!AtIndexSetter) {
1323ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!receiverIdType) {
1324ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(BaseExpr->getExprLoc(),
1325ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_subscript_method_not_found)
1326ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      << BaseExpr->getType() << 1 << arrayRef;
1327ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      return false;
1328ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1329ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    AtIndexSetter =
1330ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
1331ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                         RefExpr->getSourceRange(),
133258878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar                                         true);
1333ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1334ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1335ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  bool err = false;
1336ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (AtIndexSetter && arrayRef) {
1337c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    QualType T = AtIndexSetter->parameters()[1]->getType();
1338ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!T->isIntegralOrEnumerationType()) {
1339ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1340ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_subscript_index_type) << T;
1341c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
1342ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::note_parameter_type) << T;
1343ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      err = true;
1344ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1345c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    T = AtIndexSetter->parameters()[0]->getType();
1346ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    if (!T->isObjCObjectPointerType()) {
1347ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1348ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::err_objc_subscript_object_type) << T << arrayRef;
1349c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
1350ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             diag::note_parameter_type) << T;
1351ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      err = true;
1352ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1353ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1354ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else if (AtIndexSetter && !arrayRef)
1355ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    for (unsigned i=0; i <2; i++) {
1356c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines      QualType T = AtIndexSetter->parameters()[i]->getType();
1357ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      if (!T->isObjCObjectPointerType()) {
1358ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        if (i == 1)
1359ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek          S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1360ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                 diag::err_objc_subscript_key_type) << T;
1361ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        else
1362ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek          S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1363ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                 diag::err_objc_subscript_dic_object_type) << T;
1364c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines        S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
1365ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek               diag::note_parameter_type) << T;
1366ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek        err = true;
1367ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      }
1368ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    }
1369ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1370ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return !err;
1371ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1372ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1373ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// Get the object at "Index" position in the container.
1374ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek// [BaseExpr objectAtIndexedSubscript : IndexExpr];
1375ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildGet() {
1376ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!findAtIndexGetter())
1377ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
1378ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1379ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType receiverType = InstanceBase->getType();
1380ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1381ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Build a message-send.
1382ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult msg;
1383ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *Index = InstanceKey;
1384ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1385ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Arguments.
1386ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *args[] = { Index };
1387ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  assert(InstanceBase);
1388c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (AtIndexGetter)
1389c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);
1390ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1391ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       GenericLoc,
1392ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       AtIndexGetterSelector, AtIndexGetter,
1393ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                       MultiExprArg(args, 1));
1394ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return msg;
1395ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1396ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1397ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// Store into the container the "op" object at "Index"'ed location
1398ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// by building this messaging expression:
1399ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
140070517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko/// \param captureSetValueAsResult If true, capture the actual
1401ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek///   value being set as the value of the property operation.
1402ebcb57a8d298862c65043e88b2429591ab3c58d3Ted KremenekExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
1403ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                           bool captureSetValueAsResult) {
1404ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!findAtIndexSetter())
1405ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
1406c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  if (AtIndexSetter)
1407c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);
1408ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  QualType receiverType = InstanceBase->getType();
1409ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *Index = InstanceKey;
1410ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1411ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Arguments.
1412ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  Expr *args[] = { op, Index };
1413ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1414ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  // Build a message-send.
1415ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
1416ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  GenericLoc,
1417ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  AtIndexSetterSelector,
1418ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  AtIndexSetter,
1419ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek                                                  MultiExprArg(args, 2));
1420ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1421ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  if (!msg.isInvalid() && captureSetValueAsResult) {
1422ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCMessageExpr *msgExpr =
1423ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1424ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Expr *arg = msgExpr->getArg(0);
1425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (CanCaptureValue(arg))
142625f071eedf5d20faf9e1614d5ff5dc39b6de5041Eli Friedman      msgExpr->setArg(0, captureValueAsResult(arg));
1427ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1428ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
1429ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  return msg;
1430ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek}
1431ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek
14324b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
143376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall//  MSVC __declspec(property) references
143476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall//===----------------------------------------------------------------------===//
143576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
143687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarMSPropertyRefExpr *
143787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarMSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
143887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  CallArgs.insert(CallArgs.begin(), E->getIdx());
143987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  Expr *Base = E->getBase()->IgnoreParens();
144087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
144187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
144287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    Base = MSPropSubscript->getBase()->IgnoreParens();
144387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  }
144487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return cast<MSPropertyRefExpr>(Base);
144587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar}
144676da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
144787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga NainarExpr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
144887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  InstanceBase = capture(RefExpr->getBaseExpr());
144987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  std::for_each(CallArgs.begin(), CallArgs.end(),
145087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                [this](Expr *&Arg) { Arg = capture(Arg); });
145187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
145287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                    switch (Idx) {
145387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                    case 0:
145487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                      return InstanceBase;
145587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                    default:
145687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                      assert(Idx <= CallArgs.size());
145787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                      return CallArgs[Idx - 1];
145887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                    }
145987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                  }).rebuild(syntacticBase);
146076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
146176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  return syntacticBase;
146276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall}
146376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
146476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCallExprResult MSPropertyOpBuilder::buildGet() {
146576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  if (!RefExpr->getPropertyDecl()->hasGetter()) {
1466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
1467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << 0 /* getter */ << RefExpr->getPropertyDecl();
146876da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return ExprError();
146976da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  }
147076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
147176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  UnqualifiedId GetterName;
147276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();
147376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  GetterName.setIdentifier(II, RefExpr->getMemberLoc());
147476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  CXXScopeSpec SS;
147576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  SS.Adopt(RefExpr->getQualifierLoc());
147687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  ExprResult GetterExpr =
147787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
147887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                              RefExpr->isArrow() ? tok::arrow : tok::period, SS,
147987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                              SourceLocation(), GetterName, nullptr);
148076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  if (GetterExpr.isInvalid()) {
1481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    S.Diag(RefExpr->getMemberLoc(),
1482651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines           diag::error_cannot_find_suitable_accessor) << 0 /* getter */
1483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << RefExpr->getPropertyDecl();
148476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return ExprError();
148576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  }
148676da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
1487c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
148887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                         RefExpr->getSourceRange().getBegin(), CallArgs,
148976da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall                         RefExpr->getSourceRange().getEnd());
149076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall}
149176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
149276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCallExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
149376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall                                         bool captureSetValueAsResult) {
149476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  if (!RefExpr->getPropertyDecl()->hasSetter()) {
1495651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
1496651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << 1 /* setter */ << RefExpr->getPropertyDecl();
149776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return ExprError();
149876da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  }
149976da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
150076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  UnqualifiedId SetterName;
150176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();
150276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  SetterName.setIdentifier(II, RefExpr->getMemberLoc());
150376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  CXXScopeSpec SS;
150476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  SS.Adopt(RefExpr->getQualifierLoc());
150587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  ExprResult SetterExpr =
150687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
150787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                              RefExpr->isArrow() ? tok::arrow : tok::period, SS,
150887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                              SourceLocation(), SetterName, nullptr);
150976da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  if (SetterExpr.isInvalid()) {
1510651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    S.Diag(RefExpr->getMemberLoc(),
1511651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines           diag::error_cannot_find_suitable_accessor) << 1 /* setter */
1512651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      << RefExpr->getPropertyDecl();
151376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return ExprError();
151476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  }
151576da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
151687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  SmallVector<Expr*, 4> ArgExprs;
151787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  ArgExprs.append(CallArgs.begin(), CallArgs.end());
151876da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  ArgExprs.push_back(op);
1519c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines  return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
152076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall                         RefExpr->getSourceRange().getBegin(), ArgExprs,
152176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall                         op->getSourceRange().getEnd());
152276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall}
152376da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall
152476da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall//===----------------------------------------------------------------------===//
15254b9c2d235fb9449e249d74f48ecfec601650de93John McCall//  General Sema routines.
15264b9c2d235fb9449e249d74f48ecfec601650de93John McCall//===----------------------------------------------------------------------===//
15273c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
15284b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectRValue(Expr *E) {
15294b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = E->IgnoreParens();
15304b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
15314b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
15324b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
15334b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildRValueOperation(E);
1534ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  }
1535ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  else if (ObjCSubscriptRefExpr *refExpr
1536ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek           = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1537ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptOpBuilder builder(*this, refExpr);
1538ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return builder.buildRValueOperation(E);
153976da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  } else if (MSPropertyRefExpr *refExpr
154076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
154176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    MSPropertyOpBuilder builder(*this, refExpr);
154276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return builder.buildRValueOperation(E);
154387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  } else if (MSPropertySubscriptExpr *RefExpr =
154487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                 dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
154587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    MSPropertyOpBuilder Builder(*this, RefExpr);
154687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    return Builder.buildRValueOperation(E);
15474b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
15484b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
15493c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
15504b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
15513c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
15524b9c2d235fb9449e249d74f48ecfec601650de93John McCall/// Check an increment or decrement of a pseudo-object expression.
15534b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
15544b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                         UnaryOperatorKind opcode, Expr *op) {
15554b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do nothing if the operand is dependent.
15564b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (op->isTypeDependent())
15574b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
15584b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                       VK_RValue, OK_Ordinary, opcLoc);
15594b9c2d235fb9449e249d74f48ecfec601650de93John McCall
15604b9c2d235fb9449e249d74f48ecfec601650de93John McCall  assert(UnaryOperator::isIncrementDecrementOp(opcode));
15614b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = op->IgnoreParens();
15624b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
15634b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
15644b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
15654b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1566ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1567ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1568ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return ExprError();
156976da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  } else if (MSPropertyRefExpr *refExpr
157076da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
157176da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    MSPropertyOpBuilder builder(*this, refExpr);
157276da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
157387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  } else if (MSPropertySubscriptExpr *RefExpr
157487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
157587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    MSPropertyOpBuilder Builder(*this, RefExpr);
157687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
15774b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
15784b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
15793c3b7f90a863af43fa63043d396553ecf205351cJohn McCall  }
15804b9c2d235fb9449e249d74f48ecfec601650de93John McCall}
15813c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
15824b9c2d235fb9449e249d74f48ecfec601650de93John McCallExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
15834b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             BinaryOperatorKind opcode,
15844b9c2d235fb9449e249d74f48ecfec601650de93John McCall                                             Expr *LHS, Expr *RHS) {
15854b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Do nothing if either argument is dependent.
15864b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (LHS->isTypeDependent() || RHS->isTypeDependent())
15874b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
1588be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                        VK_RValue, OK_Ordinary, opcLoc, false);
15894b9c2d235fb9449e249d74f48ecfec601650de93John McCall
15904b9c2d235fb9449e249d74f48ecfec601650de93John McCall  // Filter out non-overload placeholder types in the RHS.
159132509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall  if (RHS->getType()->isNonOverloadPlaceholderType()) {
159232509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall    ExprResult result = CheckPlaceholderExpr(RHS);
159332509f1e60451d86e9fbc473b6e853ba10b5fd1eJohn McCall    if (result.isInvalid()) return ExprError();
1594c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines    RHS = result.get();
15954b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
15963c3b7f90a863af43fa63043d396553ecf205351cJohn McCall
15974b9c2d235fb9449e249d74f48ecfec601650de93John McCall  Expr *opaqueRef = LHS->IgnoreParens();
15984b9c2d235fb9449e249d74f48ecfec601650de93John McCall  if (ObjCPropertyRefExpr *refExpr
15994b9c2d235fb9449e249d74f48ecfec601650de93John McCall        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
16004b9c2d235fb9449e249d74f48ecfec601650de93John McCall    ObjCPropertyOpBuilder builder(*this, refExpr);
16014b9c2d235fb9449e249d74f48ecfec601650de93John McCall    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1602ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek  } else if (ObjCSubscriptRefExpr *refExpr
1603ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek             = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1604ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    ObjCSubscriptOpBuilder builder(*this, refExpr);
1605ebcb57a8d298862c65043e88b2429591ab3c58d3Ted Kremenek    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
160676da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  } else if (MSPropertyRefExpr *refExpr
160776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
160887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      MSPropertyOpBuilder builder(*this, refExpr);
160987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
161087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  } else if (MSPropertySubscriptExpr *RefExpr
161187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
161287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      MSPropertyOpBuilder Builder(*this, RefExpr);
161387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
16144b9c2d235fb9449e249d74f48ecfec601650de93John McCall  } else {
16154b9c2d235fb9449e249d74f48ecfec601650de93John McCall    llvm_unreachable("unknown pseudo-object kind!");
16164b9c2d235fb9449e249d74f48ecfec601650de93John McCall  }
16173c3b7f90a863af43fa63043d396553ecf205351cJohn McCall}
161801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall
161901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// Given a pseudo-object reference, rebuild it without the opaque
162001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// values.  Basically, undo the behavior of rebuildAndCaptureObject.
162101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// This should never operate in-place.
162201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCallstatic Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
162387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  return Rebuilder(S,
162487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                   [=](Expr *E, unsigned) -> Expr * {
162587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                     return cast<OpaqueValueExpr>(E)->getSourceExpr();
162687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar                   })
162787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar      .rebuild(E);
162801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall}
162901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall
163001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// Given a pseudo-object expression, recreate what it looks like
163101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// syntactically without the attendant OpaqueValueExprs.
163201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall///
163301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// This is a hack which should be removed when TreeTransform is
163401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// capable of rebuilding a tree without stripping implicit
163501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall/// operations.
163601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCallExpr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
163701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  Expr *syntax = E->getSyntacticForm();
163801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
163901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
164001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
164101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                       uop->getValueKind(), uop->getObjectKind(),
164201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                       uop->getOperatorLoc());
164301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else if (CompoundAssignOperator *cop
164401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall               = dyn_cast<CompoundAssignOperator>(syntax)) {
164501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
164601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
164701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
164801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getType(),
164901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getValueKind(),
165001e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getObjectKind(),
165101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getComputationLHSType(),
165201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                                cop->getComputationResultType(),
1653be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                                cop->getOperatorLoc(), false);
165401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
165501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
165601e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
165701e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
165801e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                        bop->getType(), bop->getValueKind(),
165901e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall                                        bop->getObjectKind(),
1660be9af1288881110e406b87914162eaa59f1e5918Lang Hames                                        bop->getOperatorLoc(), false);
166101e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  } else {
166201e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
166301e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall    return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
166401e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall  }
166501e19be69a37bc4ab7746c454cfaa6aec7bb7c6aJohn McCall}
1666