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