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