xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaPseudoObject.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/SemaPseudoObject.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 "clang/Sema/SemaInternal.h"
40 #include "clang/Sema/SemaObjC.h"
41 #include "llvm/ADT/SmallString.h"
42 
43 using namespace clang;
44 using namespace sema;
45 
46 namespace {
47   // Basically just a very focused copy of TreeTransform.
48   struct Rebuilder {
49     Sema &S;
50     unsigned MSPropertySubscriptCount;
51     typedef llvm::function_ref<Expr *(Expr *, unsigned)> SpecificRebuilderRefTy;
52     const SpecificRebuilderRefTy &SpecificCallback;
Rebuilder__anonb581425c0111::Rebuilder53     Rebuilder(Sema &S, const SpecificRebuilderRefTy &SpecificCallback)
54         : S(S), MSPropertySubscriptCount(0),
55           SpecificCallback(SpecificCallback) {}
56 
rebuildObjCPropertyRefExpr__anonb581425c0111::Rebuilder57     Expr *rebuildObjCPropertyRefExpr(ObjCPropertyRefExpr *refExpr) {
58       // Fortunately, the constraint that we're rebuilding something
59       // with a base limits the number of cases here.
60       if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
61         return refExpr;
62 
63       if (refExpr->isExplicitProperty()) {
64         return new (S.Context) ObjCPropertyRefExpr(
65             refExpr->getExplicitProperty(), refExpr->getType(),
66             refExpr->getValueKind(), refExpr->getObjectKind(),
67             refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
68       }
69       return new (S.Context) ObjCPropertyRefExpr(
70           refExpr->getImplicitPropertyGetter(),
71           refExpr->getImplicitPropertySetter(), refExpr->getType(),
72           refExpr->getValueKind(), refExpr->getObjectKind(),
73           refExpr->getLocation(), SpecificCallback(refExpr->getBase(), 0));
74     }
rebuildObjCSubscriptRefExpr__anonb581425c0111::Rebuilder75     Expr *rebuildObjCSubscriptRefExpr(ObjCSubscriptRefExpr *refExpr) {
76       assert(refExpr->getBaseExpr());
77       assert(refExpr->getKeyExpr());
78 
79       return new (S.Context) ObjCSubscriptRefExpr(
80           SpecificCallback(refExpr->getBaseExpr(), 0),
81           SpecificCallback(refExpr->getKeyExpr(), 1), refExpr->getType(),
82           refExpr->getValueKind(), refExpr->getObjectKind(),
83           refExpr->getAtIndexMethodDecl(), refExpr->setAtIndexMethodDecl(),
84           refExpr->getRBracket());
85     }
rebuildMSPropertyRefExpr__anonb581425c0111::Rebuilder86     Expr *rebuildMSPropertyRefExpr(MSPropertyRefExpr *refExpr) {
87       assert(refExpr->getBaseExpr());
88 
89       return new (S.Context) MSPropertyRefExpr(
90           SpecificCallback(refExpr->getBaseExpr(), 0),
91           refExpr->getPropertyDecl(), refExpr->isArrow(), refExpr->getType(),
92           refExpr->getValueKind(), refExpr->getQualifierLoc(),
93           refExpr->getMemberLoc());
94     }
rebuildMSPropertySubscriptExpr__anonb581425c0111::Rebuilder95     Expr *rebuildMSPropertySubscriptExpr(MSPropertySubscriptExpr *refExpr) {
96       assert(refExpr->getBase());
97       assert(refExpr->getIdx());
98 
99       auto *NewBase = rebuild(refExpr->getBase());
100       ++MSPropertySubscriptCount;
101       return new (S.Context) MSPropertySubscriptExpr(
102           NewBase,
103           SpecificCallback(refExpr->getIdx(), MSPropertySubscriptCount),
104           refExpr->getType(), refExpr->getValueKind(), refExpr->getObjectKind(),
105           refExpr->getRBracketLoc());
106     }
107 
rebuild__anonb581425c0111::Rebuilder108     Expr *rebuild(Expr *e) {
109       // Fast path: nothing to look through.
110       if (auto *PRE = dyn_cast<ObjCPropertyRefExpr>(e))
111         return rebuildObjCPropertyRefExpr(PRE);
112       if (auto *SRE = dyn_cast<ObjCSubscriptRefExpr>(e))
113         return rebuildObjCSubscriptRefExpr(SRE);
114       if (auto *MSPRE = dyn_cast<MSPropertyRefExpr>(e))
115         return rebuildMSPropertyRefExpr(MSPRE);
116       if (auto *MSPSE = dyn_cast<MSPropertySubscriptExpr>(e))
117         return rebuildMSPropertySubscriptExpr(MSPSE);
118 
119       // Otherwise, we should look through and rebuild anything that
120       // IgnoreParens would.
121 
122       if (ParenExpr *parens = dyn_cast<ParenExpr>(e)) {
123         e = rebuild(parens->getSubExpr());
124         return new (S.Context) ParenExpr(parens->getLParen(),
125                                          parens->getRParen(),
126                                          e);
127       }
128 
129       if (UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
130         assert(uop->getOpcode() == UO_Extension);
131         e = rebuild(uop->getSubExpr());
132         return UnaryOperator::Create(
133             S.Context, e, uop->getOpcode(), uop->getType(), uop->getValueKind(),
134             uop->getObjectKind(), uop->getOperatorLoc(), uop->canOverflow(),
135             S.CurFPFeatureOverrides());
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         if (gse->isExprPredicate())
158           return GenericSelectionExpr::Create(
159               S.Context, gse->getGenericLoc(), gse->getControllingExpr(),
160               assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
161               gse->containsUnexpandedParameterPack(), resultIndex);
162         return GenericSelectionExpr::Create(
163             S.Context, gse->getGenericLoc(), gse->getControllingType(),
164             assocTypes, assocExprs, gse->getDefaultLoc(), gse->getRParenLoc(),
165             gse->containsUnexpandedParameterPack(), resultIndex);
166       }
167 
168       if (ChooseExpr *ce = dyn_cast<ChooseExpr>(e)) {
169         assert(!ce->isConditionDependent());
170 
171         Expr *LHS = ce->getLHS(), *RHS = ce->getRHS();
172         Expr *&rebuiltExpr = ce->isConditionTrue() ? LHS : RHS;
173         rebuiltExpr = rebuild(rebuiltExpr);
174 
175         return new (S.Context)
176             ChooseExpr(ce->getBuiltinLoc(), ce->getCond(), LHS, RHS,
177                        rebuiltExpr->getType(), rebuiltExpr->getValueKind(),
178                        rebuiltExpr->getObjectKind(), ce->getRParenLoc(),
179                        ce->isConditionTrue());
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 
PseudoOpBuilder(Sema & S,SourceLocation genericLoc,bool IsUnique)194     PseudoOpBuilder(Sema &S, SourceLocation genericLoc, bool IsUnique)
195       : S(S), ResultIndex(PseudoObjectExpr::NoResult),
196         GenericLoc(genericLoc), IsUnique(IsUnique) {}
197 
~PseudoOpBuilder()198     virtual ~PseudoOpBuilder() {}
199 
200     /// Add a normal semantic expression.
addSemanticExpr(Expr * semantic)201     void addSemanticExpr(Expr *semantic) {
202       Semantics.push_back(semantic);
203     }
204 
205     /// Add the 'result' semantic expression.
addResultSemanticExpr(Expr * resultExpr)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 
setResultToLastSemantic()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.
CanCaptureValue(Expr * exp)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.
captureSetValueAsResult() const267     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:
ObjCPropertyOpBuilder(Sema & S,ObjCPropertyRefExpr * refExpr,bool IsUnique)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:
ObjCSubscriptOpBuilder(Sema & S,ObjCSubscriptRefExpr * refExpr,bool IsUnique)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:
MSPropertyOpBuilder(Sema & S,MSPropertyRefExpr * refExpr,bool IsUnique)349    MSPropertyOpBuilder(Sema &S, MSPropertyRefExpr *refExpr, bool IsUnique)
350        : PseudoOpBuilder(S, refExpr->getSourceRange().getBegin(), IsUnique),
351          RefExpr(refExpr), InstanceBase(nullptr) {}
MSPropertyOpBuilder(Sema & S,MSPropertySubscriptExpr * refExpr,bool IsUnique)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;
captureSetValueAsResult() const361    bool captureSetValueAsResult() const override { return false; }
362  };
363 }
364 
365 /// Capture the given expression in an OpaqueValueExpr.
capture(Expr * e)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
captureValueAsResult(Expr * e)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.
complete(Expr * syntactic)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.
buildRValueOperation(Expr * op)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
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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 = BinaryOperator::Create(S.Context, syntacticLHS, capturedRHS,
457                                        opcode, capturedRHS->getType(),
458                                        capturedRHS->getValueKind(), OK_Ordinary,
459                                        opcLoc, S.CurFPFeatureOverrides());
460 
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 = CompoundAssignOperator::Create(
472         S.Context, syntacticLHS, capturedRHS, opcode, result.get()->getType(),
473         result.get()->getValueKind(), OK_Ordinary, opcLoc,
474         S.CurFPFeatureOverrides(), opLHS.get()->getType(),
475         result.get()->getType());
476   }
477 
478   // The result of the assignment, if not void, is the value set into
479   // the l-value.
480   result = buildSet(result.get(), opcLoc, captureSetValueAsResult());
481   if (result.isInvalid()) return ExprError();
482   addSemanticExpr(result.get());
483   if (!captureSetValueAsResult() && !result.get()->getType()->isVoidType() &&
484       (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
485     setResultToLastSemantic();
486 
487   return complete(syntactic);
488 }
489 
490 /// The basic skeleton for building an increment or decrement
491 /// operation.
492 ExprResult
buildIncDecOperation(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)493 PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
494                                       UnaryOperatorKind opcode,
495                                       Expr *op) {
496   assert(UnaryOperator::isIncrementDecrementOp(opcode));
497 
498   Expr *syntacticOp = rebuildAndCaptureObject(op);
499 
500   // Load the value.
501   ExprResult result = buildGet();
502   if (result.isInvalid()) return ExprError();
503 
504   QualType resultType = result.get()->getType();
505 
506   // That's the postfix result.
507   if (UnaryOperator::isPostfix(opcode) &&
508       (result.get()->isTypeDependent() || CanCaptureValue(result.get()))) {
509     result = capture(result.get());
510     setResultToLastSemantic();
511   }
512 
513   // Add or subtract a literal 1.
514   llvm::APInt oneV(S.Context.getTypeSize(S.Context.IntTy), 1);
515   Expr *one = IntegerLiteral::Create(S.Context, oneV, S.Context.IntTy,
516                                      GenericLoc);
517 
518   if (UnaryOperator::isIncrementOp(opcode)) {
519     result = S.BuildBinOp(Sc, opcLoc, BO_Add, result.get(), one);
520   } else {
521     result = S.BuildBinOp(Sc, opcLoc, BO_Sub, result.get(), one);
522   }
523   if (result.isInvalid()) return ExprError();
524 
525   // Store that back into the result.  The value stored is the result
526   // of a prefix operation.
527   result = buildSet(result.get(), opcLoc, UnaryOperator::isPrefix(opcode) &&
528                                               captureSetValueAsResult());
529   if (result.isInvalid()) return ExprError();
530   addSemanticExpr(result.get());
531   if (UnaryOperator::isPrefix(opcode) && !captureSetValueAsResult() &&
532       !result.get()->getType()->isVoidType() &&
533       (result.get()->isTypeDependent() || CanCaptureValue(result.get())))
534     setResultToLastSemantic();
535 
536   UnaryOperator *syntactic =
537       UnaryOperator::Create(S.Context, syntacticOp, opcode, resultType,
538                             VK_LValue, OK_Ordinary, opcLoc,
539                             !resultType->isDependentType()
540                                 ? S.Context.getTypeSize(resultType) >=
541                                       S.Context.getTypeSize(S.Context.IntTy)
542                                 : false,
543                             S.CurFPFeatureOverrides());
544   return complete(syntactic);
545 }
546 
547 
548 //===----------------------------------------------------------------------===//
549 //  Objective-C @property and implicit property references
550 //===----------------------------------------------------------------------===//
551 
552 /// Look up a method in the receiver type of an Objective-C property
553 /// reference.
LookupMethodInReceiverType(Sema & S,Selector sel,const ObjCPropertyRefExpr * PRE)554 static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
555                                             const ObjCPropertyRefExpr *PRE) {
556   if (PRE->isObjectReceiver()) {
557     const ObjCObjectPointerType *PT =
558       PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
559 
560     // Special case for 'self' in class method implementations.
561     if (PT->isObjCClassType() &&
562         S.ObjC().isSelfExpr(const_cast<Expr *>(PRE->getBase()))) {
563       // This cast is safe because isSelfExpr is only true within
564       // methods.
565       ObjCMethodDecl *method =
566         cast<ObjCMethodDecl>(S.CurContext->getNonClosureAncestor());
567       return S.ObjC().LookupMethodInObjectType(
568           sel, S.Context.getObjCInterfaceType(method->getClassInterface()),
569           /*instance*/ false);
570     }
571 
572     return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);
573   }
574 
575   if (PRE->isSuperReceiver()) {
576     if (const ObjCObjectPointerType *PT =
577         PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
578       return S.ObjC().LookupMethodInObjectType(sel, PT->getPointeeType(), true);
579 
580     return S.ObjC().LookupMethodInObjectType(sel, PRE->getSuperReceiverType(),
581                                              false);
582   }
583 
584   assert(PRE->isClassReceiver() && "Invalid expression");
585   QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
586   return S.ObjC().LookupMethodInObjectType(sel, IT, false);
587 }
588 
isWeakProperty() const589 bool ObjCPropertyOpBuilder::isWeakProperty() const {
590   QualType T;
591   if (RefExpr->isExplicitProperty()) {
592     const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty();
593     if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_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 
findGetter()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       const IdentifierInfo *setterName =
620           setter->getSelector().getIdentifierInfoForSlot(0);
621       const 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
findSetter(bool warn)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       const IdentifierInfo *getterName = RefExpr->getImplicitPropertyGetter()
647                                              ->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         const IdentifierInfo *AltMember =
674             &S.PP.getIdentifierTable().get(PropertyName);
675         if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(
676                 AltMember, prop->getQueryKind()))
677           if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) {
678             S.Diag(RefExpr->getExprLoc(), diag::err_property_setter_ambiguous_use)
679               << prop << prop1 << setter->getSelector();
680             S.Diag(prop->getLocation(), diag::note_property_declare);
681             S.Diag(prop1->getLocation(), diag::note_property_declare);
682           }
683       }
684     Setter = setter;
685     return true;
686   }
687 
688   // That can fail in the somewhat crazy situation that we're
689   // type-checking a message send within the @interface declaration
690   // that declared the @property.  But it's not clear that that's
691   // valuable to support.
692 
693   return false;
694 }
695 
DiagnoseUnsupportedPropertyUse()696 void ObjCPropertyOpBuilder::DiagnoseUnsupportedPropertyUse() {
697   if (S.getCurLexicalContext()->isObjCContainer() &&
698       S.getCurLexicalContext()->getDeclKind() != Decl::ObjCCategoryImpl &&
699       S.getCurLexicalContext()->getDeclKind() != Decl::ObjCImplementation) {
700     if (ObjCPropertyDecl *prop = RefExpr->getExplicitProperty()) {
701         S.Diag(RefExpr->getLocation(),
702                diag::err_property_function_in_objc_container);
703         S.Diag(prop->getLocation(), diag::note_property_declare);
704     }
705   }
706 }
707 
708 /// Capture the base object of an Objective-C property expression.
rebuildAndCaptureObject(Expr * syntacticBase)709 Expr *ObjCPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
710   assert(InstanceReceiver == nullptr);
711 
712   // If we have a base, capture it in an OVE and rebuild the syntactic
713   // form to use the OVE as its base.
714   if (RefExpr->isObjectReceiver()) {
715     InstanceReceiver = capture(RefExpr->getBase());
716     syntacticBase = Rebuilder(S, [=](Expr *, unsigned) -> Expr * {
717                       return InstanceReceiver;
718                     }).rebuild(syntacticBase);
719   }
720 
721   if (ObjCPropertyRefExpr *
722         refE = dyn_cast<ObjCPropertyRefExpr>(syntacticBase->IgnoreParens()))
723     SyntacticRefExpr = refE;
724 
725   return syntacticBase;
726 }
727 
728 /// Load from an Objective-C property reference.
buildGet()729 ExprResult ObjCPropertyOpBuilder::buildGet() {
730   findGetter();
731   if (!Getter) {
732     DiagnoseUnsupportedPropertyUse();
733     return ExprError();
734   }
735 
736   if (SyntacticRefExpr)
737     SyntacticRefExpr->setIsMessagingGetter();
738 
739   QualType receiverType = RefExpr->getReceiverType(S.Context);
740   if (!Getter->isImplicit())
741     S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true);
742   // Build a message-send.
743   ExprResult msg;
744   if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
745       RefExpr->isObjectReceiver()) {
746     assert(InstanceReceiver || RefExpr->isSuperReceiver());
747     msg = S.ObjC().BuildInstanceMessageImplicit(
748         InstanceReceiver, receiverType, GenericLoc, Getter->getSelector(),
749         Getter, std::nullopt);
750   } else {
751     msg = S.ObjC().BuildClassMessageImplicit(
752         receiverType, RefExpr->isSuperReceiver(), GenericLoc,
753         Getter->getSelector(), Getter, std::nullopt);
754   }
755   return msg;
756 }
757 
758 /// Store to an Objective-C property reference.
759 ///
760 /// \param captureSetValueAsResult If true, capture the actual
761 ///   value being set as the value of the property operation.
buildSet(Expr * op,SourceLocation opcLoc,bool captureSetValueAsResult)762 ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
763                                            bool captureSetValueAsResult) {
764   if (!findSetter(false)) {
765     DiagnoseUnsupportedPropertyUse();
766     return ExprError();
767   }
768 
769   if (SyntacticRefExpr)
770     SyntacticRefExpr->setIsMessagingSetter();
771 
772   QualType receiverType = RefExpr->getReceiverType(S.Context);
773 
774   // Use assignment constraints when possible; they give us better
775   // diagnostics.  "When possible" basically means anything except a
776   // C++ class type.
777   if (!S.getLangOpts().CPlusPlus || !op->getType()->isRecordType()) {
778     QualType paramType = (*Setter->param_begin())->getType()
779                            .substObjCMemberType(
780                              receiverType,
781                              Setter->getDeclContext(),
782                              ObjCSubstitutionContext::Parameter);
783     if (!S.getLangOpts().CPlusPlus || !paramType->isRecordType()) {
784       ExprResult opResult = op;
785       Sema::AssignConvertType assignResult
786         = S.CheckSingleAssignmentConstraints(paramType, opResult);
787       if (opResult.isInvalid() ||
788           S.DiagnoseAssignmentResult(assignResult, opcLoc, paramType,
789                                      op->getType(), opResult.get(),
790                                      Sema::AA_Assigning))
791         return ExprError();
792 
793       op = opResult.get();
794       assert(op && "successful assignment left argument invalid?");
795     }
796   }
797 
798   // Arguments.
799   Expr *args[] = { op };
800 
801   // Build a message-send.
802   ExprResult msg;
803   if (!Setter->isImplicit())
804     S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true);
805   if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) ||
806       RefExpr->isObjectReceiver()) {
807     msg = S.ObjC().BuildInstanceMessageImplicit(InstanceReceiver, receiverType,
808                                                 GenericLoc, SetterSelector,
809                                                 Setter, MultiExprArg(args, 1));
810   } else {
811     msg = S.ObjC().BuildClassMessageImplicit(
812         receiverType, RefExpr->isSuperReceiver(), GenericLoc, SetterSelector,
813         Setter, 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.
buildRValueOperation(Expr * op)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.ObjC().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()->isPRValue()) {
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
tryBuildGetOfReference(Expr * op,ExprResult & result)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
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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.ObjC().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
buildIncDecOperation(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)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 
complete(Expr * SyntacticForm)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.
buildRValueOperation(Expr * op)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
buildAssignmentOperation(Scope * Sc,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)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.ObjC().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.
rebuildAndCaptureObject(Expr * syntacticBase)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 /// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF
1051 /// objects used as dictionary subscript key objects.
CheckKeyForObjCARCConversion(Sema & S,QualType ContainerT,Expr * Key)1052 static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT,
1053                                          Expr *Key) {
1054   if (ContainerT.isNull())
1055     return;
1056   // dictionary subscripting.
1057   // - (id)objectForKeyedSubscript:(id)key;
1058   const IdentifierInfo *KeyIdents[] = {
1059       &S.Context.Idents.get("objectForKeyedSubscript")};
1060   Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1061   ObjCMethodDecl *Getter = S.ObjC().LookupMethodInObjectType(
1062       GetterSelector, ContainerT, true /*instance*/);
1063   if (!Getter)
1064     return;
1065   QualType T = Getter->parameters()[0]->getType();
1066   S.ObjC().CheckObjCConversion(Key->getSourceRange(), T, Key,
1067                                CheckedConversionKind::Implicit);
1068 }
1069 
findAtIndexGetter()1070 bool ObjCSubscriptOpBuilder::findAtIndexGetter() {
1071   if (AtIndexGetter)
1072     return true;
1073 
1074   Expr *BaseExpr = RefExpr->getBaseExpr();
1075   QualType BaseT = BaseExpr->getType();
1076 
1077   QualType ResultType;
1078   if (const ObjCObjectPointerType *PTy =
1079       BaseT->getAs<ObjCObjectPointerType>()) {
1080     ResultType = PTy->getPointeeType();
1081   }
1082   SemaObjC::ObjCSubscriptKind Res =
1083       S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());
1084   if (Res == SemaObjC::OS_Error) {
1085     if (S.getLangOpts().ObjCAutoRefCount)
1086       CheckKeyForObjCARCConversion(S, ResultType,
1087                                    RefExpr->getKeyExpr());
1088     return false;
1089   }
1090   bool arrayRef = (Res == SemaObjC::OS_Array);
1091 
1092   if (ResultType.isNull()) {
1093     S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1094       << BaseExpr->getType() << arrayRef;
1095     return false;
1096   }
1097   if (!arrayRef) {
1098     // dictionary subscripting.
1099     // - (id)objectForKeyedSubscript:(id)key;
1100     const IdentifierInfo *KeyIdents[] = {
1101         &S.Context.Idents.get("objectForKeyedSubscript")};
1102     AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1103   }
1104   else {
1105     // - (id)objectAtIndexedSubscript:(size_t)index;
1106     const IdentifierInfo *KeyIdents[] = {
1107         &S.Context.Idents.get("objectAtIndexedSubscript")};
1108 
1109     AtIndexGetterSelector = S.Context.Selectors.getSelector(1, KeyIdents);
1110   }
1111 
1112   AtIndexGetter = S.ObjC().LookupMethodInObjectType(
1113       AtIndexGetterSelector, ResultType, true /*instance*/);
1114 
1115   if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) {
1116     AtIndexGetter = ObjCMethodDecl::Create(
1117         S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector,
1118         S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */,
1119         S.Context.getTranslationUnitDecl(), true /*Instance*/,
1120         false /*isVariadic*/,
1121         /*isPropertyAccessor=*/false,
1122         /*isSynthesizedAccessorStub=*/false,
1123         /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1124         ObjCImplementationControl::Required, false);
1125     ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter,
1126                                                 SourceLocation(), SourceLocation(),
1127                                                 arrayRef ? &S.Context.Idents.get("index")
1128                                                          : &S.Context.Idents.get("key"),
1129                                                 arrayRef ? S.Context.UnsignedLongTy
1130                                                          : S.Context.getObjCIdType(),
1131                                                 /*TInfo=*/nullptr,
1132                                                 SC_None,
1133                                                 nullptr);
1134     AtIndexGetter->setMethodParams(S.Context, Argument, std::nullopt);
1135   }
1136 
1137   if (!AtIndexGetter) {
1138     if (!BaseT->isObjCIdType()) {
1139       S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_method_not_found)
1140       << BaseExpr->getType() << 0 << arrayRef;
1141       return false;
1142     }
1143     AtIndexGetter = S.ObjC().LookupInstanceMethodInGlobalPool(
1144         AtIndexGetterSelector, RefExpr->getSourceRange(), true);
1145   }
1146 
1147   if (AtIndexGetter) {
1148     QualType T = AtIndexGetter->parameters()[0]->getType();
1149     if ((arrayRef && !T->isIntegralOrEnumerationType()) ||
1150         (!arrayRef && !T->isObjCObjectPointerType())) {
1151       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1152              arrayRef ? diag::err_objc_subscript_index_type
1153                       : diag::err_objc_subscript_key_type) << T;
1154       S.Diag(AtIndexGetter->parameters()[0]->getLocation(),
1155              diag::note_parameter_type) << T;
1156       return false;
1157     }
1158     QualType R = AtIndexGetter->getReturnType();
1159     if (!R->isObjCObjectPointerType()) {
1160       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1161              diag::err_objc_indexing_method_result_type) << R << arrayRef;
1162       S.Diag(AtIndexGetter->getLocation(), diag::note_method_declared_at) <<
1163         AtIndexGetter->getDeclName();
1164     }
1165   }
1166   return true;
1167 }
1168 
findAtIndexSetter()1169 bool ObjCSubscriptOpBuilder::findAtIndexSetter() {
1170   if (AtIndexSetter)
1171     return true;
1172 
1173   Expr *BaseExpr = RefExpr->getBaseExpr();
1174   QualType BaseT = BaseExpr->getType();
1175 
1176   QualType ResultType;
1177   if (const ObjCObjectPointerType *PTy =
1178       BaseT->getAs<ObjCObjectPointerType>()) {
1179     ResultType = PTy->getPointeeType();
1180   }
1181 
1182   SemaObjC::ObjCSubscriptKind Res =
1183       S.ObjC().CheckSubscriptingKind(RefExpr->getKeyExpr());
1184   if (Res == SemaObjC::OS_Error) {
1185     if (S.getLangOpts().ObjCAutoRefCount)
1186       CheckKeyForObjCARCConversion(S, ResultType,
1187                                    RefExpr->getKeyExpr());
1188     return false;
1189   }
1190   bool arrayRef = (Res == SemaObjC::OS_Array);
1191 
1192   if (ResultType.isNull()) {
1193     S.Diag(BaseExpr->getExprLoc(), diag::err_objc_subscript_base_type)
1194       << BaseExpr->getType() << arrayRef;
1195     return false;
1196   }
1197 
1198   if (!arrayRef) {
1199     // dictionary subscripting.
1200     // - (void)setObject:(id)object forKeyedSubscript:(id)key;
1201     const IdentifierInfo *KeyIdents[] = {
1202         &S.Context.Idents.get("setObject"),
1203         &S.Context.Idents.get("forKeyedSubscript")};
1204     AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1205   }
1206   else {
1207     // - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1208     const IdentifierInfo *KeyIdents[] = {
1209         &S.Context.Idents.get("setObject"),
1210         &S.Context.Idents.get("atIndexedSubscript")};
1211     AtIndexSetterSelector = S.Context.Selectors.getSelector(2, KeyIdents);
1212   }
1213   AtIndexSetter = S.ObjC().LookupMethodInObjectType(
1214       AtIndexSetterSelector, ResultType, true /*instance*/);
1215 
1216   if (!AtIndexSetter && S.getLangOpts().DebuggerObjCLiteral) {
1217     TypeSourceInfo *ReturnTInfo = nullptr;
1218     QualType ReturnType = S.Context.VoidTy;
1219     AtIndexSetter = ObjCMethodDecl::Create(
1220         S.Context, SourceLocation(), SourceLocation(), AtIndexSetterSelector,
1221         ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(),
1222         true /*Instance*/, false /*isVariadic*/,
1223         /*isPropertyAccessor=*/false,
1224         /*isSynthesizedAccessorStub=*/false,
1225         /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1226         ObjCImplementationControl::Required, false);
1227     SmallVector<ParmVarDecl *, 2> Params;
1228     ParmVarDecl *object = ParmVarDecl::Create(S.Context, AtIndexSetter,
1229                                                 SourceLocation(), SourceLocation(),
1230                                                 &S.Context.Idents.get("object"),
1231                                                 S.Context.getObjCIdType(),
1232                                                 /*TInfo=*/nullptr,
1233                                                 SC_None,
1234                                                 nullptr);
1235     Params.push_back(object);
1236     ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter,
1237                                                 SourceLocation(), SourceLocation(),
1238                                                 arrayRef ?  &S.Context.Idents.get("index")
1239                                                          :  &S.Context.Idents.get("key"),
1240                                                 arrayRef ? S.Context.UnsignedLongTy
1241                                                          : S.Context.getObjCIdType(),
1242                                                 /*TInfo=*/nullptr,
1243                                                 SC_None,
1244                                                 nullptr);
1245     Params.push_back(key);
1246     AtIndexSetter->setMethodParams(S.Context, Params, std::nullopt);
1247   }
1248 
1249   if (!AtIndexSetter) {
1250     if (!BaseT->isObjCIdType()) {
1251       S.Diag(BaseExpr->getExprLoc(),
1252              diag::err_objc_subscript_method_not_found)
1253       << BaseExpr->getType() << 1 << arrayRef;
1254       return false;
1255     }
1256     AtIndexSetter = S.ObjC().LookupInstanceMethodInGlobalPool(
1257         AtIndexSetterSelector, RefExpr->getSourceRange(), true);
1258   }
1259 
1260   bool err = false;
1261   if (AtIndexSetter && arrayRef) {
1262     QualType T = AtIndexSetter->parameters()[1]->getType();
1263     if (!T->isIntegralOrEnumerationType()) {
1264       S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1265              diag::err_objc_subscript_index_type) << T;
1266       S.Diag(AtIndexSetter->parameters()[1]->getLocation(),
1267              diag::note_parameter_type) << T;
1268       err = true;
1269     }
1270     T = AtIndexSetter->parameters()[0]->getType();
1271     if (!T->isObjCObjectPointerType()) {
1272       S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1273              diag::err_objc_subscript_object_type) << T << arrayRef;
1274       S.Diag(AtIndexSetter->parameters()[0]->getLocation(),
1275              diag::note_parameter_type) << T;
1276       err = true;
1277     }
1278   }
1279   else if (AtIndexSetter && !arrayRef)
1280     for (unsigned i=0; i <2; i++) {
1281       QualType T = AtIndexSetter->parameters()[i]->getType();
1282       if (!T->isObjCObjectPointerType()) {
1283         if (i == 1)
1284           S.Diag(RefExpr->getKeyExpr()->getExprLoc(),
1285                  diag::err_objc_subscript_key_type) << T;
1286         else
1287           S.Diag(RefExpr->getBaseExpr()->getExprLoc(),
1288                  diag::err_objc_subscript_dic_object_type) << T;
1289         S.Diag(AtIndexSetter->parameters()[i]->getLocation(),
1290                diag::note_parameter_type) << T;
1291         err = true;
1292       }
1293     }
1294 
1295   return !err;
1296 }
1297 
1298 // Get the object at "Index" position in the container.
1299 // [BaseExpr objectAtIndexedSubscript : IndexExpr];
buildGet()1300 ExprResult ObjCSubscriptOpBuilder::buildGet() {
1301   if (!findAtIndexGetter())
1302     return ExprError();
1303 
1304   QualType receiverType = InstanceBase->getType();
1305 
1306   // Build a message-send.
1307   ExprResult msg;
1308   Expr *Index = InstanceKey;
1309 
1310   // Arguments.
1311   Expr *args[] = { Index };
1312   assert(InstanceBase);
1313   if (AtIndexGetter)
1314     S.DiagnoseUseOfDecl(AtIndexGetter, GenericLoc);
1315   msg = S.ObjC().BuildInstanceMessageImplicit(
1316       InstanceBase, receiverType, GenericLoc, AtIndexGetterSelector,
1317       AtIndexGetter, MultiExprArg(args, 1));
1318   return msg;
1319 }
1320 
1321 /// Store into the container the "op" object at "Index"'ed location
1322 /// by building this messaging expression:
1323 /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index;
1324 /// \param captureSetValueAsResult If true, capture the actual
1325 ///   value being set as the value of the property operation.
buildSet(Expr * op,SourceLocation opcLoc,bool captureSetValueAsResult)1326 ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc,
1327                                            bool captureSetValueAsResult) {
1328   if (!findAtIndexSetter())
1329     return ExprError();
1330   if (AtIndexSetter)
1331     S.DiagnoseUseOfDecl(AtIndexSetter, GenericLoc);
1332   QualType receiverType = InstanceBase->getType();
1333   Expr *Index = InstanceKey;
1334 
1335   // Arguments.
1336   Expr *args[] = { op, Index };
1337 
1338   // Build a message-send.
1339   ExprResult msg = S.ObjC().BuildInstanceMessageImplicit(
1340       InstanceBase, receiverType, GenericLoc, AtIndexSetterSelector,
1341       AtIndexSetter, MultiExprArg(args, 2));
1342 
1343   if (!msg.isInvalid() && captureSetValueAsResult) {
1344     ObjCMessageExpr *msgExpr =
1345       cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit());
1346     Expr *arg = msgExpr->getArg(0);
1347     if (CanCaptureValue(arg))
1348       msgExpr->setArg(0, captureValueAsResult(arg));
1349   }
1350 
1351   return msg;
1352 }
1353 
1354 //===----------------------------------------------------------------------===//
1355 //  MSVC __declspec(property) references
1356 //===----------------------------------------------------------------------===//
1357 
1358 MSPropertyRefExpr *
getBaseMSProperty(MSPropertySubscriptExpr * E)1359 MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) {
1360   CallArgs.insert(CallArgs.begin(), E->getIdx());
1361   Expr *Base = E->getBase()->IgnoreParens();
1362   while (auto *MSPropSubscript = dyn_cast<MSPropertySubscriptExpr>(Base)) {
1363     CallArgs.insert(CallArgs.begin(), MSPropSubscript->getIdx());
1364     Base = MSPropSubscript->getBase()->IgnoreParens();
1365   }
1366   return cast<MSPropertyRefExpr>(Base);
1367 }
1368 
rebuildAndCaptureObject(Expr * syntacticBase)1369 Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) {
1370   InstanceBase = capture(RefExpr->getBaseExpr());
1371   for (Expr *&Arg : CallArgs)
1372     Arg = capture(Arg);
1373   syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * {
1374                     switch (Idx) {
1375                     case 0:
1376                       return InstanceBase;
1377                     default:
1378                       assert(Idx <= CallArgs.size());
1379                       return CallArgs[Idx - 1];
1380                     }
1381                   }).rebuild(syntacticBase);
1382 
1383   return syntacticBase;
1384 }
1385 
buildGet()1386 ExprResult MSPropertyOpBuilder::buildGet() {
1387   if (!RefExpr->getPropertyDecl()->hasGetter()) {
1388     S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
1389       << 0 /* getter */ << RefExpr->getPropertyDecl();
1390     return ExprError();
1391   }
1392 
1393   UnqualifiedId GetterName;
1394   const IdentifierInfo *II = RefExpr->getPropertyDecl()->getGetterId();
1395   GetterName.setIdentifier(II, RefExpr->getMemberLoc());
1396   CXXScopeSpec SS;
1397   SS.Adopt(RefExpr->getQualifierLoc());
1398   ExprResult GetterExpr =
1399       S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
1400                               RefExpr->isArrow() ? tok::arrow : tok::period, SS,
1401                               SourceLocation(), GetterName, nullptr);
1402   if (GetterExpr.isInvalid()) {
1403     S.Diag(RefExpr->getMemberLoc(),
1404            diag::err_cannot_find_suitable_accessor) << 0 /* getter */
1405       << RefExpr->getPropertyDecl();
1406     return ExprError();
1407   }
1408 
1409   return S.BuildCallExpr(S.getCurScope(), GetterExpr.get(),
1410                          RefExpr->getSourceRange().getBegin(), CallArgs,
1411                          RefExpr->getSourceRange().getEnd());
1412 }
1413 
buildSet(Expr * op,SourceLocation sl,bool captureSetValueAsResult)1414 ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
1415                                          bool captureSetValueAsResult) {
1416   if (!RefExpr->getPropertyDecl()->hasSetter()) {
1417     S.Diag(RefExpr->getMemberLoc(), diag::err_no_accessor_for_property)
1418       << 1 /* setter */ << RefExpr->getPropertyDecl();
1419     return ExprError();
1420   }
1421 
1422   UnqualifiedId SetterName;
1423   const IdentifierInfo *II = RefExpr->getPropertyDecl()->getSetterId();
1424   SetterName.setIdentifier(II, RefExpr->getMemberLoc());
1425   CXXScopeSpec SS;
1426   SS.Adopt(RefExpr->getQualifierLoc());
1427   ExprResult SetterExpr =
1428       S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
1429                               RefExpr->isArrow() ? tok::arrow : tok::period, SS,
1430                               SourceLocation(), SetterName, nullptr);
1431   if (SetterExpr.isInvalid()) {
1432     S.Diag(RefExpr->getMemberLoc(),
1433            diag::err_cannot_find_suitable_accessor) << 1 /* setter */
1434       << RefExpr->getPropertyDecl();
1435     return ExprError();
1436   }
1437 
1438   SmallVector<Expr*, 4> ArgExprs;
1439   ArgExprs.append(CallArgs.begin(), CallArgs.end());
1440   ArgExprs.push_back(op);
1441   return S.BuildCallExpr(S.getCurScope(), SetterExpr.get(),
1442                          RefExpr->getSourceRange().getBegin(), ArgExprs,
1443                          op->getSourceRange().getEnd());
1444 }
1445 
1446 //===----------------------------------------------------------------------===//
1447 //  General Sema routines.
1448 //===----------------------------------------------------------------------===//
1449 
checkRValue(Expr * E)1450 ExprResult SemaPseudoObject::checkRValue(Expr *E) {
1451   Expr *opaqueRef = E->IgnoreParens();
1452   if (ObjCPropertyRefExpr *refExpr
1453         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1454     ObjCPropertyOpBuilder builder(SemaRef, refExpr, true);
1455     return builder.buildRValueOperation(E);
1456   }
1457   else if (ObjCSubscriptRefExpr *refExpr
1458            = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1459     ObjCSubscriptOpBuilder builder(SemaRef, refExpr, true);
1460     return builder.buildRValueOperation(E);
1461   } else if (MSPropertyRefExpr *refExpr
1462              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
1463     MSPropertyOpBuilder builder(SemaRef, refExpr, true);
1464     return builder.buildRValueOperation(E);
1465   } else if (MSPropertySubscriptExpr *RefExpr =
1466                  dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
1467     MSPropertyOpBuilder Builder(SemaRef, RefExpr, true);
1468     return Builder.buildRValueOperation(E);
1469   } else {
1470     llvm_unreachable("unknown pseudo-object kind!");
1471   }
1472 }
1473 
1474 /// Check an increment or decrement of a pseudo-object expression.
checkIncDec(Scope * Sc,SourceLocation opcLoc,UnaryOperatorKind opcode,Expr * op)1475 ExprResult SemaPseudoObject::checkIncDec(Scope *Sc, SourceLocation opcLoc,
1476                                          UnaryOperatorKind opcode, Expr *op) {
1477   // Do nothing if the operand is dependent.
1478   if (op->isTypeDependent())
1479     return UnaryOperator::Create(
1480         SemaRef.Context, op, opcode, SemaRef.Context.DependentTy, VK_PRValue,
1481         OK_Ordinary, opcLoc, false, SemaRef.CurFPFeatureOverrides());
1482 
1483   assert(UnaryOperator::isIncrementDecrementOp(opcode));
1484   Expr *opaqueRef = op->IgnoreParens();
1485   if (ObjCPropertyRefExpr *refExpr
1486         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1487     ObjCPropertyOpBuilder builder(SemaRef, refExpr, false);
1488     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1489   } else if (isa<ObjCSubscriptRefExpr>(opaqueRef)) {
1490     Diag(opcLoc, diag::err_illegal_container_subscripting_op);
1491     return ExprError();
1492   } else if (MSPropertyRefExpr *refExpr
1493              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
1494     MSPropertyOpBuilder builder(SemaRef, refExpr, false);
1495     return builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1496   } else if (MSPropertySubscriptExpr *RefExpr
1497              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
1498     MSPropertyOpBuilder Builder(SemaRef, RefExpr, false);
1499     return Builder.buildIncDecOperation(Sc, opcLoc, opcode, op);
1500   } else {
1501     llvm_unreachable("unknown pseudo-object kind!");
1502   }
1503 }
1504 
checkAssignment(Scope * S,SourceLocation opcLoc,BinaryOperatorKind opcode,Expr * LHS,Expr * RHS)1505 ExprResult SemaPseudoObject::checkAssignment(Scope *S, SourceLocation opcLoc,
1506                                              BinaryOperatorKind opcode,
1507                                              Expr *LHS, Expr *RHS) {
1508   // Do nothing if either argument is dependent.
1509   if (LHS->isTypeDependent() || RHS->isTypeDependent())
1510     return BinaryOperator::Create(
1511         SemaRef.Context, LHS, RHS, opcode, SemaRef.Context.DependentTy,
1512         VK_PRValue, OK_Ordinary, opcLoc, SemaRef.CurFPFeatureOverrides());
1513 
1514   // Filter out non-overload placeholder types in the RHS.
1515   if (RHS->getType()->isNonOverloadPlaceholderType()) {
1516     ExprResult result = SemaRef.CheckPlaceholderExpr(RHS);
1517     if (result.isInvalid()) return ExprError();
1518     RHS = result.get();
1519   }
1520 
1521   bool IsSimpleAssign = opcode == BO_Assign;
1522   Expr *opaqueRef = LHS->IgnoreParens();
1523   if (ObjCPropertyRefExpr *refExpr
1524         = dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
1525     ObjCPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);
1526     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1527   } else if (ObjCSubscriptRefExpr *refExpr
1528              = dyn_cast<ObjCSubscriptRefExpr>(opaqueRef)) {
1529     ObjCSubscriptOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);
1530     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1531   } else if (MSPropertyRefExpr *refExpr
1532              = dyn_cast<MSPropertyRefExpr>(opaqueRef)) {
1533     MSPropertyOpBuilder builder(SemaRef, refExpr, IsSimpleAssign);
1534     return builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1535   } else if (MSPropertySubscriptExpr *RefExpr
1536              = dyn_cast<MSPropertySubscriptExpr>(opaqueRef)) {
1537     MSPropertyOpBuilder Builder(SemaRef, RefExpr, IsSimpleAssign);
1538     return Builder.buildAssignmentOperation(S, opcLoc, opcode, LHS, RHS);
1539   } else {
1540     llvm_unreachable("unknown pseudo-object kind!");
1541   }
1542 }
1543 
1544 /// Given a pseudo-object reference, rebuild it without the opaque
1545 /// values.  Basically, undo the behavior of rebuildAndCaptureObject.
1546 /// This should never operate in-place.
stripOpaqueValuesFromPseudoObjectRef(Sema & S,Expr * E)1547 static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
1548   return Rebuilder(S,
1549                    [=](Expr *E, unsigned) -> Expr * {
1550                      return cast<OpaqueValueExpr>(E)->getSourceExpr();
1551                    })
1552       .rebuild(E);
1553 }
1554 
1555 /// Given a pseudo-object expression, recreate what it looks like
1556 /// syntactically without the attendant OpaqueValueExprs.
1557 ///
1558 /// This is a hack which should be removed when TreeTransform is
1559 /// capable of rebuilding a tree without stripping implicit
1560 /// operations.
recreateSyntacticForm(PseudoObjectExpr * E)1561 Expr *SemaPseudoObject::recreateSyntacticForm(PseudoObjectExpr *E) {
1562   Expr *syntax = E->getSyntacticForm();
1563   if (UnaryOperator *uop = dyn_cast<UnaryOperator>(syntax)) {
1564     Expr *op = stripOpaqueValuesFromPseudoObjectRef(SemaRef, uop->getSubExpr());
1565     return UnaryOperator::Create(
1566         SemaRef.Context, op, uop->getOpcode(), uop->getType(),
1567         uop->getValueKind(), uop->getObjectKind(), uop->getOperatorLoc(),
1568         uop->canOverflow(), SemaRef.CurFPFeatureOverrides());
1569   } else if (CompoundAssignOperator *cop
1570                = dyn_cast<CompoundAssignOperator>(syntax)) {
1571     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, cop->getLHS());
1572     Expr *rhs = cast<OpaqueValueExpr>(cop->getRHS())->getSourceExpr();
1573     return CompoundAssignOperator::Create(
1574         SemaRef.Context, lhs, rhs, cop->getOpcode(), cop->getType(),
1575         cop->getValueKind(), cop->getObjectKind(), cop->getOperatorLoc(),
1576         SemaRef.CurFPFeatureOverrides(), cop->getComputationLHSType(),
1577         cop->getComputationResultType());
1578 
1579   } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) {
1580     Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(SemaRef, bop->getLHS());
1581     Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr();
1582     return BinaryOperator::Create(SemaRef.Context, lhs, rhs, bop->getOpcode(),
1583                                   bop->getType(), bop->getValueKind(),
1584                                   bop->getObjectKind(), bop->getOperatorLoc(),
1585                                   SemaRef.CurFPFeatureOverrides());
1586 
1587   } else if (isa<CallExpr>(syntax)) {
1588     return syntax;
1589   } else {
1590     assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject));
1591     return stripOpaqueValuesFromPseudoObjectRef(SemaRef, syntax);
1592   }
1593 }
1594 
SemaPseudoObject(Sema & S)1595 SemaPseudoObject::SemaPseudoObject(Sema &S) : SemaBase(S) {}
1596