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 true;
    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(
    662                 AltMember, prop->getQueryKind()))
    663           if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
    664             S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use)
    665               << prop << prop1 << setter->getSelector();
    666             S.Diag(prop->getLocation(), diag::note_property_declare);
    667             S.Diag(prop1->getLocation(), diag::note_property_declare);
    668           }
    669       }
    670     Setter = setter;
    671     return true;
    672   }
    673 
    674   // That can fail in the somewhat crazy situation that we're
    675   // type-checking a message send within the @interface declaration
    676   // that declared the @property.  But it's not clear that that's
    677   // valuable to support.
    678 
    679   return false;
    680 }
    681 
    682 void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
    683   if (S.getCurLexicalContext()->isObjCContainer() &&
    684       S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&
    685       S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {
    686     if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {
    687         S.Diag(RefExpr->getLocation(),
    688                diag::err_property_function_in_objc_container);
    689         S.Diag(prop->getLocation(), diag::note_property_declare);
    690     }
    691   }
    692 }
    693 
    694 /// Capture the base object of an Objective-C property expression.
    695 Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
    696   assert(InstanceReceiver == nullptr);
    697 
    698   // If we have a base, capture it in an OVE and rebuild the syntactic
    699   // form to use the OVE as its base.
    700   if (RefExpr->isObjectReceiver()) {
    701     InstanceReceiver = capture(RefExpr->getBase());
    702     syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
    703                       return InstanceReceiver;
    704                     }).rebuild(syntacticBase);
    705   }
    706 
    707   if (ObjCPropertyRefExpr *
    708         refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
    709     SyntacticRefExpr = refE;
    710 
    711   return syntacticBase;
    712 }
    713 
    714 /// Load from an Objective-C property reference.
    715 ExprResult ObjCPropertyOpBuilder::buildGet() {
    716   findGetter();
    717   if (!Getter) {
    718     DiagnoseUnsupportedPropertyUse();
    719     return ExprError();
    720   }
    721 
    722   if (SyntacticRefExpr)
    723     SyntacticRefExpr->setIsMessagingGetter();
    724 
    725   QualType receiverType = RefExpr->getReceiverType(S.Context);
    726   if (!Getter->isImplicit())
    727     S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
    728   // Build a message-send.
    729   ExprResult msg;
    730   if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
    731       RefExpr->isObjectReceiver()) {
    732     assert(InstanceReceiver || RefExpr->isSuperReceiver());
    733     msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
    734                                          GenericLoc, Getter->getSelector(),
    735                                          Getter, None);
    736   } else {
    737     msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
    738                                       GenericLoc, Getter->getSelector(),
    739                                       Getter, None);
    740   }
    741   return msg;
    742 }
    743 
    744 /// Store to an Objective-C property reference.
    745 ///
    746 /// \param captureSetValueAsResult If true, capture the actual
    747 ///   value being set as the value of the property operation.
    748 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
    749                                            bool captureSetValueAsResult) {
    750   if (!findSetter(false)) {
    751     DiagnoseUnsupportedPropertyUse();
    752     return ExprError();
    753   }
    754 
    755   if (SyntacticRefExpr)
    756     SyntacticRefExpr->setIsMessagingSetter();
    757 
    758   QualType receiverType = RefExpr->getReceiverType(S.Context);
    759 
    760   // Use assignment constraints when possible; they give us better
    761   // diagnostics.  "When possible" basically means anything except a
    762   // C++ class type.
    763   if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
    764     QualType paramType = (*Setter->param_begin())->getType()
    765                            .substObjCMemberType(
    766                              receiverType,
    767                              Setter->getDeclContext(),
    768                              ObjCSubstitutionContext::Parameter);
    769     if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
    770       ExprResult opResult = op;
    771       Sema::AssignConvertType assignResult
    772         = S.CheckSingleAssignmentConstraints(paramType, opResult);
    773       if (S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
    774                                      op->getType(), opResult.get(),
    775                                      Sema::AA_Assigning))
    776         return ExprError();
    777 
    778       op = opResult.get();
    779       assert(op && "successful assignment left argument invalid?");
    780     }
    781   }
    782 
    783   // Arguments.
    784   Expr *args[] = { op };
    785 
    786   // Build a message-send.
    787   ExprResult msg;
    788   if (!Setter->isImplicit())
    789     S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);
    790   if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
    791       RefExpr->isObjectReceiver()) {
    792     msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
    793                                          GenericLoc, SetterSelector, Setter,
    794                                          MultiExprArg(args, 1));
    795   } else {
    796     msg = S.BuildClassMessageImplicit(receiverType, RefExpr->isSuperReceiver(),
    797                                       GenericLoc,
    798                                       SetterSelector, Setter,
    799                                       MultiExprArg(args, 1));
    800   }
    801 
    802   if (!msg.isInvalid() && captureSetValueAsResult) {
    803     ObjCMessageExpr *msgExpr =
    804       cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
    805     Expr *arg = msgExpr->getArg(0);
    806     if (CanCaptureValue(arg))
    807       msgExpr->setArg(0, captureValueAsResult(arg));
    808   }
    809 
    810   return msg;
    811 }
    812 
    813 /// @property-specific behavior for doing lvalue-to-rvalue conversion.
    814 ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) {
    815   // Explicit properties always have getters, but implicit ones don't.
    816   // Check that before proceeding.
    817   if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) {
    818     S.Diag(RefExpr->getLocation(), diag::err_getter_not_found)
    819         << RefExpr->getSourceRange();
    820     return ExprError();
    821   }
    822 
    823   ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
    824   if (result.isInvalid()) return ExprError();
    825 
    826   if (RefExpr->isExplicitProperty() && !Getter->hasRelatedResultType())
    827     S.DiagnosePropertyAccessorMismatch(RefExpr->getExplicitProperty(),
    828                                        Getter, RefExpr->getLocation());
    829 
    830   // As a special case, if the method returns 'id', try to get
    831   // a better type from the property.
    832   if (RefExpr->isExplicitProperty() && result.get()->isRValue()) {
    833     QualType receiverType = RefExpr->getReceiverType(S.Context);
    834     QualType propType = RefExpr->getExplicitProperty()
    835                           ->getUsageType(receiverType);
    836     if (result.get()->getType()->isObjCIdType()) {
    837       if (const ObjCObjectPointerType *ptr
    838             = propType->getAs<ObjCObjectPointerType>()) {
    839         if (!ptr->isObjCIdType())
    840           result = S.ImpCastExprToType(result.get(), propType, CK_BitCast);
    841       }
    842     }
    843     if (S.getLangOpts().ObjCAutoRefCount) {
    844       Qualifiers::ObjCLifetime LT = propType.getObjCLifetime();
    845       if (LT == Qualifiers::OCL_Weak)
    846         if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation()))
    847               S.getCurFunction()->markSafeWeakUse(RefExpr);
    848     }
    849   }
    850 
    851   return result;
    852 }
    853 
    854 /// Try to build this as a call to a getter that returns a reference.
    855 ///
    856 /// \return true if it was possible, whether or not it actually
    857 ///   succeeded
    858 bool ObjCPropertyOpBuilder::tryBuildGetOfReference(Expr *op,
    859                                                    ExprResult &result) {
    860   if (!S.getLangOpts().CPlusPlus) return false;
    861 
    862   findGetter();
    863   if (!Getter) {
    864     // The property has no setter and no getter! This can happen if the type is
    865     // invalid. Error have already been reported.
    866     result = ExprError();
    867     return true;
    868   }
    869 
    870   // Only do this if the getter returns an l-value reference type.
    871   QualType resultType = Getter->getReturnType();
    872   if (!resultType->isLValueReferenceType()) return false;
    873 
    874   result = buildRValueOperation(op);
    875   return true;
    876 }
    877 
    878 /// @property-specific behavior for doing assignments.
    879 ExprResult
    880 ObjCPropertyOpBuilder::buildAssignmentOperation(Scope *Sc,
    881                                                 SourceLocation opcLoc,
    882                                                 BinaryOperatorKind opcode,
    883                                                 Expr *LHS, Expr *RHS) {
    884   assert(BinaryOperator::isAssignmentOp(opcode));
    885 
    886   // If there's no setter, we have no choice but to try to assign to
    887   // the result of the getter.
    888   if (!findSetter()) {
    889     ExprResult result;
    890     if (tryBuildGetOfReference(LHS, result)) {
    891       if (result.isInvalid()) return ExprError();
    892       return S.BuildBinOp(Sc, opcLoc, opcode, result.get(), RHS);
    893     }
    894 
    895     // Otherwise, it's an error.
    896     S.Diag(opcLoc, diag::err_nosetter_property_assignment)
    897       << unsigned(RefExpr->isImplicitProperty())
    898       << SetterSelector
    899       << LHS->getSourceRange() << RHS->getSourceRange();
    900     return ExprError();
    901   }
    902 
    903   // If there is a setter, we definitely want to use it.
    904 
    905   // Verify that we can do a compound assignment.
    906   if (opcode != BO_Assign && !findGetter()) {
    907     S.Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
    908       << LHS->getSourceRange() << RHS->getSourceRange();
    909     return ExprError();
    910   }
    911 
    912   ExprResult result =
    913     PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
    914   if (result.isInvalid()) return ExprError();
    915 
    916   // Various warnings about property assignments in ARC.
    917   if (S.getLangOpts().ObjCAutoRefCount && InstanceReceiver) {
    918     S.checkRetainCycles(InstanceReceiver->getSourceExpr(), RHS);
    919     S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
    920   }
    921 
    922   return result;
    923 }
    924 
    925 /// @property-specific behavior for doing increments and decrements.
    926 ExprResult
    927 ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
    928                                             UnaryOperatorKind opcode,
    929                                             Expr *op) {
    930   // If there's no setter, we have no choice but to try to assign to
    931   // the result of the getter.
    932   if (!findSetter()) {
    933     ExprResult result;
    934     if (tryBuildGetOfReference(op, result)) {
    935       if (result.isInvalid()) return ExprError();
    936       return S.BuildUnaryOp(Sc, opcLoc, opcode, result.get());
    937     }
    938 
    939     // Otherwise, it's an error.
    940     S.Diag(opcLoc, diag::err_nosetter_property_incdec)
    941       << unsigned(RefExpr->isImplicitProperty())
    942       << unsigned(UnaryOperator::isDecrementOp(opcode))
    943       << SetterSelector
    944       << op->getSourceRange();
    945     return ExprError();
    946   }
    947 
    948   // If there is a setter, we definitely want to use it.
    949 
    950   // We also need a getter.
    951   if (!findGetter()) {
    952     assert(RefExpr->isImplicitProperty());
    953     S.Diag(opcLoc, diag::err_nogetter_property_incdec)
    954       << unsigned(UnaryOperator::isDecrementOp(opcode))
    955       << GetterSelector
    956       << op->getSourceRange();
    957     return ExprError();
    958   }
    959 
    960   return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op);
    961 }
    962 
    963 ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) {
    964   if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty() &&
    965       !S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
    966                          SyntacticForm->getLocStart()))
    967       S.recordUseOfEvaluatedWeak(SyntacticRefExpr,
    968                                  SyntacticRefExpr->isMessagingGetter());
    969 
    970   return PseudoOpBuilder::complete(SyntacticForm);
    971 }
    972 
    973 // ObjCSubscript build stuff.
    974 //
    975 
    976 /// objective-c subscripting-specific behavior for doing lvalue-to-rvalue
    977 /// conversion.
    978 /// FIXME. Remove this routine if it is proven that no additional
    979 /// specifity is needed.
    980 ExprResult ObjCSubscriptOpBuilder::buildRValueOperation(Expr *op) {
    981   ExprResult result = PseudoOpBuilder::buildRValueOperation(op);
    982   if (result.isInvalid()) return ExprError();
    983   return result;
    984 }
    985 
    986 /// objective-c subscripting-specific  behavior for doing assignments.
    987 ExprResult
    988 ObjCSubscriptOpBuilder::buildAssignmentOperation(Scope *Sc,
    989                                                 SourceLocation opcLoc,
    990                                                 BinaryOperatorKind opcode,
    991                                                 Expr *LHS, Expr *RHS) {
    992   assert(BinaryOperator::isAssignmentOp(opcode));
    993   // There must be a method to do the Index'ed assignment.
    994   if (!findAtIndexSetter())
    995     return ExprError();
    996 
    997   // Verify that we can do a compound assignment.
    998   if (opcode != BO_Assign && !findAtIndexGetter())
    999     return ExprError();
   1000 
   1001   ExprResult result =
   1002   PseudoOpBuilder::buildAssignmentOperation(Sc, opcLoc, opcode, LHS, RHS);
   1003   if (result.isInvalid()) return ExprError();
   1004 
   1005   // Various warnings about objc Index'ed assignments in ARC.
   1006   if (S.getLangOpts().ObjCAutoRefCount && InstanceBase) {
   1007     S.checkRetainCycles(InstanceBase->getSourceExpr(), RHS);
   1008     S.checkUnsafeExprAssigns(opcLoc, LHS, RHS);
   1009   }
   1010 
   1011   return result;
   1012 }
   1013 
   1014 /// Capture the base object of an Objective-C Index'ed expression.
   1015 Expr *ObjCSubscriptOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
   1016   assert(InstanceBase == nullptr);
   1017 
   1018   // Capture base expression in an OVE and rebuild the syntactic
   1019   // form to use the OVE as its base expression.
   1020   InstanceBase = capture(RefExpr->getBaseExpr());
   1021   InstanceKey = capture(RefExpr->getKeyExpr());
   1022 
   1023   syntacticBase =
   1024       Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
   1025         switch (Idx) {
   1026         case 0:
   1027           return InstanceBase;
   1028         case 1:
   1029           return InstanceKey;
   1030         default:
   1031           llvm_unreachable("Unexpected index for ObjCSubscriptExpr");
   1032         }
   1033       }).rebuild(syntacticBase);
   1034 
   1035   return syntacticBase;
   1036 }
   1037 
   1038 /// CheckSubscriptingKind - This routine decide what type
   1039 /// of indexing represented by "FromE" is being done.
   1040 Sema::ObjCSubscriptKind
   1041   Sema::CheckSubscriptingKind(Expr *FromE) {
   1042   // If the expression already has integral or enumeration type, we're golden.
   1043   QualType T = FromE->getType();
   1044   if (T->isIntegralOrEnumerationType())
   1045     return OS_Array;
   1046 
   1047   // If we don't have a class type in C++, there's no way we can get an
   1048   // expression of integral or enumeration type.
   1049   const RecordType *RecordTy = T->getAs<RecordType>();
   1050   if (!RecordTy &&
   1051       (T->isObjCObjectPointerType() || T->isVoidPointerType()))
   1052     // All other scalar cases are assumed to be dictionary indexing which
   1053     // caller handles, with diagnostics if needed.
   1054     return OS_Dictionary;
   1055   if (!getLangOpts().CPlusPlus ||
   1056       !RecordTy || RecordTy->isIncompleteType()) {
   1057     // No indexing can be done. Issue diagnostics and quit.
   1058     const Expr *IndexExpr = FromE->IgnoreParenImpCasts();
   1059     if (isa<StringLiteral>(IndexExpr))
   1060       Diag(FromE->getExprLoc(), diag::err_objc_subscript_pointer)
   1061         << T << FixItHint::CreateInsertion(FromE->getExprLoc(), "@");
   1062     else
   1063       Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
   1064         << T;
   1065     return OS_Error;
   1066   }
   1067 
   1068   // We must have a complete class type.
   1069   if (RequireCompleteType(FromE->getExprLoc(), T,
   1070                           diag::err_objc_index_incomplete_class_type, FromE))
   1071     return OS_Error;
   1072 
   1073   // Look for a conversion to an integral, enumeration type, or
   1074   // objective-C pointer type.
   1075   int NoIntegrals=0, NoObjCIdPointers=0;
   1076   SmallVector<CXXConversionDecl *, 4> ConversionDecls;
   1077 
   1078   for (NamedDecl *D : cast<CXXRecordDecl>(RecordTy->getDecl())
   1079                           ->getVisibleConversionFunctions()) {
   1080     if (CXXConversionDecl *Conversion =
   1081             dyn_cast<CXXConversionDecl>(D->getUnderlyingDecl())) {
   1082       QualType CT = Conversion->getConversionType().getNonReferenceType();
   1083       if (CT->isIntegralOrEnumerationType()) {
   1084         ++NoIntegrals;
   1085         ConversionDecls.push_back(Conversion);
   1086       }
   1087       else if (CT->isObjCIdType() ||CT->isBlockPointerType()) {
   1088         ++NoObjCIdPointers;
   1089         ConversionDecls.push_back(Conversion);
   1090       }
   1091     }
   1092   }
   1093   if (NoIntegrals ==1 && NoObjCIdPointers == 0)
   1094     return OS_Array;
   1095   if (NoIntegrals == 0 && NoObjCIdPointers == 1)
   1096     return OS_Dictionary;
   1097   if (NoIntegrals == 0 && NoObjCIdPointers == 0) {
   1098     // No conversion function was found. Issue diagnostic and return.
   1099     Diag(FromE->getExprLoc(), diag::err_objc_subscript_type_conversion)
   1100       << FromE->getType();
   1101     return OS_Error;
   1102   }
   1103   Diag(FromE->getExprLoc(), diag::err_objc_multiple_subscript_type_conversion)
   1104       << FromE->getType();
   1105   for (unsigned int i = 0; i < ConversionDecls.size(); i++)
   1106     Diag(ConversionDecls[i]->getLocation(), diag::not_conv_function_declared_at);
   1107 
   1108   return OS_Error;
   1109 }
   1110 
   1111 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
   1112 /// objects used as dictionary subscript key objects.
   1113 static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
   1114                                          Expr *Key) {
   1115   if (ContainerT.isNull())
   1116     return;
   1117   // dictionary subscripting.
   1118   // - (id)objectForKeyedSubscript:(id)key;
   1119   IdentifierInfo *KeyIdents[] = {
   1120     &S.Context.Idents.get("objectForKeyedSubscript")
   1121   };
   1122   Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
   1123   ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT,
   1124                                                       true /*instance*/);
   1125   if (!Getter)
   1126     return;
   1127   QualType T = Getter->parameters()[0]->getType();
   1128   S.CheckObjCARCConversion(Key->getSourceRange(),
   1129                          T, Key, Sema::CCK_ImplicitConversion);
   1130 }
   1131 
   1132 bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
   1133   if (AtIndexGetter)
   1134     return true;
   1135 
   1136   Expr *BaseExpr = RefExpr->getBaseExpr();
   1137   QualType BaseT = BaseExpr->getType();
   1138 
   1139   QualType ResultType;
   1140   if (const ObjCObjectPointerType *PTy =
   1141       BaseT->getAs<ObjCObjectPointerType>()) {
   1142     ResultType = PTy->getPointeeType();
   1143   }
   1144   Sema::ObjCSubscriptKind Res =
   1145     S.CheckSubscriptingKind(RefExpr->getKeyExpr());
   1146   if (Res == Sema::OS_Error) {
   1147     if (S.getLangOpts().ObjCAutoRefCount)
   1148       CheckKeyForObjCARCConversion(S, ResultType,
   1149                                    RefExpr->getKeyExpr());
   1150     return false;
   1151   }
   1152   bool arrayRef = (Res == Sema::OS_Array);
   1153 
   1154   if (ResultType.isNull()) {
   1155     S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
   1156       << BaseExpr->getType() << arrayRef;
   1157     return false;
   1158   }
   1159   if (!arrayRef) {
   1160     // dictionary subscripting.
   1161     // - (id)objectForKeyedSubscript:(id)key;
   1162     IdentifierInfo *KeyIdents[] = {
   1163       &S.Context.Idents.get("objectForKeyedSubscript")
   1164     };
   1165     AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
   1166   }
   1167   else {
   1168     // - (id)objectAtIndexedSubscript:(size_t)index;
   1169     IdentifierInfo *KeyIdents[] = {
   1170       &S.Context.Idents.get("objectAtIndexedSubscript")
   1171     };
   1172 
   1173     AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
   1174   }
   1175 
   1176   AtIndexGetter = S.LookupMethodInObjectType(AtIndexGetterSelector, ResultType,
   1177                                              true /*instance*/);
   1178   bool receiverIdType = (BaseT->isObjCIdType() ||
   1179                          BaseT->isObjCQualifiedIdType());
   1180 
   1181   if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
   1182     AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(),
   1183                            SourceLocation(), AtIndexGetterSelector,
   1184                            S.Context.getObjCIdType() /*ReturnType*/,
   1185                            nullptr /*TypeSourceInfo */,
   1186                            S.Context.getTranslationUnitDecl(),
   1187                            true /*Instance*/, false/*isVariadic*/,
   1188                            /*isPropertyAccessor=*/false,
   1189                            /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
   1190                            ObjCMethodDecl::Required,
   1191                            false);
   1192     ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
   1193                                                 SourceLocation(), SourceLocation(),
   1194                                                 arrayRef ? &S.Context.Idents.get("index")
   1195                                                          : &S.Context.Idents.get("key"),
   1196                                                 arrayRef ? S.Context.UnsignedLongTy
   1197                                                          : S.Context.getObjCIdType(),
   1198                                                 /*TInfo=*/nullptr,
   1199                                                 SC_None,
   1200                                                 nullptr);
   1201     AtIndexGetter->setMethodParams(S.Context, Argument, None);
   1202   }
   1203 
   1204   if (!AtIndexGetter) {
   1205     if (!receiverIdType) {
   1206       S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
   1207       << BaseExpr->getType() << 0 << arrayRef;
   1208       return false;
   1209     }
   1210     AtIndexGetter =
   1211       S.LookupInstanceMethodInGlobalPool(AtIndexGetterSelector,
   1212                                          RefExpr->getSourceRange(),
   1213                                          true);
   1214   }
   1215 
   1216   if (AtIndexGetter) {
   1217     QualType T = AtIndexGetter->parameters()[0]->getType();
   1218     if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
   1219         (!arrayRef && !T->isObjCObjectPointerType())) {
   1220       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
   1221              arrayRef ? diag::err_objc_subscript_index_type
   1222                       : diag::err_objc_subscript_key_type) << T;
   1223       S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
   1224              diag::note_parameter_type) << T;
   1225       return false;
   1226     }
   1227     QualType R = AtIndexGetter->getReturnType();
   1228     if (!R->isObjCObjectPointerType()) {
   1229       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
   1230              diag::err_objc_indexing_method_result_type) << R << arrayRef;
   1231       S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
   1232         AtIndexGetter->getDeclName();
   1233     }
   1234   }
   1235   return true;
   1236 }
   1237 
   1238 bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
   1239   if (AtIndexSetter)
   1240     return true;
   1241 
   1242   Expr *BaseExpr = RefExpr->getBaseExpr();
   1243   QualType BaseT = BaseExpr->getType();
   1244 
   1245   QualType ResultType;
   1246   if (const ObjCObjectPointerType *PTy =
   1247       BaseT->getAs<ObjCObjectPointerType>()) {
   1248     ResultType = PTy->getPointeeType();
   1249   }
   1250 
   1251   Sema::ObjCSubscriptKind Res =
   1252     S.CheckSubscriptingKind(RefExpr->getKeyExpr());
   1253   if (Res == Sema::OS_Error) {
   1254     if (S.getLangOpts().ObjCAutoRefCount)
   1255       CheckKeyForObjCARCConversion(S, ResultType,
   1256                                    RefExpr->getKeyExpr());
   1257     return false;
   1258   }
   1259   bool arrayRef = (Res == Sema::OS_Array);
   1260 
   1261   if (ResultType.isNull()) {
   1262     S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
   1263       << BaseExpr->getType() << arrayRef;
   1264     return false;
   1265   }
   1266 
   1267   if (!arrayRef) {
   1268     // dictionary subscripting.
   1269     // - (void)setObject:(id)object forKeyedSubscript:(id)key;
   1270     IdentifierInfo *KeyIdents[] = {
   1271       &S.Context.Idents.get("setObject"),
   1272       &S.Context.Idents.get("forKeyedSubscript")
   1273     };
   1274     AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
   1275   }
   1276   else {
   1277     // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
   1278     IdentifierInfo *KeyIdents[] = {
   1279       &S.Context.Idents.get("setObject"),
   1280       &S.Context.Idents.get("atIndexedSubscript")
   1281     };
   1282     AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
   1283   }
   1284   AtIndexSetter = S.LookupMethodInObjectType(AtIndexSetterSelector, ResultType,
   1285                                              true /*instance*/);
   1286 
   1287   bool receiverIdType = (BaseT->isObjCIdType() ||
   1288                          BaseT->isObjCQualifiedIdType());
   1289 
   1290   if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
   1291     TypeSourceInfo *ReturnTInfo = nullptr;
   1292     QualType ReturnType = S.Context.VoidTy;
   1293     AtIndexSetter = ObjCMethodDecl::Create(
   1294         S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
   1295         ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
   1296         true /*Instance*/, false /*isVariadic*/,
   1297         /*isPropertyAccessor=*/false,
   1298         /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
   1299         ObjCMethodDecl::Required, false);
   1300     SmallVector<ParmVarDecl *, 2> Params;
   1301     ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
   1302                                                 SourceLocation(), SourceLocation(),
   1303                                                 &S.Context.Idents.get("object"),
   1304                                                 S.Context.getObjCIdType(),
   1305                                                 /*TInfo=*/nullptr,
   1306                                                 SC_None,
   1307                                                 nullptr);
   1308     Params.push_back(object);
   1309     ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
   1310                                                 SourceLocation(), SourceLocation(),
   1311                                                 arrayRef ?  &S.Context.Idents.get("index")
   1312                                                          :  &S.Context.Idents.get("key"),
   1313                                                 arrayRef ? S.Context.UnsignedLongTy
   1314                                                          : S.Context.getObjCIdType(),
   1315                                                 /*TInfo=*/nullptr,
   1316                                                 SC_None,
   1317                                                 nullptr);
   1318     Params.push_back(key);
   1319     AtIndexSetter->setMethodParams(S.Context, Params, None);
   1320   }
   1321 
   1322   if (!AtIndexSetter) {
   1323     if (!receiverIdType) {
   1324       S.Diag(BaseExpr->getExprLoc(),
   1325              diag::err_objc_subscript_method_not_found)
   1326       << BaseExpr->getType() << 1 << arrayRef;
   1327       return false;
   1328     }
   1329     AtIndexSetter =
   1330       S.LookupInstanceMethodInGlobalPool(AtIndexSetterSelector,
   1331                                          RefExpr->getSourceRange(),
   1332                                          true);
   1333   }
   1334 
   1335   bool err = false;
   1336   if (AtIndexSetter && arrayRef) {
   1337     QualType T = AtIndexSetter->parameters()[1]->getType();
   1338     if (!T->isIntegralOrEnumerationType()) {
   1339       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
   1340              diag::err_objc_subscript_index_type) << T;
   1341       S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
   1342              diag::note_parameter_type) << T;
   1343       err = true;
   1344     }
   1345     T = AtIndexSetter->parameters()[0]->getType();
   1346     if (!T->isObjCObjectPointerType()) {
   1347       S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
   1348              diag::err_objc_subscript_object_type) << T << arrayRef;
   1349       S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
   1350              diag::note_parameter_type) << T;
   1351       err = true;
   1352     }
   1353   }
   1354   else if (AtIndexSetter && !arrayRef)
   1355     for (unsigned i=0; i <2; i++) {
   1356       QualType T = AtIndexSetter->parameters()[i]->getType();
   1357       if (!T->isObjCObjectPointerType()) {
   1358         if (i == 1)
   1359           S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
   1360                  diag::err_objc_subscript_key_type) << T;
   1361         else
   1362           S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
   1363                  diag::err_objc_subscript_dic_object_type) << T;
   1364         S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
   1365                diag::note_parameter_type) << T;
   1366         err = true;
   1367       }
   1368     }
   1369 
   1370   return !err;
   1371 }
   1372 
   1373 // Get the object at "Index" position in the container.
   1374 // [BaseExpr objectAtIndexedSubscript : IndexExpr];
   1375 ExprResult ObjCSubscriptOpBuilder::buildGet() {
   1376   if (!findAtIndexGetter())
   1377     return ExprError();
   1378 
   1379   QualType receiverType = InstanceBase->getType();
   1380 
   1381   // Build a message-send.
   1382   ExprResult msg;
   1383   Expr *Index = InstanceKey;
   1384 
   1385   // Arguments.
   1386   Expr *args[] = { Index };
   1387   assert(InstanceBase);
   1388   if (AtIndexGetter)
   1389     S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);
   1390   msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
   1391                                        GenericLoc,
   1392                                        AtIndexGetterSelector, AtIndexGetter,
   1393                                        MultiExprArg(args, 1));
   1394   return msg;
   1395 }
   1396 
   1397 /// Store into the container the "op" object at "Index"'ed location
   1398 /// by building this messaging expression:
   1399 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
   1400 /// \param captureSetValueAsResult If true, capture the actual
   1401 ///   value being set as the value of the property operation.
   1402 ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
   1403                                            bool captureSetValueAsResult) {
   1404   if (!findAtIndexSetter())
   1405     return ExprError();
   1406   if (AtIndexSetter)
   1407     S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);
   1408   QualType receiverType = InstanceBase->getType();
   1409   Expr *Index = InstanceKey;
   1410 
   1411   // Arguments.
   1412   Expr *args[] = { op, Index };
   1413 
   1414   // Build a message-send.
   1415   ExprResult msg = S.BuildInstanceMessageImplicit(InstanceBase, receiverType,
   1416                                                   GenericLoc,
   1417                                                   AtIndexSetterSelector,
   1418                                                   AtIndexSetter,
   1419                                                   MultiExprArg(args, 2));
   1420 
   1421   if (!msg.isInvalid() && captureSetValueAsResult) {
   1422     ObjCMessageExpr *msgExpr =
   1423       cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
   1424     Expr *arg = msgExpr->getArg(0);
   1425     if (CanCaptureValue(arg))
   1426       msgExpr->setArg(0, captureValueAsResult(arg));
   1427   }
   1428 
   1429   return msg;
   1430 }
   1431 
   1432 //===----------------------------------------------------------------------===//
   1433 //  MSVC __declspec(property) references
   1434 //===----------------------------------------------------------------------===//
   1435 
   1436 MSPropertyRefExpr *
   1437 MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
   1438   CallArgs.insert(CallArgs.begin(), E->getIdx());
   1439   Expr *Base = E->getBase()->IgnoreParens();
   1440   while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
   1441     CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
   1442     Base = MSPropSubscript->getBase()->IgnoreParens();
   1443   }
   1444   return cast<MSPropertyRefExpr>(Base);
   1445 }
   1446 
   1447 Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
   1448   InstanceBase = capture(RefExpr->getBaseExpr());
   1449   std::for_each(CallArgs.begin(), CallArgs.end(),
   1450                 [this](Expr *&Arg) { Arg = capture(Arg); });
   1451   syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
   1452                     switch (Idx) {
   1453                     case 0:
   1454                       return InstanceBase;
   1455                     default:
   1456                       assert(Idx <= CallArgs.size());
   1457                       return CallArgs[Idx - 1];
   1458                     }
   1459                   }).rebuild(syntacticBase);
   1460 
   1461   return syntacticBase;
   1462 }
   1463 
   1464 ExprResult MSPropertyOpBuilder::buildGet() {
   1465   if (!RefExpr->getPropertyDecl()->hasGetter()) {
   1466     S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
   1467       << 0 /* getter */ << RefExpr->getPropertyDecl();
   1468     return ExprError();
   1469   }
   1470 
   1471   UnqualifiedId GetterName;
   1472   IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();
   1473   GetterName.setIdentifier(II, RefExpr->getMemberLoc());
   1474   CXXScopeSpec SS;
   1475   SS.Adopt(RefExpr->getQualifierLoc());
   1476   ExprResult GetterExpr =
   1477       S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
   1478                               RefExpr->isArrow() ? tok::arrow : tok::period, SS,
   1479                               SourceLocation(), GetterName, nullptr);
   1480   if (GetterExpr.isInvalid()) {
   1481     S.Diag(RefExpr->getMemberLoc(),
   1482            diag::error_cannot_find_suitable_accessor) << 0 /* getter */
   1483       << RefExpr->getPropertyDecl();
   1484     return ExprError();
   1485   }
   1486 
   1487   return S.ActOnCallExpr(S.getCurScope(), GetterExpr.get(),
   1488                          RefExpr->getSourceRange().getBegin(), CallArgs,
   1489                          RefExpr->getSourceRange().getEnd());
   1490 }
   1491 
   1492 ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
   1493                                          bool captureSetValueAsResult) {
   1494   if (!RefExpr->getPropertyDecl()->hasSetter()) {
   1495     S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
   1496       << 1 /* setter */ << RefExpr->getPropertyDecl();
   1497     return ExprError();
   1498   }
   1499 
   1500   UnqualifiedId SetterName;
   1501   IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();
   1502   SetterName.setIdentifier(II, RefExpr->getMemberLoc());
   1503   CXXScopeSpec SS;
   1504   SS.Adopt(RefExpr->getQualifierLoc());
   1505   ExprResult SetterExpr =
   1506       S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
   1507                               RefExpr->isArrow() ? tok::arrow : tok::period, SS,
   1508                               SourceLocation(), SetterName, nullptr);
   1509   if (SetterExpr.isInvalid()) {
   1510     S.Diag(RefExpr->getMemberLoc(),
   1511            diag::error_cannot_find_suitable_accessor) << 1 /* setter */
   1512       << RefExpr->getPropertyDecl();
   1513     return ExprError();
   1514   }
   1515 
   1516   SmallVector<Expr*, 4> ArgExprs;
   1517   ArgExprs.append(CallArgs.begin(), CallArgs.end());
   1518   ArgExprs.push_back(op);
   1519   return S.ActOnCallExpr(S.getCurScope(), SetterExpr.get(),
   1520                          RefExpr->getSourceRange().getBegin(), ArgExprs,
   1521                          op->getSourceRange().getEnd());
   1522 }
   1523 
   1524 //===----------------------------------------------------------------------===//
   1525 //  General Sema routines.
   1526 //===----------------------------------------------------------------------===//
   1527 
   1528 ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
   1529   Expr *opaqueRef = E->IgnoreParens();
   1530   if (ObjCPropertyRefExpr *refExpr
   1531         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
   1532     ObjCPropertyOpBuilder builder(*this, refExpr);
   1533     return builder.buildRValueOperation(E);
   1534   }
   1535   else if (ObjCSubscriptRefExpr *refExpr
   1536            = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
   1537     ObjCSubscriptOpBuilder builder(*this, refExpr);
   1538     return builder.buildRValueOperation(E);
   1539   } else if (MSPropertyRefExpr *refExpr
   1540              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
   1541     MSPropertyOpBuilder builder(*this, refExpr);
   1542     return builder.buildRValueOperation(E);
   1543   } else if (MSPropertySubscriptExpr *RefExpr =
   1544                  dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
   1545     MSPropertyOpBuilder Builder(*this, RefExpr);
   1546     return Builder.buildRValueOperation(E);
   1547   } else {
   1548     llvm_unreachable("unknown pseudo-object kind!");
   1549   }
   1550 }
   1551 
   1552 /// Check an increment or decrement of a pseudo-object expression.
   1553 ExprResult Sema::checkPseudoObjectIncDec(Scope *Sc, SourceLocation opcLoc,
   1554                                          UnaryOperatorKind opcode, Expr *op) {
   1555   // Do nothing if the operand is dependent.
   1556   if (op->isTypeDependent())
   1557     return new (Context) UnaryOperator(op, opcode, Context.DependentTy,
   1558                                        VK_RValue, OK_Ordinary, opcLoc);
   1559 
   1560   assert(UnaryOperator::isIncrementDecrementOp(opcode));
   1561   Expr *opaqueRef = op->IgnoreParens();
   1562   if (ObjCPropertyRefExpr *refExpr
   1563         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
   1564     ObjCPropertyOpBuilder builder(*this, refExpr);
   1565     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   1566   } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
   1567     Diag(opcLoc, diag::err_illegal_container_subscripting_op);
   1568     return ExprError();
   1569   } else if (MSPropertyRefExpr *refExpr
   1570              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
   1571     MSPropertyOpBuilder builder(*this, refExpr);
   1572     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   1573   } else if (MSPropertySubscriptExpr *RefExpr
   1574              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
   1575     MSPropertyOpBuilder Builder(*this, RefExpr);
   1576     return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
   1577   } else {
   1578     llvm_unreachable("unknown pseudo-object kind!");
   1579   }
   1580 }
   1581 
   1582 ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
   1583                                              BinaryOperatorKind opcode,
   1584                                              Expr *LHS, Expr *RHS) {
   1585   // Do nothing if either argument is dependent.
   1586   if (LHS->isTypeDependent() || RHS->isTypeDependent())
   1587     return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy,
   1588                                         VK_RValue, OK_Ordinary, opcLoc, false);
   1589 
   1590   // Filter out non-overload placeholder types in the RHS.
   1591   if (RHS->getType()->isNonOverloadPlaceholderType()) {
   1592     ExprResult result = CheckPlaceholderExpr(RHS);
   1593     if (result.isInvalid()) return ExprError();
   1594     RHS = result.get();
   1595   }
   1596 
   1597   Expr *opaqueRef = LHS->IgnoreParens();
   1598   if (ObjCPropertyRefExpr *refExpr
   1599         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
   1600     ObjCPropertyOpBuilder builder(*this, refExpr);
   1601     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   1602   } else if (ObjCSubscriptRefExpr *refExpr
   1603              = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
   1604     ObjCSubscriptOpBuilder builder(*this, refExpr);
   1605     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   1606   } else if (MSPropertyRefExpr *refExpr
   1607              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
   1608       MSPropertyOpBuilder builder(*this, refExpr);
   1609       return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   1610   } else if (MSPropertySubscriptExpr *RefExpr
   1611              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
   1612       MSPropertyOpBuilder Builder(*this, RefExpr);
   1613       return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
   1614   } else {
   1615     llvm_unreachable("unknown pseudo-object kind!");
   1616   }
   1617 }
   1618 
   1619 /// Given a pseudo-object reference, rebuild it without the opaque
   1620 /// values.  Basically, undo the behavior of rebuildAndCaptureObject.
   1621 /// This should never operate in-place.
   1622 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
   1623   return Rebuilder(S,
   1624                    [=](Expr *E, unsigned) -> Expr * {
   1625                      return cast<OpaqueValueExpr>(E)->getSourceExpr();
   1626                    })
   1627       .rebuild(E);
   1628 }
   1629 
   1630 /// Given a pseudo-object expression, recreate what it looks like
   1631 /// syntactically without the attendant OpaqueValueExprs.
   1632 ///
   1633 /// This is a hack which should be removed when TreeTransform is
   1634 /// capable of rebuilding a tree without stripping implicit
   1635 /// operations.
   1636 Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) {
   1637   Expr *syntax = E->getSyntacticForm();
   1638   if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
   1639     Expr *op = stripOpaqueValuesFromPseudoObjectRef(*this, uop->getSubExpr());
   1640     return new (Context) UnaryOperator(op, uop->getOpcode(), uop->getType(),
   1641                                        uop->getValueKind(), uop->getObjectKind(),
   1642                                        uop->getOperatorLoc());
   1643   } else if (CompoundAssignOperator *cop
   1644                = dyn_cast<CompoundAssignOperator>(syntax)) {
   1645     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, cop->getLHS());
   1646     Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
   1647     return new (Context) CompoundAssignOperator(lhs, rhs, cop->getOpcode(),
   1648                                                 cop->getType(),
   1649                                                 cop->getValueKind(),
   1650                                                 cop->getObjectKind(),
   1651                                                 cop->getComputationLHSType(),
   1652                                                 cop->getComputationResultType(),
   1653                                                 cop->getOperatorLoc(), false);
   1654   } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
   1655     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS());
   1656     Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
   1657     return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(),
   1658                                         bop->getType(), bop->getValueKind(),
   1659                                         bop->getObjectKind(),
   1660                                         bop->getOperatorLoc(), false);
   1661   } else {
   1662     assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
   1663     return stripOpaqueValuesFromPseudoObjectRef(*this, syntax);
   1664   }
   1665 }
   1666