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