brintos

brintos / llvm-project-archived public Read only

0
0
Text · 61.5 KiB · 6673667 Raw
1594 lines · cpp
1//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements semantic analysis for expressions involving10//  pseudo-object references.  Pseudo-objects are conceptual objects11//  whose storage is entirely abstract and all accesses to which are12//  translated through some sort of abstraction barrier.13//14//  For example, Objective-C objects can have "properties", either15//  declared or undeclared.  A property may be accessed by writing16//    expr.prop17//  where 'expr' is an r-value of Objective-C pointer type and 'prop'18//  is the name of the property.  If this expression is used in a context19//  needing an r-value, it is treated as if it were a message-send20//  of the associated 'getter' selector, typically:21//    [expr prop]22//  If it is used as the LHS of a simple assignment, it is treated23//  as a message-send of the associated 'setter' selector, typically:24//    [expr setProp: RHS]25//  If it is used as the LHS of a compound assignment, or the operand26//  of a unary increment or decrement, both are required;  for example,27//  'expr.prop *= 100' would be translated to:28//    [expr setProp: [expr prop] * 100]29//30//===----------------------------------------------------------------------===//31 32#include "clang/Sema/SemaPseudoObject.h"33#include "clang/AST/ExprCXX.h"34#include "clang/AST/ExprObjC.h"35#include "clang/Basic/CharInfo.h"36#include "clang/Lex/Preprocessor.h"37#include "clang/Sema/Initialization.h"38#include "clang/Sema/ScopeInfo.h"39#include "clang/Sema/SemaObjC.h"40 41using namespace clang;42using namespace sema;43 44namespace {45  // Basically just a very focused copy of TreeTransform.46  struct Rebuilder {47    Sema &S;48    unsigned MSPropertySubscriptCount;49    typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;50    const SpecificRebuilderRefTy &SpecificCallback;51    Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)52        : S(S), MSPropertySubscriptCount(0),53          SpecificCallback(SpecificCallback) {}54 55    Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {56      // Fortunately, the constraint that we're rebuilding something57      // with a base limits the number of cases here.58      if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())59        return refExpr;60 61      if (refExpr->isExplicitProperty()) {62        return new (S.Context) ObjCPropertyRefExpr(63            refExpr->getExplicitProperty(), refExpr->getType(),64            refExpr->getValueKind(), refExpr->getObjectKind(),65            refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));66      }67      return new (S.Context) ObjCPropertyRefExpr(68          refExpr->getImplicitPropertyGetter(),69          refExpr->getImplicitPropertySetter(), refExpr->getType(),70          refExpr->getValueKind(), refExpr->getObjectKind(),71          refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));72    }73    Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {74      assert(refExpr->getBaseExpr());75      assert(refExpr->getKeyExpr());76 77      return new (S.Context) ObjCSubscriptRefExpr(78          SpecificCallback(refExpr->getBaseExpr(), 0),79          SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),80          refExpr->getValueKind(), refExpr->getObjectKind(),81          refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),82          refExpr->getRBracket());83    }84    Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {85      assert(refExpr->getBaseExpr());86 87      return new (S.Context) MSPropertyRefExpr(88          SpecificCallback(refExpr->getBaseExpr(), 0),89          refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),90          refExpr->getValueKind(), refExpr->getQualifierLoc(),91          refExpr->getMemberLoc());92    }93    Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {94      assert(refExpr->getBase());95      assert(refExpr->getIdx());96 97      auto *NewBase = rebuild(refExpr->getBase());98      ++MSPropertySubscriptCount;99      return new (S.Context) MSPropertySubscriptExpr(100          NewBase,101          SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),102          refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),103          refExpr->getRBracketLoc());104    }105 106    Expr *rebuild(Expr *e) {107      // Fast path: nothing to look through.108      if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))109        return rebuildObjCPropertyRefExpr(PRE);110      if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))111        return rebuildObjCSubscriptRefExpr(SRE);112      if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))113        return rebuildMSPropertyRefExpr(MSPRE);114      if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))115        return rebuildMSPropertySubscriptExpr(MSPSE);116 117      // Otherwise, we should look through and rebuild anything that118      // IgnoreParens would.119 120      if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {121        e = rebuild(parens->getSubExpr());122        return new (S.Context) ParenExpr(parens->getLParen(),123                                         parens->getRParen(),124                                         e);125      }126 127      if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {128        assert(uop->getOpcode() == UO_Extension);129        e = rebuild(uop->getSubExpr());130        return UnaryOperator::Create(131            S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),132            uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),133            S.CurFPFeatureOverrides());134      }135 136      if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {137        assert(!gse->isResultDependent());138        unsigned resultIndex = gse->getResultIndex();139        unsigned numAssocs = gse->getNumAssocs();140 141        SmallVector<Expr *, 8> assocExprs;142        SmallVector<TypeSourceInfo *, 8> assocTypes;143        assocExprs.reserve(numAssocs);144        assocTypes.reserve(numAssocs);145 146        for (const GenericSelectionExpr::Association assoc :147             gse->associations()) {148          Expr *assocExpr = assoc.getAssociationExpr();149          if (assoc.isSelected())150            assocExpr = rebuild(assocExpr);151          assocExprs.push_back(assocExpr);152          assocTypes.push_back(assoc.getTypeSourceInfo());153        }154 155        if (gse->isExprPredicate())156          return GenericSelectionExpr::Create(157              S.Context, gse->getGenericLoc(), gse->getControllingExpr(),158              assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),159              gse->containsUnexpandedParameterPack(), resultIndex);160        return GenericSelectionExpr::Create(161            S.Context, gse->getGenericLoc(), gse->getControllingType(),162            assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),163            gse->containsUnexpandedParameterPack(), resultIndex);164      }165 166      if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {167        assert(!ce->isConditionDependent());168 169        Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();170        Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;171        rebuiltExpr = rebuild(rebuiltExpr);172 173        return new (S.Context)174            ChooseExpr(ce->getBuiltinLoc(), ce->getCond(), LHS, RHS,175                       rebuiltExpr->getType(), rebuiltExpr->getValueKind(),176                       rebuiltExpr->getObjectKind(), ce->getRParenLoc(),177                       ce->isConditionTrue());178      }179 180      llvm_unreachable("bad expression to rebuild!");181    }182  };183 184  class PseudoOpBuilder {185  public:186    Sema &S;187    unsigned ResultIndex;188    SourceLocation GenericLoc;189    bool IsUnique;190    SmallVector<Expr *, 4> Semantics;191 192    PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)193      : S(S), ResultIndex(PseudoObjectExpr::NoResult),194        GenericLoc(genericLoc), IsUnique(IsUnique) {}195 196    virtual ~PseudoOpBuilder() {}197 198    /// Add a normal semantic expression.199    void addSemanticExpr(Expr *semantic) {200      Semantics.push_back(semantic);201    }202 203    /// Add the 'result' semantic expression.204    void addResultSemanticExpr(Expr *resultExpr) {205      assert(ResultIndex == PseudoObjectExpr::NoResult);206      ResultIndex = Semantics.size();207      Semantics.push_back(resultExpr);208      // An OVE is not unique if it is used as the result expression.209      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))210        OVE->setIsUnique(false);211    }212 213    ExprResult buildRValueOperation(Expr *op);214    ExprResult buildAssignmentOperation(Scope *Sc,215                                        SourceLocation opLoc,216                                        BinaryOperatorKind opcode,217                                        Expr *LHS, Expr *RHS);218    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,219                                    UnaryOperatorKind opcode,220                                    Expr *op);221 222    virtual ExprResult complete(Expr *syntacticForm);223 224    OpaqueValueExpr *capture(Expr *op);225    OpaqueValueExpr *captureValueAsResult(Expr *op);226 227    void setResultToLastSemantic() {228      assert(ResultIndex == PseudoObjectExpr::NoResult);229      ResultIndex = Semantics.size() - 1;230      // An OVE is not unique if it is used as the result expression.231      if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantics.back()))232        OVE->setIsUnique(false);233    }234 235    /// Return true if assignments have a non-void result.236    static bool CanCaptureValue(Expr *exp) {237      if (exp->isGLValue())238        return true;239      QualType ty = exp->getType();240      assert(!ty->isIncompleteType());241      assert(!ty->isDependentType());242 243      if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl())244        return ClassDecl->isTriviallyCopyable();245      return true;246    }247 248    virtual Expr *rebuildAndCaptureObject(Expr *) = 0;249    virtual ExprResult buildGet() = 0;250    virtual ExprResult buildSet(Expr *, SourceLocation,251                                bool captureSetValueAsResult) = 0;252    /// Should the result of an assignment be the formal result of the253    /// setter call or the value that was passed to the setter?254    ///255    /// Different pseudo-object language features use different language rules256    /// for this.257    /// The default is to use the set value.  Currently, this affects the258    /// behavior of simple assignments, compound assignments, and prefix259    /// increment and decrement.260    /// Postfix increment and decrement always use the getter result as the261    /// expression result.262    ///263    /// If this method returns true, and the set value isn't capturable for264    /// some reason, the result of the expression will be void.265    virtual bool captureSetValueAsResult() const { return true; }266  };267 268  /// A PseudoOpBuilder for Objective-C \@properties.269  class ObjCPropertyOpBuilder : public PseudoOpBuilder {270    ObjCPropertyRefExpr *RefExpr;271    ObjCPropertyRefExpr *SyntacticRefExpr;272    OpaqueValueExpr *InstanceReceiver;273    ObjCMethodDecl *Getter;274 275    ObjCMethodDecl *Setter;276    Selector SetterSelector;277    Selector GetterSelector;278 279  public:280    ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr, bool IsUnique)281        : PseudoOpBuilder(S, refExpr->getLocation(), IsUnique),282          RefExpr(refExpr), SyntacticRefExpr(nullptr),283          InstanceReceiver(nullptr), Getter(nullptr), Setter(nullptr) {284    }285 286    ExprResult buildRValueOperation(Expr *op);287    ExprResult buildAssignmentOperation(Scope *Sc,288                                        SourceLocation opLoc,289                                        BinaryOperatorKind opcode,290                                        Expr *LHS, Expr *RHS);291    ExprResult buildIncDecOperation(Scope *Sc, SourceLocation opLoc,292                                    UnaryOperatorKind opcode,293                                    Expr *op);294 295    bool tryBuildGetOfReference(Expr *op, ExprResult &result);296    bool findSetter(bool warn=true);297    bool findGetter();298    void DiagnoseUnsupportedPropertyUse();299 300    Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;301    ExprResult buildGet() override;302    ExprResult buildSet(Expr *op, SourceLocation, bool) override;303    ExprResult complete(Expr *SyntacticForm) override;304 305    bool isWeakProperty() const;306  };307 308 /// A PseudoOpBuilder for Objective-C array/dictionary indexing.309 class ObjCSubscriptOpBuilder : public PseudoOpBuilder {310   ObjCSubscriptRefExpr *RefExpr;311   OpaqueValueExpr *InstanceBase;312   OpaqueValueExpr *InstanceKey;313   ObjCMethodDecl *AtIndexGetter;314   Selector AtIndexGetterSelector;315 316   ObjCMethodDecl *AtIndexSetter;317   Selector AtIndexSetterSelector;318 319 public:320   ObjCSubscriptOpBuilder(Sema &S, ObjCSubscriptRefExpr *refExpr, bool IsUnique)321       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),322         RefExpr(refExpr), InstanceBase(nullptr), InstanceKey(nullptr),323         AtIndexGetter(nullptr), AtIndexSetter(nullptr) {}324 325   ExprResult buildRValueOperation(Expr *op);326   ExprResult buildAssignmentOperation(Scope *Sc,327                                       SourceLocation opLoc,328                                       BinaryOperatorKind opcode,329                                       Expr *LHS, Expr *RHS);330   Expr *rebuildAndCaptureObject(Expr *syntacticBase) override;331 332   bool findAtIndexGetter();333   bool findAtIndexSetter();334 335   ExprResult buildGet() override;336   ExprResult buildSet(Expr *op, SourceLocation, bool) override;337 };338 339 class MSPropertyOpBuilder : public PseudoOpBuilder {340   MSPropertyRefExpr *RefExpr;341   OpaqueValueExpr *InstanceBase;342   SmallVector<Expr *, 4> CallArgs;343 344   MSPropertyRefExpr *getBaseMSProperty(MSPropertySubscriptExpr *E);345 346 public:347   MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)348       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),349         RefExpr(refExpr), InstanceBase(nullptr) {}350   MSPropertyOpBuilder(Sema &S, MSPropertySubscriptExpr *refExpr, bool IsUnique)351       : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),352         InstanceBase(nullptr) {353     RefExpr = getBaseMSProperty(refExpr);354   }355 356   Expr *rebuildAndCaptureObject(Expr *) override;357   ExprResult buildGet() override;358   ExprResult buildSet(Expr *op, SourceLocation, bool) override;359   bool captureSetValueAsResult() const override { return false; }360 };361}362 363/// Capture the given expression in an OpaqueValueExpr.364OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) {365  // Make a new OVE whose source is the given expression.366  OpaqueValueExpr *captured =367    new (S.Context) OpaqueValueExpr(GenericLoc, e->getType(),368                                    e->getValueKind(), e->getObjectKind(),369                                    e);370  if (IsUnique)371    captured->setIsUnique(true);372 373  // Make sure we bind that in the semantics.374  addSemanticExpr(captured);375  return captured;376}377 378/// Capture the given expression as the result of this pseudo-object379/// operation.  This routine is safe against expressions which may380/// already be captured.381///382/// \returns the captured expression, which will be the383///   same as the input if the input was already captured384OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) {385  assert(ResultIndex == PseudoObjectExpr::NoResult);386 387  // If the expression hasn't already been captured, just capture it388  // and set the new semantic389  if (!isa<OpaqueValueExpr>(e)) {390    OpaqueValueExpr *cap = capture(e);391    setResultToLastSemantic();392    return cap;393  }394 395  // Otherwise, it must already be one of our semantic expressions;396  // set ResultIndex to its index.397  unsigned index = 0;398  for (;; ++index) {399    assert(index < Semantics.size() &&400           "captured expression not found in semantics!");401    if (e == Semantics[index]) break;402  }403  ResultIndex = index;404  // An OVE is not unique if it is used as the result expression.405  cast<OpaqueValueExpr>(e)->setIsUnique(false);406  return cast<OpaqueValueExpr>(e);407}408 409/// The routine which creates the final PseudoObjectExpr.410ExprResult PseudoOpBuilder::complete(Expr *syntactic) {411  return PseudoObjectExpr::Create(S.Context, syntactic,412                                  Semantics, ResultIndex);413}414 415/// The main skeleton for building an r-value operation.416ExprResult PseudoOpBuilder::buildRValueOperation(Expr *op) {417  Expr *syntacticBase = rebuildAndCaptureObject(op);418 419  ExprResult getExpr = buildGet();420  if (getExpr.isInvalid()) return ExprError();421  addResultSemanticExpr(getExpr.get());422 423  return complete(syntacticBase);424}425 426/// The basic skeleton for building a simple or compound427/// assignment operation.428ExprResult429PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc,430                                          BinaryOperatorKind opcode,431                                          Expr *LHS, Expr *RHS) {432  assert(BinaryOperator::isAssignmentOp(opcode));433 434  Expr *syntacticLHS = rebuildAndCaptureObject(LHS);435  OpaqueValueExpr *capturedRHS = capture(RHS);436 437  // In some very specific cases, semantic analysis of the RHS as an438  // expression may require it to be rewritten.  In these cases, we439  // cannot safely keep the OVE around.  Fortunately, we don't really440  // need to: we don't use this particular OVE in multiple places, and441  // no clients rely that closely on matching up expressions in the442  // semantic expression with expressions from the syntactic form.443  Expr *semanticRHS = capturedRHS;444  if (RHS->hasPlaceholderType() || isa<InitListExpr>(RHS)) {445    semanticRHS = RHS;446    Semantics.pop_back();447  }448 449  Expr *syntactic;450 451  ExprResult result;452  if (opcode == BO_Assign) {453    result = semanticRHS;454    syntactic = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS,455                                       opcode, capturedRHS->getType(),456                                       capturedRHS->getValueKind(), OK_Ordinary,457                                       opcLoc, S.CurFPFeatureOverrides());458 459  } else {460    ExprResult opLHS = buildGet();461    if (opLHS.isInvalid()) return ExprError();462 463    // Build an ordinary, non-compound operation.464    BinaryOperatorKind nonCompound =465      BinaryOperator::getOpForCompoundAssignment(opcode);466    result = S.BuildBinOp(Sc, opcLoc, nonCompound, opLHS.get(), semanticRHS);467    if (result.isInvalid()) return ExprError();468 469    syntactic = CompoundAssignOperator::Create(470        S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),471        result.get()->getValueKind(), OK_Ordinary, opcLoc,472        S.CurFPFeatureOverrides(), opLHS.get()->getType(),473        result.get()->getType());474  }475 476  // The result of the assignment, if not void, is the value set into477  // the l-value.478  result = buildSet(result.get(), opcLoc, captureSetValueAsResult());479  if (result.isInvalid()) return ExprError();480  addSemanticExpr(result.get());481  if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&482      (result.get()->isTypeDependent() || CanCaptureValue(result.get())))483    setResultToLastSemantic();484 485  return complete(syntactic);486}487 488/// The basic skeleton for building an increment or decrement489/// operation.490ExprResult491PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,492                                      UnaryOperatorKind opcode,493                                      Expr *op) {494  assert(UnaryOperator::isIncrementDecrementOp(opcode));495 496  Expr *syntacticOp = rebuildAndCaptureObject(op);497 498  // Load the value.499  ExprResult result = buildGet();500  if (result.isInvalid()) return ExprError();501 502  QualType resultType = result.get()->getType();503 504  // That's the postfix result.505  if (UnaryOperator::isPostfix(opcode) &&506      (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {507    result = capture(result.get());508    setResultToLastSemantic();509  }510 511  // Add or subtract a literal 1.512  llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);513  Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,514                                     GenericLoc);515 516  if (UnaryOperator::isIncrementOp(opcode)) {517    result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one);518  } else {519    result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one);520  }521  if (result.isInvalid()) return ExprError();522 523  // Store that back into the result.  The value stored is the result524  // of a prefix operation.525  result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&526                                              captureSetValueAsResult());527  if (result.isInvalid()) return ExprError();528  addSemanticExpr(result.get());529  if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&530      !result.get()->getType()->isVoidType() &&531      (result.get()->isTypeDependent() || CanCaptureValue(result.get())))532    setResultToLastSemantic();533 534  UnaryOperator *syntactic =535      UnaryOperator::Create(S.Context, syntacticOp, opcode, resultType,536                            VK_LValue, OK_Ordinary, opcLoc,537                            !resultType->isDependentType()538                                ? S.Context.getTypeSize(resultType) >=539                                      S.Context.getTypeSize(S.Context.IntTy)540                                : false,541                            S.CurFPFeatureOverrides());542  return complete(syntactic);543}544 545 546//===----------------------------------------------------------------------===//547//  Objective-C @property and implicit property references548//===----------------------------------------------------------------------===//549 550/// Look up a method in the receiver type of an Objective-C property551/// reference.552static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,553                                            const ObjCPropertyRefExpr *PRE) {554  if (PRE->isObjectReceiver()) {555    const ObjCObjectPointerType *PT =556      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();557 558    // Special case for 'self' in class method implementations.559    if (PT->isObjCClassType() &&560        S.ObjC().isSelfExpr(const_cast<Expr *>(PRE->getBase()))) {561      // This cast is safe because isSelfExpr is only true within562      // methods.563      ObjCMethodDecl *method =564        cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());565      return S.ObjC().LookupMethodInObjectType(566          sel, S.Context.getObjCInterfaceType(method->getClassInterface()),567          /*instance*/ false);568    }569 570    return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);571  }572 573  if (PRE->isSuperReceiver()) {574    if (const ObjCObjectPointerType *PT =575        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())576      return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);577 578    return S.ObjC().LookupMethodInObjectType(sel, PRE->getSuperReceiverType(),579                                             false);580  }581 582  assert(PRE->isClassReceiver() && "Invalid expression");583  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());584  return S.ObjC().LookupMethodInObjectType(sel, IT, false);585}586 587bool ObjCPropertyOpBuilder::isWeakProperty() const {588  QualType T;589  if (RefExpr->isExplicitProperty()) {590    const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();591    if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak)592      return true;593 594    T = Prop->getType();595  } else if (Getter) {596    T = Getter->getReturnType();597  } else {598    return false;599  }600 601  return T.getObjCLifetime() == Qualifiers::OCL_Weak;602}603 604bool ObjCPropertyOpBuilder::findGetter() {605  if (Getter) return true;606 607  // For implicit properties, just trust the lookup we already did.608  if (RefExpr->isImplicitProperty()) {609    if ((Getter = RefExpr->getImplicitPropertyGetter())) {610      GetterSelector = Getter->getSelector();611      return true;612    }613    else {614      // Must build the getter selector the hard way.615      ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();616      assert(setter && "both setter and getter are null - cannot happen");617      const IdentifierInfo *setterName =618          setter->getSelector().getIdentifierInfoForSlot(0);619      const IdentifierInfo *getterName =620          &S.Context.Idents.get(setterName->getName().substr(3));621      GetterSelector =622        S.PP.getSelectorTable().getNullarySelector(getterName);623      return false;624    }625  }626 627  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();628  Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr);629  return (Getter != nullptr);630}631 632/// Try to find the most accurate setter declaration for the property633/// reference.634///635/// \return true if a setter was found, in which case Setter636bool ObjCPropertyOpBuilder::findSetter(bool warn) {637  // For implicit properties, just trust the lookup we already did.638  if (RefExpr->isImplicitProperty()) {639    if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {640      Setter = setter;641      SetterSelector = setter->getSelector();642      return true;643    } else {644      const IdentifierInfo *getterName = RefExpr->getImplicitPropertyGetter()645                                             ->getSelector()646                                             .getIdentifierInfoForSlot(0);647      SetterSelector =648        SelectorTable::constructSetterSelector(S.PP.getIdentifierTable(),649                                               S.PP.getSelectorTable(),650                                               getterName);651      return false;652    }653  }654 655  // For explicit properties, this is more involved.656  ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();657  SetterSelector = prop->getSetterName();658 659  // Do a normal method lookup first.660  if (ObjCMethodDecl *setter =661        LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {662    if (setter->isPropertyAccessor() && warn)663      if (const ObjCInterfaceDecl *IFace =664          dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) {665        StringRef thisPropertyName = prop->getName();666        // Try flipping the case of the first character.667        char front = thisPropertyName.front();668        front = isLowercase(front) ? toUppercase(front) : toLowercase(front);669        SmallString<100> PropertyName = thisPropertyName;670        PropertyName[0] = front;671        const IdentifierInfo *AltMember =672            &S.PP.getIdentifierTable().get(PropertyName);673        if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(674                AltMember, prop->getQueryKind()))675          if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {676            S.Diag(RefExpr->getExprLoc(), diag::err_property_setter_ambiguous_use)677              << prop << prop1 << setter->getSelector();678            S.Diag(prop->getLocation(), diag::note_property_declare);679            S.Diag(prop1->getLocation(), diag::note_property_declare);680          }681      }682    Setter = setter;683    return true;684  }685 686  // That can fail in the somewhat crazy situation that we're687  // type-checking a message send within the @interface declaration688  // that declared the @property.  But it's not clear that that's689  // valuable to support.690 691  return false;692}693 694void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {695  if (S.getCurLexicalContext()->isObjCContainer() &&696      S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&697      S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {698    if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {699        S.Diag(RefExpr->getLocation(),700               diag::err_property_function_in_objc_container);701        S.Diag(prop->getLocation(), diag::note_property_declare);702    }703  }704}705 706/// Capture the base object of an Objective-C property expression.707Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {708  assert(InstanceReceiver == nullptr);709 710  // If we have a base, capture it in an OVE and rebuild the syntactic711  // form to use the OVE as its base.712  if (RefExpr->isObjectReceiver()) {713    InstanceReceiver = capture(RefExpr->getBase());714    syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {715                      return InstanceReceiver;716                    }).rebuild(syntacticBase);717  }718 719  if (ObjCPropertyRefExpr *720        refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))721    SyntacticRefExpr = refE;722 723  return syntacticBase;724}725 726/// Load from an Objective-C property reference.727ExprResult ObjCPropertyOpBuilder::buildGet() {728  findGetter();729  if (!Getter) {730    DiagnoseUnsupportedPropertyUse();731    return ExprError();732  }733 734  if (SyntacticRefExpr)735    SyntacticRefExpr->setIsMessagingGetter();736 737  QualType receiverType = RefExpr->getReceiverType(S.Context);738  if (!Getter->isImplicit())739    S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);740  // Build a message-send.741  ExprResult msg;742  if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||743      RefExpr->isObjectReceiver()) {744    assert(InstanceReceiver || RefExpr->isSuperReceiver());745    msg = S.ObjC().BuildInstanceMessageImplicit(746        InstanceReceiver, receiverType, GenericLoc, Getter->getSelector(),747        Getter, {});748  } else {749    msg = S.ObjC().BuildClassMessageImplicit(750        receiverType, RefExpr->isSuperReceiver(), GenericLoc,751        Getter->getSelector(), Getter, {});752  }753  return msg;754}755 756/// Store to an Objective-C property reference.757///758/// \param captureSetValueAsResult If true, capture the actual759///   value being set as the value of the property operation.760ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,761                                           bool captureSetValueAsResult) {762  if (!findSetter(false)) {763    DiagnoseUnsupportedPropertyUse();764    return ExprError();765  }766 767  if (SyntacticRefExpr)768    SyntacticRefExpr->setIsMessagingSetter();769 770  QualType receiverType = RefExpr->getReceiverType(S.Context);771 772  // Use assignment constraints when possible; they give us better773  // diagnostics.  "When possible" basically means anything except a774  // C++ class type.775  if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {776    QualType paramType = (*Setter->param_begin())->getType()777                           .substObjCMemberType(778                             receiverType,779                             Setter->getDeclContext(),780                             ObjCSubstitutionContext::Parameter);781    if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {782      ExprResult opResult = op;783      AssignConvertType assignResult =784          S.CheckSingleAssignmentConstraints(paramType, opResult);785      if (opResult.isInvalid() ||786          S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,787                                     op->getType(), opResult.get(),788                                     AssignmentAction::Assigning))789        return ExprError();790 791      op = opResult.get();792      assert(op && "successful assignment left argument invalid?");793    }794  }795 796  // Arguments.797  Expr *args[] = { op };798 799  // Build a message-send.800  ExprResult msg;801  if (!Setter->isImplicit())802    S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);803  if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||804      RefExpr->isObjectReceiver()) {805    msg = S.ObjC().BuildInstanceMessageImplicit(InstanceReceiver, receiverType,806                                                GenericLoc, SetterSelector,807                                                Setter, MultiExprArg(args, 1));808  } else {809    msg = S.ObjC().BuildClassMessageImplicit(810        receiverType, RefExpr->isSuperReceiver(), GenericLoc, SetterSelector,811        Setter, MultiExprArg(args, 1));812  }813 814  if (!msg.isInvalid() && captureSetValueAsResult) {815    ObjCMessageExpr *msgExpr =816      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());817    Expr *arg = msgExpr->getArg(0);818    if (CanCaptureValue(arg))819      msgExpr->setArg(0, captureValueAsResult(arg));820  }821 822  return msg;823}824 825/// @property-specific behavior for doing lvalue-to-rvalue conversion.826ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {827  // Explicit properties always have getters, but implicit ones don't.828  // Check that before proceeding.829  if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {830    S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)831        << RefExpr->getSourceRange();832    return ExprError();833  }834 835  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);836  if (result.isInvalid()) return ExprError();837 838  if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())839    S.ObjC().DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),840                                              Getter, RefExpr->getLocation());841 842  // As a special case, if the method returns 'id', try to get843  // a better type from the property.844  if (RefExpr->isExplicitProperty() && result.get()->isPRValue()) {845    QualType receiverType = RefExpr->getReceiverType(S.Context);846    QualType propType = RefExpr->getExplicitProperty()847                          ->getUsageType(receiverType);848    if (result.get()->getType()->isObjCIdType()) {849      if (const ObjCObjectPointerType *ptr850            = propType->getAs<ObjCObjectPointerType>()) {851        if (!ptr->isObjCIdType())852          result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);853      }854    }855    if (propType.getObjCLifetime() == Qualifiers::OCL_Weak &&856        !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,857                           RefExpr->getLocation()))858      S.getCurFunction()->markSafeWeakUse(RefExpr);859  }860 861  return result;862}863 864/// Try to build this as a call to a getter that returns a reference.865///866/// \return true if it was possible, whether or not it actually867///   succeeded868bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,869                                                   ExprResult &result) {870  if (!S.getLangOpts().CPlusPlus) return false;871 872  findGetter();873  if (!Getter) {874    // The property has no setter and no getter! This can happen if the type is875    // invalid. Error have already been reported.876    result = ExprError();877    return true;878  }879 880  // Only do this if the getter returns an l-value reference type.881  QualType resultType = Getter->getReturnType();882  if (!resultType->isLValueReferenceType()) return false;883 884  result = buildRValueOperation(op);885  return true;886}887 888/// @property-specific behavior for doing assignments.889ExprResult890ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,891                                                SourceLocation opcLoc,892                                                BinaryOperatorKind opcode,893                                                Expr *LHS, Expr *RHS) {894  assert(BinaryOperator::isAssignmentOp(opcode));895 896  // If there's no setter, we have no choice but to try to assign to897  // the result of the getter.898  if (!findSetter()) {899    ExprResult result;900    if (tryBuildGetOfReference(LHS, result)) {901      if (result.isInvalid()) return ExprError();902      return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS);903    }904 905    // Otherwise, it's an error.906    S.Diag(opcLoc, diag::err_nosetter_property_assignment)907      << unsigned(RefExpr->isImplicitProperty())908      << SetterSelector909      << LHS->getSourceRange() << RHS->getSourceRange();910    return ExprError();911  }912 913  // If there is a setter, we definitely want to use it.914 915  // Verify that we can do a compound assignment.916  if (opcode != BO_Assign && !findGetter()) {917    S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)918      << LHS->getSourceRange() << RHS->getSourceRange();919    return ExprError();920  }921 922  ExprResult result =923    PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);924  if (result.isInvalid()) return ExprError();925 926  // Various warnings about property assignments in ARC.927  if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {928    S.ObjC().checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);929    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);930  }931 932  return result;933}934 935/// @property-specific behavior for doing increments and decrements.936ExprResult937ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,938                                            UnaryOperatorKind opcode,939                                            Expr *op) {940  // If there's no setter, we have no choice but to try to assign to941  // the result of the getter.942  if (!findSetter()) {943    ExprResult result;944    if (tryBuildGetOfReference(op, result)) {945      if (result.isInvalid()) return ExprError();946      return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get());947    }948 949    // Otherwise, it's an error.950    S.Diag(opcLoc, diag::err_nosetter_property_incdec)951      << unsigned(RefExpr->isImplicitProperty())952      << unsigned(UnaryOperator::isDecrementOp(opcode))953      << SetterSelector954      << op->getSourceRange();955    return ExprError();956  }957 958  // If there is a setter, we definitely want to use it.959 960  // We also need a getter.961  if (!findGetter()) {962    assert(RefExpr->isImplicitProperty());963    S.Diag(opcLoc, diag::err_nogetter_property_incdec)964      << unsigned(UnaryOperator::isDecrementOp(opcode))965      << GetterSelector966      << op->getSourceRange();967    return ExprError();968  }969 970  return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);971}972 973ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {974  if (isWeakProperty() && !S.isUnevaluatedContext() &&975      !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,976                         SyntacticForm->getBeginLoc()))977    S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,978                                        SyntacticRefExpr->isMessagingGetter());979 980  return PseudoOpBuilder::complete(SyntacticForm);981}982 983// ObjCSubscript build stuff.984//985 986/// objective-c subscripting-specific behavior for doing lvalue-to-rvalue987/// conversion.988/// FIXME. Remove this routine if it is proven that no additional989/// specifity is needed.990ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {991  ExprResult result = PseudoOpBuilder::buildRValueOperation(op);992  if (result.isInvalid()) return ExprError();993  return result;994}995 996/// objective-c subscripting-specific  behavior for doing assignments.997ExprResult998ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,999                                                SourceLocation opcLoc,1000                                                BinaryOperatorKind opcode,1001                                                Expr *LHS, Expr *RHS) {1002  assert(BinaryOperator::isAssignmentOp(opcode));1003  // There must be a method to do the Index'ed assignment.1004  if (!findAtIndexSetter())1005    return ExprError();1006 1007  // Verify that we can do a compound assignment.1008  if (opcode != BO_Assign && !findAtIndexGetter())1009    return ExprError();1010 1011  ExprResult result =1012  PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);1013  if (result.isInvalid()) return ExprError();1014 1015  // Various warnings about objc Index'ed assignments in ARC.1016  if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {1017    S.ObjC().checkRetainCycles(InstanceBase->getSourceExpr(), RHS);1018    S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);1019  }1020 1021  return result;1022}1023 1024/// Capture the base object of an Objective-C Index'ed expression.1025Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {1026  assert(InstanceBase == nullptr);1027 1028  // Capture base expression in an OVE and rebuild the syntactic1029  // form to use the OVE as its base expression.1030  InstanceBase = capture(RefExpr->getBaseExpr());1031  InstanceKey = capture(RefExpr->getKeyExpr());1032 1033  syntacticBase =1034      Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {1035        switch (Idx) {1036        case 0:1037          return InstanceBase;1038        case 1:1039          return InstanceKey;1040        default:1041          llvm_unreachable("Unexpected index for ObjCSubscriptExpr");1042        }1043      }).rebuild(syntacticBase);1044 1045  return syntacticBase;1046}1047 1048/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF1049/// objects used as dictionary subscript key objects.1050static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,1051                                         Expr *Key) {1052  if (ContainerT.isNull())1053    return;1054  // dictionary subscripting.1055  // - (id)objectForKeyedSubscript:(id)key;1056  const IdentifierInfo *KeyIdents[] = {1057      &S.Context.Idents.get("objectForKeyedSubscript")};1058  Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);1059  ObjCMethodDecl *Getter = S.ObjC().LookupMethodInObjectType(1060      GetterSelector, ContainerT, true /*instance*/);1061  if (!Getter)1062    return;1063  QualType T = Getter->parameters()[0]->getType();1064  S.ObjC().CheckObjCConversion(Key->getSourceRange(), T, Key,1065                               CheckedConversionKind::Implicit);1066}1067 1068bool ObjCSubscriptOpBuilder::findAtIndexGetter() {1069  if (AtIndexGetter)1070    return true;1071 1072  Expr *BaseExpr = RefExpr->getBaseExpr();1073  QualType BaseT = BaseExpr->getType();1074 1075  QualType ResultType;1076  if (const ObjCObjectPointerType *PTy =1077      BaseT->getAs<ObjCObjectPointerType>()) {1078    ResultType = PTy->getPointeeType();1079  }1080  SemaObjC::ObjCSubscriptKind Res =1081      S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());1082  if (Res == SemaObjC::OS_Error) {1083    if (S.getLangOpts().ObjCAutoRefCount)1084      CheckKeyForObjCARCConversion(S, ResultType,1085                                   RefExpr->getKeyExpr());1086    return false;1087  }1088  bool arrayRef = (Res == SemaObjC::OS_Array);1089 1090  if (ResultType.isNull()) {1091    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)1092      << BaseExpr->getType() << arrayRef;1093    return false;1094  }1095  if (!arrayRef) {1096    // dictionary subscripting.1097    // - (id)objectForKeyedSubscript:(id)key;1098    const IdentifierInfo *KeyIdents[] = {1099        &S.Context.Idents.get("objectForKeyedSubscript")};1100    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);1101  }1102  else {1103    // - (id)objectAtIndexedSubscript:(size_t)index;1104    const IdentifierInfo *KeyIdents[] = {1105        &S.Context.Idents.get("objectAtIndexedSubscript")};1106 1107    AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);1108  }1109 1110  AtIndexGetter = S.ObjC().LookupMethodInObjectType(1111      AtIndexGetterSelector, ResultType, true /*instance*/);1112 1113  if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {1114    AtIndexGetter = ObjCMethodDecl::Create(1115        S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector,1116        S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,1117        S.Context.getTranslationUnitDecl(), true /*Instance*/,1118        false /*isVariadic*/,1119        /*isPropertyAccessor=*/false,1120        /*isSynthesizedAccessorStub=*/false,1121        /*isImplicitlyDeclared=*/true, /*isDefined=*/false,1122        ObjCImplementationControl::Required, false);1123    ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,1124                                                SourceLocation(), SourceLocation(),1125                                                arrayRef ? &S.Context.Idents.get("index")1126                                                         : &S.Context.Idents.get("key"),1127                                                arrayRef ? S.Context.UnsignedLongTy1128                                                         : S.Context.getObjCIdType(),1129                                                /*TInfo=*/nullptr,1130                                                SC_None,1131                                                nullptr);1132    AtIndexGetter->setMethodParams(S.Context, Argument, {});1133  }1134 1135  if (!AtIndexGetter) {1136    if (!BaseT->isObjCIdType()) {1137      S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)1138      << BaseExpr->getType() << 0 << arrayRef;1139      return false;1140    }1141    AtIndexGetter = S.ObjC().LookupInstanceMethodInGlobalPool(1142        AtIndexGetterSelector, RefExpr->getSourceRange(), true);1143  }1144 1145  if (AtIndexGetter) {1146    QualType T = AtIndexGetter->parameters()[0]->getType();1147    if ((arrayRef && !T->isIntegralOrEnumerationType()) ||1148        (!arrayRef && !T->isObjCObjectPointerType())) {1149      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1150             arrayRef ? diag::err_objc_subscript_index_type1151                      : diag::err_objc_subscript_key_type) << T;1152      S.Diag(AtIndexGetter->parameters()[0]->getLocation(),1153             diag::note_parameter_type) << T;1154      return false;1155    }1156    QualType R = AtIndexGetter->getReturnType();1157    if (!R->isObjCObjectPointerType()) {1158      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1159             diag::err_objc_indexing_method_result_type) << R << arrayRef;1160      S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<1161        AtIndexGetter->getDeclName();1162    }1163  }1164  return true;1165}1166 1167bool ObjCSubscriptOpBuilder::findAtIndexSetter() {1168  if (AtIndexSetter)1169    return true;1170 1171  Expr *BaseExpr = RefExpr->getBaseExpr();1172  QualType BaseT = BaseExpr->getType();1173 1174  QualType ResultType;1175  if (const ObjCObjectPointerType *PTy =1176      BaseT->getAs<ObjCObjectPointerType>()) {1177    ResultType = PTy->getPointeeType();1178  }1179 1180  SemaObjC::ObjCSubscriptKind Res =1181      S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());1182  if (Res == SemaObjC::OS_Error) {1183    if (S.getLangOpts().ObjCAutoRefCount)1184      CheckKeyForObjCARCConversion(S, ResultType,1185                                   RefExpr->getKeyExpr());1186    return false;1187  }1188  bool arrayRef = (Res == SemaObjC::OS_Array);1189 1190  if (ResultType.isNull()) {1191    S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)1192      << BaseExpr->getType() << arrayRef;1193    return false;1194  }1195 1196  if (!arrayRef) {1197    // dictionary subscripting.1198    // - (void)setObject:(id)object forKeyedSubscript:(id)key;1199    const IdentifierInfo *KeyIdents[] = {1200        &S.Context.Idents.get("setObject"),1201        &S.Context.Idents.get("forKeyedSubscript")};1202    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);1203  }1204  else {1205    // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;1206    const IdentifierInfo *KeyIdents[] = {1207        &S.Context.Idents.get("setObject"),1208        &S.Context.Idents.get("atIndexedSubscript")};1209    AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);1210  }1211  AtIndexSetter = S.ObjC().LookupMethodInObjectType(1212      AtIndexSetterSelector, ResultType, true /*instance*/);1213 1214  if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {1215    TypeSourceInfo *ReturnTInfo = nullptr;1216    QualType ReturnType = S.Context.VoidTy;1217    AtIndexSetter = ObjCMethodDecl::Create(1218        S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,1219        ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),1220        true /*Instance*/, false /*isVariadic*/,1221        /*isPropertyAccessor=*/false,1222        /*isSynthesizedAccessorStub=*/false,1223        /*isImplicitlyDeclared=*/true, /*isDefined=*/false,1224        ObjCImplementationControl::Required, false);1225    SmallVector<ParmVarDecl *, 2> Params;1226    ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,1227                                                SourceLocation(), SourceLocation(),1228                                                &S.Context.Idents.get("object"),1229                                                S.Context.getObjCIdType(),1230                                                /*TInfo=*/nullptr,1231                                                SC_None,1232                                                nullptr);1233    Params.push_back(object);1234    ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,1235                                                SourceLocation(), SourceLocation(),1236                                                arrayRef ?  &S.Context.Idents.get("index")1237                                                         :  &S.Context.Idents.get("key"),1238                                                arrayRef ? S.Context.UnsignedLongTy1239                                                         : S.Context.getObjCIdType(),1240                                                /*TInfo=*/nullptr,1241                                                SC_None,1242                                                nullptr);1243    Params.push_back(key);1244    AtIndexSetter->setMethodParams(S.Context, Params, {});1245  }1246 1247  if (!AtIndexSetter) {1248    if (!BaseT->isObjCIdType()) {1249      S.Diag(BaseExpr->getExprLoc(),1250             diag::err_objc_subscript_method_not_found)1251      << BaseExpr->getType() << 1 << arrayRef;1252      return false;1253    }1254    AtIndexSetter = S.ObjC().LookupInstanceMethodInGlobalPool(1255        AtIndexSetterSelector, RefExpr->getSourceRange(), true);1256  }1257 1258  bool err = false;1259  if (AtIndexSetter && arrayRef) {1260    QualType T = AtIndexSetter->parameters()[1]->getType();1261    if (!T->isIntegralOrEnumerationType()) {1262      S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1263             diag::err_objc_subscript_index_type) << T;1264      S.Diag(AtIndexSetter->parameters()[1]->getLocation(),1265             diag::note_parameter_type) << T;1266      err = true;1267    }1268    T = AtIndexSetter->parameters()[0]->getType();1269    if (!T->isObjCObjectPointerType()) {1270      S.Diag(RefExpr->getBaseExpr()->getExprLoc(),1271             diag::err_objc_subscript_object_type) << T << arrayRef;1272      S.Diag(AtIndexSetter->parameters()[0]->getLocation(),1273             diag::note_parameter_type) << T;1274      err = true;1275    }1276  }1277  else if (AtIndexSetter && !arrayRef)1278    for (unsigned i=0; i <2; i++) {1279      QualType T = AtIndexSetter->parameters()[i]->getType();1280      if (!T->isObjCObjectPointerType()) {1281        if (i == 1)1282          S.Diag(RefExpr->getKeyExpr()->getExprLoc(),1283                 diag::err_objc_subscript_key_type) << T;1284        else1285          S.Diag(RefExpr->getBaseExpr()->getExprLoc(),1286                 diag::err_objc_subscript_dic_object_type) << T;1287        S.Diag(AtIndexSetter->parameters()[i]->getLocation(),1288               diag::note_parameter_type) << T;1289        err = true;1290      }1291    }1292 1293  return !err;1294}1295 1296// Get the object at "Index" position in the container.1297// [BaseExpr objectAtIndexedSubscript : IndexExpr];1298ExprResult ObjCSubscriptOpBuilder::buildGet() {1299  if (!findAtIndexGetter())1300    return ExprError();1301 1302  QualType receiverType = InstanceBase->getType();1303 1304  // Build a message-send.1305  ExprResult msg;1306  Expr *Index = InstanceKey;1307 1308  // Arguments.1309  Expr *args[] = { Index };1310  assert(InstanceBase);1311  if (AtIndexGetter)1312    S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);1313  msg = S.ObjC().BuildInstanceMessageImplicit(1314      InstanceBase, receiverType, GenericLoc, AtIndexGetterSelector,1315      AtIndexGetter, MultiExprArg(args, 1));1316  return msg;1317}1318 1319/// Store into the container the "op" object at "Index"'ed location1320/// by building this messaging expression:1321/// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;1322/// \param captureSetValueAsResult If true, capture the actual1323///   value being set as the value of the property operation.1324ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,1325                                           bool captureSetValueAsResult) {1326  if (!findAtIndexSetter())1327    return ExprError();1328  if (AtIndexSetter)1329    S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);1330  QualType receiverType = InstanceBase->getType();1331  Expr *Index = InstanceKey;1332 1333  // Arguments.1334  Expr *args[] = { op, Index };1335 1336  // Build a message-send.1337  ExprResult msg = S.ObjC().BuildInstanceMessageImplicit(1338      InstanceBase, receiverType, GenericLoc, AtIndexSetterSelector,1339      AtIndexSetter, MultiExprArg(args, 2));1340 1341  if (!msg.isInvalid() && captureSetValueAsResult) {1342    ObjCMessageExpr *msgExpr =1343      cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());1344    Expr *arg = msgExpr->getArg(0);1345    if (CanCaptureValue(arg))1346      msgExpr->setArg(0, captureValueAsResult(arg));1347  }1348 1349  return msg;1350}1351 1352//===----------------------------------------------------------------------===//1353//  MSVC __declspec(property) references1354//===----------------------------------------------------------------------===//1355 1356MSPropertyRefExpr *1357MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {1358  CallArgs.insert(CallArgs.begin(), E->getIdx());1359  Expr *Base = E->getBase()->IgnoreParens();1360  while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {1361    CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());1362    Base = MSPropSubscript->getBase()->IgnoreParens();1363  }1364  return cast<MSPropertyRefExpr>(Base);1365}1366 1367Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {1368  InstanceBase = capture(RefExpr->getBaseExpr());1369  for (Expr *&Arg : CallArgs)1370    Arg = capture(Arg);1371  syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {1372                    switch (Idx) {1373                    case 0:1374                      return InstanceBase;1375                    default:1376                      assert(Idx <= CallArgs.size());1377                      return CallArgs[Idx - 1];1378                    }1379                  }).rebuild(syntacticBase);1380 1381  return syntacticBase;1382}1383 1384ExprResult MSPropertyOpBuilder::buildGet() {1385  if (!RefExpr->getPropertyDecl()->hasGetter()) {1386    S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)1387      << 0 /* getter */ << RefExpr->getPropertyDecl();1388    return ExprError();1389  }1390 1391  UnqualifiedId GetterName;1392  const IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();1393  GetterName.setIdentifier(II, RefExpr->getMemberLoc());1394  CXXScopeSpec SS;1395  SS.Adopt(RefExpr->getQualifierLoc());1396  ExprResult GetterExpr =1397      S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),1398                              RefExpr->isArrow() ? tok::arrow : tok::period, SS,1399                              SourceLocation(), GetterName, nullptr);1400  if (GetterExpr.isInvalid()) {1401    S.Diag(RefExpr->getMemberLoc(),1402           diag::err_cannot_find_suitable_accessor) << 0 /* getter */1403      << RefExpr->getPropertyDecl();1404    return ExprError();1405  }1406 1407  return S.BuildCallExpr(S.getCurScope(), GetterExpr.get(),1408                         RefExpr->getSourceRange().getBegin(), CallArgs,1409                         RefExpr->getSourceRange().getEnd());1410}1411 1412ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,1413                                         bool captureSetValueAsResult) {1414  if (!RefExpr->getPropertyDecl()->hasSetter()) {1415    S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)1416      << 1 /* setter */ << RefExpr->getPropertyDecl();1417    return ExprError();1418  }1419 1420  UnqualifiedId SetterName;1421  const IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();1422  SetterName.setIdentifier(II, RefExpr->getMemberLoc());1423  CXXScopeSpec SS;1424  SS.Adopt(RefExpr->getQualifierLoc());1425  ExprResult SetterExpr =1426      S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),1427                              RefExpr->isArrow() ? tok::arrow : tok::period, SS,1428                              SourceLocation(), SetterName, nullptr);1429  if (SetterExpr.isInvalid()) {1430    S.Diag(RefExpr->getMemberLoc(),1431           diag::err_cannot_find_suitable_accessor) << 1 /* setter */1432      << RefExpr->getPropertyDecl();1433    return ExprError();1434  }1435 1436  SmallVector<Expr*, 4> ArgExprs;1437  ArgExprs.append(CallArgs.begin(), CallArgs.end());1438  ArgExprs.push_back(op);1439  return S.BuildCallExpr(S.getCurScope(), SetterExpr.get(),1440                         RefExpr->getSourceRange().getBegin(), ArgExprs,1441                         op->getSourceRange().getEnd());1442}1443 1444//===----------------------------------------------------------------------===//1445//  General Sema routines.1446//===----------------------------------------------------------------------===//1447 1448ExprResult SemaPseudoObject::checkRValue(Expr *E) {1449  Expr *opaqueRef = E->IgnoreParens();1450  if (ObjCPropertyRefExpr *refExpr1451        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {1452    ObjCPropertyOpBuilder builder(SemaRef, refExpr, true);1453    return builder.buildRValueOperation(E);1454  }1455  else if (ObjCSubscriptRefExpr *refExpr1456           = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {1457    ObjCSubscriptOpBuilder builder(SemaRef, refExpr, true);1458    return builder.buildRValueOperation(E);1459  } else if (MSPropertyRefExpr *refExpr1460             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {1461    MSPropertyOpBuilder builder(SemaRef, refExpr, true);1462    return builder.buildRValueOperation(E);1463  } else if (MSPropertySubscriptExpr *RefExpr =1464                 dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {1465    MSPropertyOpBuilder Builder(SemaRef, RefExpr, true);1466    return Builder.buildRValueOperation(E);1467  } else {1468    llvm_unreachable("unknown pseudo-object kind!");1469  }1470}1471 1472/// Check an increment or decrement of a pseudo-object expression.1473ExprResult SemaPseudoObject::checkIncDec(Scope *Sc, SourceLocation opcLoc,1474                                         UnaryOperatorKind opcode, Expr *op) {1475  // Do nothing if the operand is dependent.1476  if (op->isTypeDependent())1477    return UnaryOperator::Create(1478        SemaRef.Context, op, opcode, SemaRef.Context.DependentTy, VK_PRValue,1479        OK_Ordinary, opcLoc, false, SemaRef.CurFPFeatureOverrides());1480 1481  assert(UnaryOperator::isIncrementDecrementOp(opcode));1482  Expr *opaqueRef = op->IgnoreParens();1483  if (ObjCPropertyRefExpr *refExpr1484        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {1485    ObjCPropertyOpBuilder builder(SemaRef, refExpr, false);1486    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);1487  } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {1488    Diag(opcLoc, diag::err_illegal_container_subscripting_op);1489    return ExprError();1490  } else if (MSPropertyRefExpr *refExpr1491             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {1492    MSPropertyOpBuilder builder(SemaRef, refExpr, false);1493    return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);1494  } else if (MSPropertySubscriptExpr *RefExpr1495             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {1496    MSPropertyOpBuilder Builder(SemaRef, RefExpr, false);1497    return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);1498  } else {1499    llvm_unreachable("unknown pseudo-object kind!");1500  }1501}1502 1503ExprResult SemaPseudoObject::checkAssignment(Scope *S, SourceLocation opcLoc,1504                                             BinaryOperatorKind opcode,1505                                             Expr *LHS, Expr *RHS) {1506  // Do nothing if either argument is dependent.1507  if (LHS->isTypeDependent() || RHS->isTypeDependent())1508    return BinaryOperator::Create(1509        SemaRef.Context, LHS, RHS, opcode, SemaRef.Context.DependentTy,1510        VK_PRValue, OK_Ordinary, opcLoc, SemaRef.CurFPFeatureOverrides());1511 1512  // Filter out non-overload placeholder types in the RHS.1513  if (RHS->getType()->isNonOverloadPlaceholderType()) {1514    ExprResult result = SemaRef.CheckPlaceholderExpr(RHS);1515    if (result.isInvalid()) return ExprError();1516    RHS = result.get();1517  }1518 1519  bool IsSimpleAssign = opcode == BO_Assign;1520  Expr *opaqueRef = LHS->IgnoreParens();1521  if (ObjCPropertyRefExpr *refExpr1522        = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {1523    ObjCPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);1524    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1525  } else if (ObjCSubscriptRefExpr *refExpr1526             = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {1527    ObjCSubscriptOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);1528    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1529  } else if (MSPropertyRefExpr *refExpr1530             = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {1531    MSPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);1532    return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1533  } else if (MSPropertySubscriptExpr *RefExpr1534             = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {1535    MSPropertyOpBuilder Builder(SemaRef, RefExpr, IsSimpleAssign);1536    return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);1537  } else {1538    llvm_unreachable("unknown pseudo-object kind!");1539  }1540}1541 1542/// Given a pseudo-object reference, rebuild it without the opaque1543/// values.  Basically, undo the behavior of rebuildAndCaptureObject.1544/// This should never operate in-place.1545static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {1546  return Rebuilder(S,1547                   [=](Expr *E, unsigned) -> Expr * {1548                     return cast<OpaqueValueExpr>(E)->getSourceExpr();1549                   })1550      .rebuild(E);1551}1552 1553/// Given a pseudo-object expression, recreate what it looks like1554/// syntactically without the attendant OpaqueValueExprs.1555///1556/// This is a hack which should be removed when TreeTransform is1557/// capable of rebuilding a tree without stripping implicit1558/// operations.1559Expr *SemaPseudoObject::recreateSyntacticForm(PseudoObjectExpr *E) {1560  Expr *syntax = E->getSyntacticForm();1561  if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {1562    Expr *op = stripOpaqueValuesFromPseudoObjectRef(SemaRef, uop->getSubExpr());1563    return UnaryOperator::Create(1564        SemaRef.Context, op, uop->getOpcode(), uop->getType(),1565        uop->getValueKind(), uop->getObjectKind(), uop->getOperatorLoc(),1566        uop->canOverflow(), SemaRef.CurFPFeatureOverrides());1567  } else if (CompoundAssignOperator *cop1568               = dyn_cast<CompoundAssignOperator>(syntax)) {1569    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, cop->getLHS());1570    Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();1571    return CompoundAssignOperator::Create(1572        SemaRef.Context, lhs, rhs, cop->getOpcode(), cop->getType(),1573        cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),1574        SemaRef.CurFPFeatureOverrides(), cop->getComputationLHSType(),1575        cop->getComputationResultType());1576 1577  } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {1578    Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, bop->getLHS());1579    Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();1580    return BinaryOperator::Create(SemaRef.Context, lhs, rhs, bop->getOpcode(),1581                                  bop->getType(), bop->getValueKind(),1582                                  bop->getObjectKind(), bop->getOperatorLoc(),1583                                  SemaRef.CurFPFeatureOverrides());1584 1585  } else if (isa<CallExpr>(syntax)) {1586    return syntax;1587  } else {1588    assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));1589    return stripOpaqueValuesFromPseudoObjectRef(SemaRef, syntax);1590  }1591}1592 1593SemaPseudoObject::SemaPseudoObject(Sema &S) : SemaBase(S) {}1594