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