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