xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp (revision 62cfcf62f627e5093fb37026a6d8c98e4d2ef04c)
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 
41 using namespace clang;
42 using namespace sema;
43 
44 namespace {
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.
366 OpaqueValueExpr *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
386 OpaqueValueExpr *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.
412 ExprResult 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.
418 ExprResult 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.
430 ExprResult
431 PseudoOpBuilder::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.
495 ExprResult
496 PseudoOpBuilder::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.
555 static 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 
589 bool 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 
606 bool 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
638 bool 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 
695 void 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.
708 Expr *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.
728 ExprResult 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.
761 ExprResult 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.
828 ExprResult 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
870 bool 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.
891 ExprResult
892 ObjCPropertyOpBuilder::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.
938 ExprResult
939 ObjCPropertyOpBuilder::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 
975 ExprResult 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.
992 ExprResult 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.
999 ExprResult
1000 ObjCSubscriptOpBuilder::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.
1027 Expr *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.
1052 Sema::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.
1126 static 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 
1145 bool 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 
1248 bool 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];
1383 ExprResult 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.
1410 ExprResult 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 
1444 MSPropertyRefExpr *
1445 MSPropertyOpBuilder::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 
1455 Expr *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 
1471 ExprResult 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 
1499 ExprResult 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 
1535 ExprResult 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.
1560 ExprResult 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 
1589 ExprResult 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.
1631 static 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.
1645 Expr *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