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