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