/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/ExprObjC.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ExprObjC.h - Classes for representing ObjC expressions ---*- C++ -*-===// |
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 defines the ExprObjC interface and subclasses. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef LLVM_CLANG_AST_EXPROBJC_H |
14 | | #define LLVM_CLANG_AST_EXPROBJC_H |
15 | | |
16 | | #include "clang/AST/ComputeDependence.h" |
17 | | #include "clang/AST/Decl.h" |
18 | | #include "clang/AST/DeclObjC.h" |
19 | | #include "clang/AST/DependenceFlags.h" |
20 | | #include "clang/AST/Expr.h" |
21 | | #include "clang/AST/OperationKinds.h" |
22 | | #include "clang/AST/SelectorLocationsKind.h" |
23 | | #include "clang/AST/Stmt.h" |
24 | | #include "clang/AST/Type.h" |
25 | | #include "clang/Basic/IdentifierTable.h" |
26 | | #include "clang/Basic/LLVM.h" |
27 | | #include "clang/Basic/SourceLocation.h" |
28 | | #include "clang/Basic/Specifiers.h" |
29 | | #include "llvm/ADT/ArrayRef.h" |
30 | | #include "llvm/ADT/None.h" |
31 | | #include "llvm/ADT/Optional.h" |
32 | | #include "llvm/ADT/PointerIntPair.h" |
33 | | #include "llvm/ADT/PointerUnion.h" |
34 | | #include "llvm/ADT/StringRef.h" |
35 | | #include "llvm/ADT/iterator_range.h" |
36 | | #include "llvm/Support/Casting.h" |
37 | | #include "llvm/Support/Compiler.h" |
38 | | #include "llvm/Support/TrailingObjects.h" |
39 | | #include "llvm/Support/VersionTuple.h" |
40 | | #include "llvm/Support/type_traits.h" |
41 | | #include <cassert> |
42 | | #include <cstddef> |
43 | | #include <cstdint> |
44 | | |
45 | | namespace clang { |
46 | | |
47 | | class ASTContext; |
48 | | class CXXBaseSpecifier; |
49 | | |
50 | | /// ObjCStringLiteral, used for Objective-C string literals |
51 | | /// i.e. @"foo". |
52 | | class ObjCStringLiteral : public Expr { |
53 | | Stmt *String; |
54 | | SourceLocation AtLoc; |
55 | | |
56 | | public: |
57 | | ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L) |
58 | | : Expr(ObjCStringLiteralClass, T, VK_PRValue, OK_Ordinary), String(SL), |
59 | 6.17k | AtLoc(L) { |
60 | 6.17k | setDependence(ExprDependence::None); |
61 | 6.17k | } |
62 | | explicit ObjCStringLiteral(EmptyShell Empty) |
63 | 10 | : Expr(ObjCStringLiteralClass, Empty) {} |
64 | | |
65 | 1.21k | StringLiteral *getString() { return cast<StringLiteral>(String); } |
66 | 6.84k | const StringLiteral *getString() const { return cast<StringLiteral>(String); } |
67 | 10 | void setString(StringLiteral *S) { String = S; } |
68 | | |
69 | 7 | SourceLocation getAtLoc() const { return AtLoc; } |
70 | 10 | void setAtLoc(SourceLocation L) { AtLoc = L; } |
71 | | |
72 | 72.2k | SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } |
73 | 4.84k | SourceLocation getEndLoc() const LLVM_READONLY { return String->getEndLoc(); } |
74 | | |
75 | | // Iterators |
76 | 16.2k | child_range children() { return child_range(&String, &String+1); } |
77 | | |
78 | 0 | const_child_range children() const { |
79 | 0 | return const_child_range(&String, &String + 1); |
80 | 0 | } |
81 | | |
82 | 235k | static bool classof(const Stmt *T) { |
83 | 235k | return T->getStmtClass() == ObjCStringLiteralClass; |
84 | 235k | } |
85 | | }; |
86 | | |
87 | | /// ObjCBoolLiteralExpr - Objective-C Boolean Literal. |
88 | | class ObjCBoolLiteralExpr : public Expr { |
89 | | bool Value; |
90 | | SourceLocation Loc; |
91 | | |
92 | | public: |
93 | | ObjCBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) |
94 | | : Expr(ObjCBoolLiteralExprClass, Ty, VK_PRValue, OK_Ordinary), Value(val), |
95 | 959 | Loc(l) { |
96 | 959 | setDependence(ExprDependence::None); |
97 | 959 | } |
98 | | explicit ObjCBoolLiteralExpr(EmptyShell Empty) |
99 | 0 | : Expr(ObjCBoolLiteralExprClass, Empty) {} |
100 | | |
101 | 1.09k | bool getValue() const { return Value; } |
102 | 0 | void setValue(bool V) { Value = V; } |
103 | | |
104 | 8.49k | SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
105 | 352 | SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } |
106 | | |
107 | 60 | SourceLocation getLocation() const { return Loc; } |
108 | 0 | void setLocation(SourceLocation L) { Loc = L; } |
109 | | |
110 | | // Iterators |
111 | 2.40k | child_range children() { |
112 | 2.40k | return child_range(child_iterator(), child_iterator()); |
113 | 2.40k | } |
114 | | |
115 | 0 | const_child_range children() const { |
116 | 0 | return const_child_range(const_child_iterator(), const_child_iterator()); |
117 | 0 | } |
118 | | |
119 | 388k | static bool classof(const Stmt *T) { |
120 | 388k | return T->getStmtClass() == ObjCBoolLiteralExprClass; |
121 | 388k | } |
122 | | }; |
123 | | |
124 | | /// ObjCBoxedExpr - used for generalized expression boxing. |
125 | | /// as in: @(strdup("hello world")), @(random()) or @(view.frame) |
126 | | /// Also used for boxing non-parenthesized numeric literals; |
127 | | /// as in: @42 or \@true (c++/objc++) or \@__objc_yes (c/objc). |
128 | | class ObjCBoxedExpr : public Expr { |
129 | | Stmt *SubExpr; |
130 | | ObjCMethodDecl *BoxingMethod; |
131 | | SourceRange Range; |
132 | | |
133 | | public: |
134 | | friend class ASTStmtReader; |
135 | | |
136 | | ObjCBoxedExpr(Expr *E, QualType T, ObjCMethodDecl *method, SourceRange R) |
137 | | : Expr(ObjCBoxedExprClass, T, VK_PRValue, OK_Ordinary), SubExpr(E), |
138 | 1.31k | BoxingMethod(method), Range(R) { |
139 | 1.31k | setDependence(computeDependence(this)); |
140 | 1.31k | } |
141 | | explicit ObjCBoxedExpr(EmptyShell Empty) |
142 | 26 | : Expr(ObjCBoxedExprClass, Empty) {} |
143 | | |
144 | 1.56k | Expr *getSubExpr() { return cast<Expr>(SubExpr); } |
145 | 1.54k | const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } |
146 | | |
147 | 876 | ObjCMethodDecl *getBoxingMethod() const { |
148 | 876 | return BoxingMethod; |
149 | 876 | } |
150 | | |
151 | | // Indicates whether this boxed expression can be emitted as a compile-time |
152 | | // constant. |
153 | 1.62k | bool isExpressibleAsConstantInitializer() const { |
154 | 1.62k | return !BoxingMethod && SubExpr24 ; |
155 | 1.62k | } |
156 | | |
157 | 0 | SourceLocation getAtLoc() const { return Range.getBegin(); } |
158 | | |
159 | 9.22k | SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } |
160 | 271 | SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } |
161 | | |
162 | 732 | SourceRange getSourceRange() const LLVM_READONLY { |
163 | 732 | return Range; |
164 | 732 | } |
165 | | |
166 | | // Iterators |
167 | 3.48k | child_range children() { return child_range(&SubExpr, &SubExpr+1); } |
168 | | |
169 | 0 | const_child_range children() const { |
170 | 0 | return const_child_range(&SubExpr, &SubExpr + 1); |
171 | 0 | } |
172 | | |
173 | | using const_arg_iterator = ConstExprIterator; |
174 | | |
175 | 0 | const_arg_iterator arg_begin() const { |
176 | 0 | return reinterpret_cast<Stmt const * const*>(&SubExpr); |
177 | 0 | } |
178 | | |
179 | 0 | const_arg_iterator arg_end() const { |
180 | 0 | return reinterpret_cast<Stmt const * const*>(&SubExpr + 1); |
181 | 0 | } |
182 | | |
183 | 10.1M | static bool classof(const Stmt *T) { |
184 | 10.1M | return T->getStmtClass() == ObjCBoxedExprClass; |
185 | 10.1M | } |
186 | | }; |
187 | | |
188 | | /// ObjCArrayLiteral - used for objective-c array containers; as in: |
189 | | /// @[@"Hello", NSApp, [NSNumber numberWithInt:42]]; |
190 | | class ObjCArrayLiteral final |
191 | | : public Expr, |
192 | | private llvm::TrailingObjects<ObjCArrayLiteral, Expr *> { |
193 | | unsigned NumElements; |
194 | | SourceRange Range; |
195 | | ObjCMethodDecl *ArrayWithObjectsMethod; |
196 | | |
197 | | ObjCArrayLiteral(ArrayRef<Expr *> Elements, |
198 | | QualType T, ObjCMethodDecl * Method, |
199 | | SourceRange SR); |
200 | | |
201 | | explicit ObjCArrayLiteral(EmptyShell Empty, unsigned NumElements) |
202 | 4 | : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} |
203 | | |
204 | | public: |
205 | | friend class ASTStmtReader; |
206 | | friend TrailingObjects; |
207 | | |
208 | | static ObjCArrayLiteral *Create(const ASTContext &C, |
209 | | ArrayRef<Expr *> Elements, |
210 | | QualType T, ObjCMethodDecl * Method, |
211 | | SourceRange SR); |
212 | | |
213 | | static ObjCArrayLiteral *CreateEmpty(const ASTContext &C, |
214 | | unsigned NumElements); |
215 | | |
216 | 2.07k | SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } |
217 | 104 | SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } |
218 | 440 | SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
219 | | |
220 | | /// Retrieve elements of array of literals. |
221 | 2.64k | Expr **getElements() { return getTrailingObjects<Expr *>(); } |
222 | | |
223 | | /// Retrieve elements of array of literals. |
224 | 300 | const Expr * const *getElements() const { |
225 | 300 | return getTrailingObjects<Expr *>(); |
226 | 300 | } |
227 | | |
228 | | /// getNumElements - Return number of elements of objective-c array literal. |
229 | 484 | unsigned getNumElements() const { return NumElements; } |
230 | | |
231 | | /// getElement - Return the Element at the specified index. |
232 | 41 | Expr *getElement(unsigned Index) { |
233 | 41 | assert((Index < NumElements) && "Arg access out of range!"); |
234 | 0 | return getElements()[Index]; |
235 | 41 | } |
236 | 300 | const Expr *getElement(unsigned Index) const { |
237 | 300 | assert((Index < NumElements) && "Arg access out of range!"); |
238 | 0 | return getElements()[Index]; |
239 | 300 | } |
240 | | |
241 | 163 | ObjCMethodDecl *getArrayWithObjectsMethod() const { |
242 | 163 | return ArrayWithObjectsMethod; |
243 | 163 | } |
244 | | |
245 | | // Iterators |
246 | 1.01k | child_range children() { |
247 | 1.01k | return child_range(reinterpret_cast<Stmt **>(getElements()), |
248 | 1.01k | reinterpret_cast<Stmt **>(getElements()) + NumElements); |
249 | 1.01k | } |
250 | | |
251 | 0 | const_child_range children() const { |
252 | 0 | auto Children = const_cast<ObjCArrayLiteral *>(this)->children(); |
253 | 0 | return const_child_range(Children.begin(), Children.end()); |
254 | 0 | } |
255 | | |
256 | 5.65M | static bool classof(const Stmt *T) { |
257 | 5.65M | return T->getStmtClass() == ObjCArrayLiteralClass; |
258 | 5.65M | } |
259 | | }; |
260 | | |
261 | | /// An element in an Objective-C dictionary literal. |
262 | | /// |
263 | | struct ObjCDictionaryElement { |
264 | | /// The key for the dictionary element. |
265 | | Expr *Key; |
266 | | |
267 | | /// The value of the dictionary element. |
268 | | Expr *Value; |
269 | | |
270 | | /// The location of the ellipsis, if this is a pack expansion. |
271 | | SourceLocation EllipsisLoc; |
272 | | |
273 | | /// The number of elements this pack expansion will expand to, if |
274 | | /// this is a pack expansion and is known. |
275 | | Optional<unsigned> NumExpansions; |
276 | | |
277 | | /// Determines whether this dictionary element is a pack expansion. |
278 | 28 | bool isPackExpansion() const { return EllipsisLoc.isValid(); } |
279 | | }; |
280 | | |
281 | | } // namespace clang |
282 | | |
283 | | namespace clang { |
284 | | |
285 | | /// Internal struct for storing Key/value pair. |
286 | | struct ObjCDictionaryLiteral_KeyValuePair { |
287 | | Expr *Key; |
288 | | Expr *Value; |
289 | | }; |
290 | | |
291 | | /// Internal struct to describes an element that is a pack |
292 | | /// expansion, used if any of the elements in the dictionary literal |
293 | | /// are pack expansions. |
294 | | struct ObjCDictionaryLiteral_ExpansionData { |
295 | | /// The location of the ellipsis, if this element is a pack |
296 | | /// expansion. |
297 | | SourceLocation EllipsisLoc; |
298 | | |
299 | | /// If non-zero, the number of elements that this pack |
300 | | /// expansion will expand to (+1). |
301 | | unsigned NumExpansionsPlusOne; |
302 | | }; |
303 | | |
304 | | /// ObjCDictionaryLiteral - AST node to represent objective-c dictionary |
305 | | /// literals; as in: @{@"name" : NSUserName(), @"date" : [NSDate date] }; |
306 | | class ObjCDictionaryLiteral final |
307 | | : public Expr, |
308 | | private llvm::TrailingObjects<ObjCDictionaryLiteral, |
309 | | ObjCDictionaryLiteral_KeyValuePair, |
310 | | ObjCDictionaryLiteral_ExpansionData> { |
311 | | /// The number of elements in this dictionary literal. |
312 | | unsigned NumElements : 31; |
313 | | |
314 | | /// Determine whether this dictionary literal has any pack expansions. |
315 | | /// |
316 | | /// If the dictionary literal has pack expansions, then there will |
317 | | /// be an array of pack expansion data following the array of |
318 | | /// key/value pairs, which provide the locations of the ellipses (if |
319 | | /// any) and number of elements in the expansion (if known). If |
320 | | /// there are no pack expansions, we optimize away this storage. |
321 | | unsigned HasPackExpansions : 1; |
322 | | |
323 | | SourceRange Range; |
324 | | ObjCMethodDecl *DictWithObjectsMethod; |
325 | | |
326 | | using KeyValuePair = ObjCDictionaryLiteral_KeyValuePair; |
327 | | using ExpansionData = ObjCDictionaryLiteral_ExpansionData; |
328 | | |
329 | | ObjCDictionaryLiteral(ArrayRef<ObjCDictionaryElement> VK, |
330 | | bool HasPackExpansions, |
331 | | QualType T, ObjCMethodDecl *method, |
332 | | SourceRange SR); |
333 | | |
334 | | explicit ObjCDictionaryLiteral(EmptyShell Empty, unsigned NumElements, |
335 | | bool HasPackExpansions) |
336 | | : Expr(ObjCDictionaryLiteralClass, Empty), NumElements(NumElements), |
337 | 7 | HasPackExpansions(HasPackExpansions) {} |
338 | | |
339 | 32 | size_t numTrailingObjects(OverloadToken<KeyValuePair>) const { |
340 | 32 | return NumElements; |
341 | 32 | } |
342 | | |
343 | | public: |
344 | | friend class ASTStmtReader; |
345 | | friend class ASTStmtWriter; |
346 | | friend TrailingObjects; |
347 | | |
348 | | static ObjCDictionaryLiteral *Create(const ASTContext &C, |
349 | | ArrayRef<ObjCDictionaryElement> VK, |
350 | | bool HasPackExpansions, |
351 | | QualType T, ObjCMethodDecl *method, |
352 | | SourceRange SR); |
353 | | |
354 | | static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C, |
355 | | unsigned NumElements, |
356 | | bool HasPackExpansions); |
357 | | |
358 | | /// getNumElements - Return number of elements of objective-c dictionary |
359 | | /// literal. |
360 | 600 | unsigned getNumElements() const { return NumElements; } |
361 | | |
362 | 1.02k | ObjCDictionaryElement getKeyValueElement(unsigned Index) const { |
363 | 1.02k | assert((Index < NumElements) && "Arg access out of range!"); |
364 | 0 | const KeyValuePair &KV = getTrailingObjects<KeyValuePair>()[Index]; |
365 | 1.02k | ObjCDictionaryElement Result = { KV.Key, KV.Value, SourceLocation(), None }; |
366 | 1.02k | if (HasPackExpansions) { |
367 | 22 | const ExpansionData &Expansion = |
368 | 22 | getTrailingObjects<ExpansionData>()[Index]; |
369 | 22 | Result.EllipsisLoc = Expansion.EllipsisLoc; |
370 | 22 | if (Expansion.NumExpansionsPlusOne > 0) |
371 | 0 | Result.NumExpansions = Expansion.NumExpansionsPlusOne - 1; |
372 | 22 | } |
373 | 1.02k | return Result; |
374 | 1.02k | } |
375 | | |
376 | 139 | ObjCMethodDecl *getDictWithObjectsMethod() const { |
377 | 139 | return DictWithObjectsMethod; |
378 | 139 | } |
379 | | |
380 | 1.40k | SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } |
381 | 69 | SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } |
382 | 176 | SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
383 | | |
384 | | // Iterators |
385 | 634 | child_range children() { |
386 | | // Note: we're taking advantage of the layout of the KeyValuePair struct |
387 | | // here. If that struct changes, this code will need to change as well. |
388 | 634 | static_assert(sizeof(KeyValuePair) == sizeof(Stmt *) * 2, |
389 | 634 | "KeyValuePair is expected size"); |
390 | 634 | return child_range( |
391 | 634 | reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()), |
392 | 634 | reinterpret_cast<Stmt **>(getTrailingObjects<KeyValuePair>()) + |
393 | 634 | NumElements * 2); |
394 | 634 | } |
395 | | |
396 | 0 | const_child_range children() const { |
397 | 0 | auto Children = const_cast<ObjCDictionaryLiteral *>(this)->children(); |
398 | 0 | return const_child_range(Children.begin(), Children.end()); |
399 | 0 | } |
400 | | |
401 | 5.65M | static bool classof(const Stmt *T) { |
402 | 5.65M | return T->getStmtClass() == ObjCDictionaryLiteralClass; |
403 | 5.65M | } |
404 | | }; |
405 | | |
406 | | /// ObjCEncodeExpr, used for \@encode in Objective-C. \@encode has the same |
407 | | /// type and behavior as StringLiteral except that the string initializer is |
408 | | /// obtained from ASTContext with the encoding type as an argument. |
409 | | class ObjCEncodeExpr : public Expr { |
410 | | TypeSourceInfo *EncodedType; |
411 | | SourceLocation AtLoc, RParenLoc; |
412 | | |
413 | | public: |
414 | | ObjCEncodeExpr(QualType T, TypeSourceInfo *EncodedType, SourceLocation at, |
415 | | SourceLocation rp) |
416 | | : Expr(ObjCEncodeExprClass, T, VK_LValue, OK_Ordinary), |
417 | 204 | EncodedType(EncodedType), AtLoc(at), RParenLoc(rp) { |
418 | 204 | setDependence(computeDependence(this)); |
419 | 204 | } |
420 | | |
421 | 1 | explicit ObjCEncodeExpr(EmptyShell Empty) : Expr(ObjCEncodeExprClass, Empty){} |
422 | | |
423 | 4 | SourceLocation getAtLoc() const { return AtLoc; } |
424 | 1 | void setAtLoc(SourceLocation L) { AtLoc = L; } |
425 | 4 | SourceLocation getRParenLoc() const { return RParenLoc; } |
426 | 1 | void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
427 | | |
428 | 353 | QualType getEncodedType() const { return EncodedType->getType(); } |
429 | | |
430 | 10 | TypeSourceInfo *getEncodedTypeSourceInfo() const { return EncodedType; } |
431 | | |
432 | 1 | void setEncodedTypeSourceInfo(TypeSourceInfo *EncType) { |
433 | 1 | EncodedType = EncType; |
434 | 1 | } |
435 | | |
436 | 1.17k | SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } |
437 | 95 | SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
438 | | |
439 | | // Iterators |
440 | 518 | child_range children() { |
441 | 518 | return child_range(child_iterator(), child_iterator()); |
442 | 518 | } |
443 | | |
444 | 0 | const_child_range children() const { |
445 | 0 | return const_child_range(const_child_iterator(), const_child_iterator()); |
446 | 0 | } |
447 | | |
448 | 1.41M | static bool classof(const Stmt *T) { |
449 | 1.41M | return T->getStmtClass() == ObjCEncodeExprClass; |
450 | 1.41M | } |
451 | | }; |
452 | | |
453 | | /// ObjCSelectorExpr used for \@selector in Objective-C. |
454 | | class ObjCSelectorExpr : public Expr { |
455 | | Selector SelName; |
456 | | SourceLocation AtLoc, RParenLoc; |
457 | | |
458 | | public: |
459 | | ObjCSelectorExpr(QualType T, Selector selInfo, SourceLocation at, |
460 | | SourceLocation rp) |
461 | | : Expr(ObjCSelectorExprClass, T, VK_PRValue, OK_Ordinary), |
462 | 402 | SelName(selInfo), AtLoc(at), RParenLoc(rp) { |
463 | 402 | setDependence(ExprDependence::None); |
464 | 402 | } |
465 | | explicit ObjCSelectorExpr(EmptyShell Empty) |
466 | 3 | : Expr(ObjCSelectorExprClass, Empty) {} |
467 | | |
468 | 191 | Selector getSelector() const { return SelName; } |
469 | 3 | void setSelector(Selector S) { SelName = S; } |
470 | | |
471 | 23 | SourceLocation getAtLoc() const { return AtLoc; } |
472 | 15 | SourceLocation getRParenLoc() const { return RParenLoc; } |
473 | 3 | void setAtLoc(SourceLocation L) { AtLoc = L; } |
474 | 3 | void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
475 | | |
476 | 1.65k | SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } |
477 | 245 | SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
478 | | |
479 | | /// getNumArgs - Return the number of actual arguments to this call. |
480 | 0 | unsigned getNumArgs() const { return SelName.getNumArgs(); } |
481 | | |
482 | | // Iterators |
483 | 1.22k | child_range children() { |
484 | 1.22k | return child_range(child_iterator(), child_iterator()); |
485 | 1.22k | } |
486 | | |
487 | 0 | const_child_range children() const { |
488 | 0 | return const_child_range(const_child_iterator(), const_child_iterator()); |
489 | 0 | } |
490 | | |
491 | 888k | static bool classof(const Stmt *T) { |
492 | 888k | return T->getStmtClass() == ObjCSelectorExprClass; |
493 | 888k | } |
494 | | }; |
495 | | |
496 | | /// ObjCProtocolExpr used for protocol expression in Objective-C. |
497 | | /// |
498 | | /// This is used as: \@protocol(foo), as in: |
499 | | /// \code |
500 | | /// [obj conformsToProtocol:@protocol(foo)] |
501 | | /// \endcode |
502 | | /// |
503 | | /// The return type is "Protocol*". |
504 | | class ObjCProtocolExpr : public Expr { |
505 | | ObjCProtocolDecl *TheProtocol; |
506 | | SourceLocation AtLoc, ProtoLoc, RParenLoc; |
507 | | |
508 | | public: |
509 | | friend class ASTStmtReader; |
510 | | friend class ASTStmtWriter; |
511 | | |
512 | | ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol, SourceLocation at, |
513 | | SourceLocation protoLoc, SourceLocation rp) |
514 | | : Expr(ObjCProtocolExprClass, T, VK_PRValue, OK_Ordinary), |
515 | 39 | TheProtocol(protocol), AtLoc(at), ProtoLoc(protoLoc), RParenLoc(rp) { |
516 | 39 | setDependence(ExprDependence::None); |
517 | 39 | } |
518 | | explicit ObjCProtocolExpr(EmptyShell Empty) |
519 | 1 | : Expr(ObjCProtocolExprClass, Empty) {} |
520 | | |
521 | 36 | ObjCProtocolDecl *getProtocol() const { return TheProtocol; } |
522 | 1 | void setProtocol(ObjCProtocolDecl *P) { TheProtocol = P; } |
523 | | |
524 | 1 | SourceLocation getProtocolIdLoc() const { return ProtoLoc; } |
525 | 1 | SourceLocation getAtLoc() const { return AtLoc; } |
526 | 1 | SourceLocation getRParenLoc() const { return RParenLoc; } |
527 | 1 | void setAtLoc(SourceLocation L) { AtLoc = L; } |
528 | 1 | void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
529 | | |
530 | 246 | SourceLocation getBeginLoc() const LLVM_READONLY { return AtLoc; } |
531 | 49 | SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
532 | | |
533 | | // Iterators |
534 | 112 | child_range children() { |
535 | 112 | return child_range(child_iterator(), child_iterator()); |
536 | 112 | } |
537 | | |
538 | 0 | const_child_range children() const { |
539 | 0 | return const_child_range(const_child_iterator(), const_child_iterator()); |
540 | 0 | } |
541 | | |
542 | 13.9k | static bool classof(const Stmt *T) { |
543 | 13.9k | return T->getStmtClass() == ObjCProtocolExprClass; |
544 | 13.9k | } |
545 | | }; |
546 | | |
547 | | /// ObjCIvarRefExpr - A reference to an ObjC instance variable. |
548 | | class ObjCIvarRefExpr : public Expr { |
549 | | ObjCIvarDecl *D; |
550 | | Stmt *Base; |
551 | | SourceLocation Loc; |
552 | | |
553 | | /// OpLoc - This is the location of '.' or '->' |
554 | | SourceLocation OpLoc; |
555 | | |
556 | | // True if this is "X->F", false if this is "X.F". |
557 | | bool IsArrow : 1; |
558 | | |
559 | | // True if ivar reference has no base (self assumed). |
560 | | bool IsFreeIvar : 1; |
561 | | |
562 | | public: |
563 | | ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, |
564 | | SourceLocation oploc, Expr *base, bool arrow = false, |
565 | | bool freeIvar = false) |
566 | | : Expr(ObjCIvarRefExprClass, t, VK_LValue, |
567 | | d->isBitField() ? OK_BitField : OK_Ordinary), |
568 | | D(d), Base(base), Loc(l), OpLoc(oploc), IsArrow(arrow), |
569 | 3.40k | IsFreeIvar(freeIvar) { |
570 | 3.40k | setDependence(computeDependence(this)); |
571 | 3.40k | } |
572 | | |
573 | | explicit ObjCIvarRefExpr(EmptyShell Empty) |
574 | 15 | : Expr(ObjCIvarRefExprClass, Empty) {} |
575 | | |
576 | 2.25k | ObjCIvarDecl *getDecl() { return D; } |
577 | 5.84k | const ObjCIvarDecl *getDecl() const { return D; } |
578 | 15 | void setDecl(ObjCIvarDecl *d) { D = d; } |
579 | | |
580 | 13.5k | const Expr *getBase() const { return cast<Expr>(Base); } |
581 | 4.10k | Expr *getBase() { return cast<Expr>(Base); } |
582 | 172 | void setBase(Expr * base) { Base = base; } |
583 | | |
584 | 1.60k | bool isArrow() const { return IsArrow; } |
585 | 32.6k | bool isFreeIvar() const { return IsFreeIvar; } |
586 | 15 | void setIsArrow(bool A) { IsArrow = A; } |
587 | 26 | void setIsFreeIvar(bool A) { IsFreeIvar = A; } |
588 | | |
589 | 47 | SourceLocation getLocation() const { return Loc; } |
590 | 15 | void setLocation(SourceLocation L) { Loc = L; } |
591 | | |
592 | 32.4k | SourceLocation getBeginLoc() const LLVM_READONLY { |
593 | 32.4k | return isFreeIvar() ? Loc21.6k : getBase()->getBeginLoc()10.7k ; |
594 | 32.4k | } |
595 | 5.01k | SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } |
596 | | |
597 | 20 | SourceLocation getOpLoc() const { return OpLoc; } |
598 | 15 | void setOpLoc(SourceLocation L) { OpLoc = L; } |
599 | | |
600 | | // Iterators |
601 | 14.9k | child_range children() { return child_range(&Base, &Base+1); } |
602 | | |
603 | 0 | const_child_range children() const { |
604 | 0 | return const_child_range(&Base, &Base + 1); |
605 | 0 | } |
606 | | |
607 | 37.5M | static bool classof(const Stmt *T) { |
608 | 37.5M | return T->getStmtClass() == ObjCIvarRefExprClass; |
609 | 37.5M | } |
610 | | }; |
611 | | |
612 | | /// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC |
613 | | /// property. |
614 | | class ObjCPropertyRefExpr : public Expr { |
615 | | private: |
616 | | /// If the bool is true, this is an implicit property reference; the |
617 | | /// pointer is an (optional) ObjCMethodDecl and Setter may be set. |
618 | | /// if the bool is false, this is an explicit property reference; |
619 | | /// the pointer is an ObjCPropertyDecl and Setter is always null. |
620 | | llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter; |
621 | | |
622 | | /// Indicates whether the property reference will result in a message |
623 | | /// to the getter, the setter, or both. |
624 | | /// This applies to both implicit and explicit property references. |
625 | | enum MethodRefFlags { |
626 | | MethodRef_None = 0, |
627 | | MethodRef_Getter = 0x1, |
628 | | MethodRef_Setter = 0x2 |
629 | | }; |
630 | | |
631 | | /// Contains the Setter method pointer and MethodRefFlags bit flags. |
632 | | llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags; |
633 | | |
634 | | // FIXME: Maybe we should store the property identifier here, |
635 | | // because it's not rederivable from the other data when there's an |
636 | | // implicit property with no getter (because the 'foo' -> 'setFoo:' |
637 | | // transformation is lossy on the first character). |
638 | | |
639 | | SourceLocation IdLoc; |
640 | | |
641 | | /// When the receiver in property access is 'super', this is |
642 | | /// the location of the 'super' keyword. When it's an interface, |
643 | | /// this is that interface. |
644 | | SourceLocation ReceiverLoc; |
645 | | llvm::PointerUnion<Stmt *, const Type *, ObjCInterfaceDecl *> Receiver; |
646 | | |
647 | | public: |
648 | | ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, |
649 | | ExprObjectKind OK, SourceLocation l, Expr *base) |
650 | | : Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false), |
651 | 3.74k | IdLoc(l), Receiver(base) { |
652 | 3.74k | assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); |
653 | 0 | setDependence(computeDependence(this)); |
654 | 3.74k | } |
655 | | |
656 | | ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t, ExprValueKind VK, |
657 | | ExprObjectKind OK, SourceLocation l, SourceLocation sl, |
658 | | QualType st) |
659 | | : Expr(ObjCPropertyRefExprClass, t, VK, OK), PropertyOrGetter(PD, false), |
660 | 58 | IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) { |
661 | 58 | assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject)); |
662 | 0 | setDependence(computeDependence(this)); |
663 | 58 | } |
664 | | |
665 | | ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, |
666 | | QualType T, ExprValueKind VK, ExprObjectKind OK, |
667 | | SourceLocation IdLoc, Expr *Base) |
668 | | : Expr(ObjCPropertyRefExprClass, T, VK, OK), |
669 | | PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), |
670 | 598 | IdLoc(IdLoc), Receiver(Base) { |
671 | 598 | assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); |
672 | 0 | setDependence(computeDependence(this)); |
673 | 598 | } |
674 | | |
675 | | ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, |
676 | | QualType T, ExprValueKind VK, ExprObjectKind OK, |
677 | | SourceLocation IdLoc, SourceLocation SuperLoc, |
678 | | QualType SuperTy) |
679 | | : Expr(ObjCPropertyRefExprClass, T, VK, OK), |
680 | | PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), |
681 | 17 | IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) { |
682 | 17 | assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); |
683 | 0 | setDependence(computeDependence(this)); |
684 | 17 | } |
685 | | |
686 | | ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, |
687 | | QualType T, ExprValueKind VK, ExprObjectKind OK, |
688 | | SourceLocation IdLoc, SourceLocation ReceiverLoc, |
689 | | ObjCInterfaceDecl *Receiver) |
690 | | : Expr(ObjCPropertyRefExprClass, T, VK, OK), |
691 | | PropertyOrGetter(Getter, true), SetterAndMethodRefFlags(Setter, 0), |
692 | 192 | IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) { |
693 | 192 | assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject)); |
694 | 0 | setDependence(computeDependence(this)); |
695 | 192 | } |
696 | | |
697 | | explicit ObjCPropertyRefExpr(EmptyShell Empty) |
698 | 1 | : Expr(ObjCPropertyRefExprClass, Empty) {} |
699 | | |
700 | 16.6k | bool isImplicitProperty() const { return PropertyOrGetter.getInt(); } |
701 | 8.30k | bool isExplicitProperty() const { return !PropertyOrGetter.getInt(); } |
702 | | |
703 | 9.57k | ObjCPropertyDecl *getExplicitProperty() const { |
704 | 9.57k | assert(!isImplicitProperty()); |
705 | 0 | return cast<ObjCPropertyDecl>(PropertyOrGetter.getPointer()); |
706 | 9.57k | } |
707 | | |
708 | 1.20k | ObjCMethodDecl *getImplicitPropertyGetter() const { |
709 | 1.20k | assert(isImplicitProperty()); |
710 | 0 | return cast_or_null<ObjCMethodDecl>(PropertyOrGetter.getPointer()); |
711 | 1.20k | } |
712 | | |
713 | 570 | ObjCMethodDecl *getImplicitPropertySetter() const { |
714 | 570 | assert(isImplicitProperty()); |
715 | 0 | return SetterAndMethodRefFlags.getPointer(); |
716 | 570 | } |
717 | | |
718 | 0 | Selector getGetterSelector() const { |
719 | 0 | if (isImplicitProperty()) |
720 | 0 | return getImplicitPropertyGetter()->getSelector(); |
721 | 0 | return getExplicitProperty()->getGetterName(); |
722 | 0 | } |
723 | | |
724 | 0 | Selector getSetterSelector() const { |
725 | 0 | if (isImplicitProperty()) |
726 | 0 | return getImplicitPropertySetter()->getSelector(); |
727 | 0 | return getExplicitProperty()->getSetterName(); |
728 | 0 | } |
729 | | |
730 | | /// True if the property reference will result in a message to the |
731 | | /// getter. |
732 | | /// This applies to both implicit and explicit property references. |
733 | 273 | bool isMessagingGetter() const { |
734 | 273 | return SetterAndMethodRefFlags.getInt() & MethodRef_Getter; |
735 | 273 | } |
736 | | |
737 | | /// True if the property reference will result in a message to the |
738 | | /// setter. |
739 | | /// This applies to both implicit and explicit property references. |
740 | 13 | bool isMessagingSetter() const { |
741 | 13 | return SetterAndMethodRefFlags.getInt() & MethodRef_Setter; |
742 | 13 | } |
743 | | |
744 | 1.62k | void setIsMessagingGetter(bool val = true) { |
745 | 1.62k | setMethodRefFlag(MethodRef_Getter, val); |
746 | 1.62k | } |
747 | | |
748 | 845 | void setIsMessagingSetter(bool val = true) { |
749 | 845 | setMethodRefFlag(MethodRef_Setter, val); |
750 | 845 | } |
751 | | |
752 | 23.0k | const Expr *getBase() const { |
753 | 23.0k | return cast<Expr>(Receiver.get<Stmt*>()); |
754 | 23.0k | } |
755 | 8.72k | Expr *getBase() { |
756 | 8.72k | return cast<Expr>(Receiver.get<Stmt*>()); |
757 | 8.72k | } |
758 | | |
759 | 5.86k | SourceLocation getLocation() const { return IdLoc; } |
760 | | |
761 | 1.75k | SourceLocation getReceiverLocation() const { return ReceiverLoc; } |
762 | | |
763 | 265 | QualType getSuperReceiverType() const { |
764 | 265 | return QualType(Receiver.get<const Type*>(), 0); |
765 | 265 | } |
766 | | |
767 | 251 | ObjCInterfaceDecl *getClassReceiver() const { |
768 | 251 | return Receiver.get<ObjCInterfaceDecl*>(); |
769 | 251 | } |
770 | | |
771 | 28.7k | bool isObjectReceiver() const { return Receiver.is<Stmt*>(); } |
772 | 6.24k | bool isSuperReceiver() const { return Receiver.is<const Type*>(); } |
773 | 9.36k | bool isClassReceiver() const { return Receiver.is<ObjCInterfaceDecl*>(); } |
774 | | |
775 | | /// Determine the type of the base, regardless of the kind of receiver. |
776 | | QualType getReceiverType(const ASTContext &ctx) const; |
777 | | |
778 | 18.5k | SourceLocation getBeginLoc() const LLVM_READONLY { |
779 | 18.5k | return isObjectReceiver() ? getBase()->getBeginLoc()16.8k |
780 | 18.5k | : getReceiverLocation()1.70k ; |
781 | 18.5k | } |
782 | | |
783 | 2.69k | SourceLocation getEndLoc() const LLVM_READONLY { return IdLoc; } |
784 | | |
785 | | // Iterators |
786 | 7.12k | child_range children() { |
787 | 7.12k | if (Receiver.is<Stmt*>()) { |
788 | 6.45k | Stmt **begin = reinterpret_cast<Stmt**>(&Receiver); // hack! |
789 | 6.45k | return child_range(begin, begin+1); |
790 | 6.45k | } |
791 | 679 | return child_range(child_iterator(), child_iterator()); |
792 | 7.12k | } |
793 | | |
794 | 0 | const_child_range children() const { |
795 | 0 | auto Children = const_cast<ObjCPropertyRefExpr *>(this)->children(); |
796 | 0 | return const_child_range(Children.begin(), Children.end()); |
797 | 0 | } |
798 | | |
799 | 7.34M | static bool classof(const Stmt *T) { |
800 | 7.34M | return T->getStmtClass() == ObjCPropertyRefExprClass; |
801 | 7.34M | } |
802 | | |
803 | | private: |
804 | | friend class ASTStmtReader; |
805 | | friend class ASTStmtWriter; |
806 | | |
807 | 0 | void setExplicitProperty(ObjCPropertyDecl *D, unsigned methRefFlags) { |
808 | 0 | PropertyOrGetter.setPointer(D); |
809 | 0 | PropertyOrGetter.setInt(false); |
810 | 0 | SetterAndMethodRefFlags.setPointer(nullptr); |
811 | 0 | SetterAndMethodRefFlags.setInt(methRefFlags); |
812 | 0 | } |
813 | | |
814 | | void setImplicitProperty(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter, |
815 | 1 | unsigned methRefFlags) { |
816 | 1 | PropertyOrGetter.setPointer(Getter); |
817 | 1 | PropertyOrGetter.setInt(true); |
818 | 1 | SetterAndMethodRefFlags.setPointer(Setter); |
819 | 1 | SetterAndMethodRefFlags.setInt(methRefFlags); |
820 | 1 | } |
821 | | |
822 | 0 | void setBase(Expr *Base) { Receiver = Base; } |
823 | 0 | void setSuperReceiver(QualType T) { Receiver = T.getTypePtr(); } |
824 | 1 | void setClassReceiver(ObjCInterfaceDecl *D) { Receiver = D; } |
825 | | |
826 | 1 | void setLocation(SourceLocation L) { IdLoc = L; } |
827 | 1 | void setReceiverLocation(SourceLocation Loc) { ReceiverLoc = Loc; } |
828 | | |
829 | 2.46k | void setMethodRefFlag(MethodRefFlags flag, bool val) { |
830 | 2.46k | unsigned f = SetterAndMethodRefFlags.getInt(); |
831 | 2.46k | if (val) |
832 | 2.46k | f |= flag; |
833 | 0 | else |
834 | 0 | f &= ~flag; |
835 | 2.46k | SetterAndMethodRefFlags.setInt(f); |
836 | 2.46k | } |
837 | | }; |
838 | | |
839 | | /// ObjCSubscriptRefExpr - used for array and dictionary subscripting. |
840 | | /// array[4] = array[3]; dictionary[key] = dictionary[alt_key]; |
841 | | class ObjCSubscriptRefExpr : public Expr { |
842 | | // Location of ']' in an indexing expression. |
843 | | SourceLocation RBracket; |
844 | | |
845 | | // array/dictionary base expression. |
846 | | // for arrays, this is a numeric expression. For dictionaries, this is |
847 | | // an objective-c object pointer expression. |
848 | | enum { BASE, KEY, END_EXPR }; |
849 | | Stmt* SubExprs[END_EXPR]; |
850 | | |
851 | | ObjCMethodDecl *GetAtIndexMethodDecl; |
852 | | |
853 | | // For immutable objects this is null. When ObjCSubscriptRefExpr is to read |
854 | | // an indexed object this is null too. |
855 | | ObjCMethodDecl *SetAtIndexMethodDecl; |
856 | | |
857 | | public: |
858 | | ObjCSubscriptRefExpr(Expr *base, Expr *key, QualType T, ExprValueKind VK, |
859 | | ExprObjectKind OK, ObjCMethodDecl *getMethod, |
860 | | ObjCMethodDecl *setMethod, SourceLocation RB) |
861 | | : Expr(ObjCSubscriptRefExprClass, T, VK, OK), RBracket(RB), |
862 | 576 | GetAtIndexMethodDecl(getMethod), SetAtIndexMethodDecl(setMethod) { |
863 | 576 | SubExprs[BASE] = base; |
864 | 576 | SubExprs[KEY] = key; |
865 | 576 | setDependence(computeDependence(this)); |
866 | 576 | } |
867 | | |
868 | | explicit ObjCSubscriptRefExpr(EmptyShell Empty) |
869 | 12 | : Expr(ObjCSubscriptRefExprClass, Empty) {} |
870 | | |
871 | 293 | SourceLocation getRBracket() const { return RBracket; } |
872 | 12 | void setRBracket(SourceLocation RB) { RBracket = RB; } |
873 | | |
874 | 1.74k | SourceLocation getBeginLoc() const LLVM_READONLY { |
875 | 1.74k | return SubExprs[BASE]->getBeginLoc(); |
876 | 1.74k | } |
877 | | |
878 | 567 | SourceLocation getEndLoc() const LLVM_READONLY { return RBracket; } |
879 | | |
880 | 1.72k | Expr *getBaseExpr() const { return cast<Expr>(SubExprs[BASE]); } |
881 | 12 | void setBaseExpr(Stmt *S) { SubExprs[BASE] = S; } |
882 | | |
883 | 1.74k | Expr *getKeyExpr() const { return cast<Expr>(SubExprs[KEY]); } |
884 | 12 | void setKeyExpr(Stmt *S) { SubExprs[KEY] = S; } |
885 | | |
886 | 306 | ObjCMethodDecl *getAtIndexMethodDecl() const { |
887 | 306 | return GetAtIndexMethodDecl; |
888 | 306 | } |
889 | | |
890 | 306 | ObjCMethodDecl *setAtIndexMethodDecl() const { |
891 | 306 | return SetAtIndexMethodDecl; |
892 | 306 | } |
893 | | |
894 | 4 | bool isArraySubscriptRefExpr() const { |
895 | 4 | return getKeyExpr()->getType()->isIntegralOrEnumerationType(); |
896 | 4 | } |
897 | | |
898 | 669 | child_range children() { |
899 | 669 | return child_range(SubExprs, SubExprs+END_EXPR); |
900 | 669 | } |
901 | | |
902 | 0 | const_child_range children() const { |
903 | 0 | return const_child_range(SubExprs, SubExprs + END_EXPR); |
904 | 0 | } |
905 | | |
906 | 2.62k | static bool classof(const Stmt *T) { |
907 | 2.62k | return T->getStmtClass() == ObjCSubscriptRefExprClass; |
908 | 2.62k | } |
909 | | |
910 | | private: |
911 | | friend class ASTStmtReader; |
912 | | }; |
913 | | |
914 | | /// An expression that sends a message to the given Objective-C |
915 | | /// object or class. |
916 | | /// |
917 | | /// The following contains two message send expressions: |
918 | | /// |
919 | | /// \code |
920 | | /// [[NSString alloc] initWithString:@"Hello"] |
921 | | /// \endcode |
922 | | /// |
923 | | /// The innermost message send invokes the "alloc" class method on the |
924 | | /// NSString class, while the outermost message send invokes the |
925 | | /// "initWithString" instance method on the object returned from |
926 | | /// NSString's "alloc". In all, an Objective-C message send can take |
927 | | /// on four different (although related) forms: |
928 | | /// |
929 | | /// 1. Send to an object instance. |
930 | | /// 2. Send to a class. |
931 | | /// 3. Send to the superclass instance of the current class. |
932 | | /// 4. Send to the superclass of the current class. |
933 | | /// |
934 | | /// All four kinds of message sends are modeled by the ObjCMessageExpr |
935 | | /// class, and can be distinguished via \c getReceiverKind(). Example: |
936 | | /// |
937 | | /// The "void *" trailing objects are actually ONE void * (the |
938 | | /// receiver pointer), and NumArgs Expr *. But due to the |
939 | | /// implementation of children(), these must be together contiguously. |
940 | | class ObjCMessageExpr final |
941 | | : public Expr, |
942 | | private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> { |
943 | | /// Stores either the selector that this message is sending |
944 | | /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer |
945 | | /// referring to the method that we type-checked against. |
946 | | uintptr_t SelectorOrMethod = 0; |
947 | | |
948 | | enum { NumArgsBitWidth = 16 }; |
949 | | |
950 | | /// The number of arguments in the message send, not |
951 | | /// including the receiver. |
952 | | unsigned NumArgs : NumArgsBitWidth; |
953 | | |
954 | | /// The kind of message send this is, which is one of the |
955 | | /// ReceiverKind values. |
956 | | /// |
957 | | /// We pad this out to a byte to avoid excessive masking and shifting. |
958 | | unsigned Kind : 8; |
959 | | |
960 | | /// Whether we have an actual method prototype in \c |
961 | | /// SelectorOrMethod. |
962 | | /// |
963 | | /// When non-zero, we have a method declaration; otherwise, we just |
964 | | /// have a selector. |
965 | | unsigned HasMethod : 1; |
966 | | |
967 | | /// Whether this message send is a "delegate init call", |
968 | | /// i.e. a call of an init method on self from within an init method. |
969 | | unsigned IsDelegateInitCall : 1; |
970 | | |
971 | | /// Whether this message send was implicitly generated by |
972 | | /// the implementation rather than explicitly written by the user. |
973 | | unsigned IsImplicit : 1; |
974 | | |
975 | | /// Whether the locations of the selector identifiers are in a |
976 | | /// "standard" position, a enum SelectorLocationsKind. |
977 | | unsigned SelLocsKind : 2; |
978 | | |
979 | | /// When the message expression is a send to 'super', this is |
980 | | /// the location of the 'super' keyword. |
981 | | SourceLocation SuperLoc; |
982 | | |
983 | | /// The source locations of the open and close square |
984 | | /// brackets ('[' and ']', respectively). |
985 | | SourceLocation LBracLoc, RBracLoc; |
986 | | |
987 | | ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) |
988 | | : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false), |
989 | 40 | IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) { |
990 | 40 | setNumArgs(NumArgs); |
991 | 40 | } |
992 | | |
993 | | ObjCMessageExpr(QualType T, ExprValueKind VK, |
994 | | SourceLocation LBracLoc, |
995 | | SourceLocation SuperLoc, |
996 | | bool IsInstanceSuper, |
997 | | QualType SuperType, |
998 | | Selector Sel, |
999 | | ArrayRef<SourceLocation> SelLocs, |
1000 | | SelectorLocationsKind SelLocsK, |
1001 | | ObjCMethodDecl *Method, |
1002 | | ArrayRef<Expr *> Args, |
1003 | | SourceLocation RBracLoc, |
1004 | | bool isImplicit); |
1005 | | ObjCMessageExpr(QualType T, ExprValueKind VK, |
1006 | | SourceLocation LBracLoc, |
1007 | | TypeSourceInfo *Receiver, |
1008 | | Selector Sel, |
1009 | | ArrayRef<SourceLocation> SelLocs, |
1010 | | SelectorLocationsKind SelLocsK, |
1011 | | ObjCMethodDecl *Method, |
1012 | | ArrayRef<Expr *> Args, |
1013 | | SourceLocation RBracLoc, |
1014 | | bool isImplicit); |
1015 | | ObjCMessageExpr(QualType T, ExprValueKind VK, |
1016 | | SourceLocation LBracLoc, |
1017 | | Expr *Receiver, |
1018 | | Selector Sel, |
1019 | | ArrayRef<SourceLocation> SelLocs, |
1020 | | SelectorLocationsKind SelLocsK, |
1021 | | ObjCMethodDecl *Method, |
1022 | | ArrayRef<Expr *> Args, |
1023 | | SourceLocation RBracLoc, |
1024 | | bool isImplicit); |
1025 | | |
1026 | 1.64k | size_t numTrailingObjects(OverloadToken<void *>) const { return NumArgs + 1; } |
1027 | | |
1028 | 25.4k | void setNumArgs(unsigned Num) { |
1029 | 25.4k | assert((Num >> NumArgsBitWidth) == 0 && "Num of args is out of range!"); |
1030 | 0 | NumArgs = Num; |
1031 | 25.4k | } |
1032 | | |
1033 | | void initArgsAndSelLocs(ArrayRef<Expr *> Args, |
1034 | | ArrayRef<SourceLocation> SelLocs, |
1035 | | SelectorLocationsKind SelLocsK); |
1036 | | |
1037 | | /// Retrieve the pointer value of the message receiver. |
1038 | 158k | void *getReceiverPointer() const { return *getTrailingObjects<void *>(); } |
1039 | | |
1040 | | /// Set the pointer value of the message receiver. |
1041 | 25.4k | void setReceiverPointer(void *Value) { |
1042 | 25.4k | *getTrailingObjects<void *>() = Value; |
1043 | 25.4k | } |
1044 | | |
1045 | 2.33k | SelectorLocationsKind getSelLocsKind() const { |
1046 | 2.33k | return (SelectorLocationsKind)SelLocsKind; |
1047 | 2.33k | } |
1048 | | |
1049 | 1.21k | bool hasStandardSelLocs() const { |
1050 | 1.21k | return getSelLocsKind() != SelLoc_NonStandard; |
1051 | 1.21k | } |
1052 | | |
1053 | | /// Get a pointer to the stored selector identifiers locations array. |
1054 | | /// No locations will be stored if HasStandardSelLocs is true. |
1055 | 1.62k | SourceLocation *getStoredSelLocs() { |
1056 | 1.62k | return getTrailingObjects<SourceLocation>(); |
1057 | 1.62k | } |
1058 | 16 | const SourceLocation *getStoredSelLocs() const { |
1059 | 16 | return getTrailingObjects<SourceLocation>(); |
1060 | 16 | } |
1061 | | |
1062 | | /// Get the number of stored selector identifiers locations. |
1063 | | /// No locations will be stored if HasStandardSelLocs is true. |
1064 | 74 | unsigned getNumStoredSelLocs() const { |
1065 | 74 | if (hasStandardSelLocs()) |
1066 | 50 | return 0; |
1067 | 24 | return getNumSelectorLocs(); |
1068 | 74 | } |
1069 | | |
1070 | | static ObjCMessageExpr *alloc(const ASTContext &C, |
1071 | | ArrayRef<Expr *> Args, |
1072 | | SourceLocation RBraceLoc, |
1073 | | ArrayRef<SourceLocation> SelLocs, |
1074 | | Selector Sel, |
1075 | | SelectorLocationsKind &SelLocsK); |
1076 | | static ObjCMessageExpr *alloc(const ASTContext &C, |
1077 | | unsigned NumArgs, |
1078 | | unsigned NumStoredSelLocs); |
1079 | | |
1080 | | public: |
1081 | | friend class ASTStmtReader; |
1082 | | friend class ASTStmtWriter; |
1083 | | friend TrailingObjects; |
1084 | | |
1085 | | /// The kind of receiver this message is sending to. |
1086 | | enum ReceiverKind { |
1087 | | /// The receiver is a class. |
1088 | | Class = 0, |
1089 | | |
1090 | | /// The receiver is an object instance. |
1091 | | Instance, |
1092 | | |
1093 | | /// The receiver is a superclass. |
1094 | | SuperClass, |
1095 | | |
1096 | | /// The receiver is the instance of the superclass object. |
1097 | | SuperInstance |
1098 | | }; |
1099 | | |
1100 | | /// Create a message send to super. |
1101 | | /// |
1102 | | /// \param Context The ASTContext in which this expression will be created. |
1103 | | /// |
1104 | | /// \param T The result type of this message. |
1105 | | /// |
1106 | | /// \param VK The value kind of this message. A message returning |
1107 | | /// a l-value or r-value reference will be an l-value or x-value, |
1108 | | /// respectively. |
1109 | | /// |
1110 | | /// \param LBracLoc The location of the open square bracket '['. |
1111 | | /// |
1112 | | /// \param SuperLoc The location of the "super" keyword. |
1113 | | /// |
1114 | | /// \param IsInstanceSuper Whether this is an instance "super" |
1115 | | /// message (otherwise, it's a class "super" message). |
1116 | | /// |
1117 | | /// \param Sel The selector used to determine which method gets called. |
1118 | | /// |
1119 | | /// \param Method The Objective-C method against which this message |
1120 | | /// send was type-checked. May be nullptr. |
1121 | | /// |
1122 | | /// \param Args The message send arguments. |
1123 | | /// |
1124 | | /// \param RBracLoc The location of the closing square bracket ']'. |
1125 | | static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, |
1126 | | ExprValueKind VK, |
1127 | | SourceLocation LBracLoc, |
1128 | | SourceLocation SuperLoc, |
1129 | | bool IsInstanceSuper, |
1130 | | QualType SuperType, |
1131 | | Selector Sel, |
1132 | | ArrayRef<SourceLocation> SelLocs, |
1133 | | ObjCMethodDecl *Method, |
1134 | | ArrayRef<Expr *> Args, |
1135 | | SourceLocation RBracLoc, |
1136 | | bool isImplicit); |
1137 | | |
1138 | | /// Create a class message send. |
1139 | | /// |
1140 | | /// \param Context The ASTContext in which this expression will be created. |
1141 | | /// |
1142 | | /// \param T The result type of this message. |
1143 | | /// |
1144 | | /// \param VK The value kind of this message. A message returning |
1145 | | /// a l-value or r-value reference will be an l-value or x-value, |
1146 | | /// respectively. |
1147 | | /// |
1148 | | /// \param LBracLoc The location of the open square bracket '['. |
1149 | | /// |
1150 | | /// \param Receiver The type of the receiver, including |
1151 | | /// source-location information. |
1152 | | /// |
1153 | | /// \param Sel The selector used to determine which method gets called. |
1154 | | /// |
1155 | | /// \param Method The Objective-C method against which this message |
1156 | | /// send was type-checked. May be nullptr. |
1157 | | /// |
1158 | | /// \param Args The message send arguments. |
1159 | | /// |
1160 | | /// \param RBracLoc The location of the closing square bracket ']'. |
1161 | | static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, |
1162 | | ExprValueKind VK, |
1163 | | SourceLocation LBracLoc, |
1164 | | TypeSourceInfo *Receiver, |
1165 | | Selector Sel, |
1166 | | ArrayRef<SourceLocation> SelLocs, |
1167 | | ObjCMethodDecl *Method, |
1168 | | ArrayRef<Expr *> Args, |
1169 | | SourceLocation RBracLoc, |
1170 | | bool isImplicit); |
1171 | | |
1172 | | /// Create an instance message send. |
1173 | | /// |
1174 | | /// \param Context The ASTContext in which this expression will be created. |
1175 | | /// |
1176 | | /// \param T The result type of this message. |
1177 | | /// |
1178 | | /// \param VK The value kind of this message. A message returning |
1179 | | /// a l-value or r-value reference will be an l-value or x-value, |
1180 | | /// respectively. |
1181 | | /// |
1182 | | /// \param LBracLoc The location of the open square bracket '['. |
1183 | | /// |
1184 | | /// \param Receiver The expression used to produce the object that |
1185 | | /// will receive this message. |
1186 | | /// |
1187 | | /// \param Sel The selector used to determine which method gets called. |
1188 | | /// |
1189 | | /// \param Method The Objective-C method against which this message |
1190 | | /// send was type-checked. May be nullptr. |
1191 | | /// |
1192 | | /// \param Args The message send arguments. |
1193 | | /// |
1194 | | /// \param RBracLoc The location of the closing square bracket ']'. |
1195 | | static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, |
1196 | | ExprValueKind VK, |
1197 | | SourceLocation LBracLoc, |
1198 | | Expr *Receiver, |
1199 | | Selector Sel, |
1200 | | ArrayRef<SourceLocation> SeLocs, |
1201 | | ObjCMethodDecl *Method, |
1202 | | ArrayRef<Expr *> Args, |
1203 | | SourceLocation RBracLoc, |
1204 | | bool isImplicit); |
1205 | | |
1206 | | /// Create an empty Objective-C message expression, to be |
1207 | | /// filled in by subsequent calls. |
1208 | | /// |
1209 | | /// \param Context The context in which the message send will be created. |
1210 | | /// |
1211 | | /// \param NumArgs The number of message arguments, not including |
1212 | | /// the receiver. |
1213 | | static ObjCMessageExpr *CreateEmpty(const ASTContext &Context, |
1214 | | unsigned NumArgs, |
1215 | | unsigned NumStoredSelLocs); |
1216 | | |
1217 | | /// Indicates whether the message send was implicitly |
1218 | | /// generated by the implementation. If false, it was written explicitly |
1219 | | /// in the source code. |
1220 | 40.7k | bool isImplicit() const { return IsImplicit; } |
1221 | | |
1222 | | /// Determine the kind of receiver that this message is being |
1223 | | /// sent to. |
1224 | 526k | ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } |
1225 | | |
1226 | | /// \return the return type of the message being sent. |
1227 | | /// This is not always the type of the message expression itself because |
1228 | | /// of references (the expression would not have a reference type). |
1229 | | /// It is also not always the declared return type of the method because |
1230 | | /// of `instancetype` (in that case it's an expression type). |
1231 | | QualType getCallReturnType(ASTContext &Ctx) const; |
1232 | | |
1233 | | /// Source range of the receiver. |
1234 | | SourceRange getReceiverRange() const; |
1235 | | |
1236 | | /// Determine whether this is an instance message to either a |
1237 | | /// computed object or to super. |
1238 | 80.1k | bool isInstanceMessage() const { |
1239 | 80.1k | return getReceiverKind() == Instance || getReceiverKind() == SuperInstance17.3k ; |
1240 | 80.1k | } |
1241 | | |
1242 | | /// Determine whether this is an class message to either a |
1243 | | /// specified class or to super. |
1244 | 14 | bool isClassMessage() const { |
1245 | 14 | return getReceiverKind() == Class || getReceiverKind() == SuperClass9 ; |
1246 | 14 | } |
1247 | | |
1248 | | /// Returns the object expression (receiver) for an instance message, |
1249 | | /// or null for a message that is not an instance message. |
1250 | 148k | Expr *getInstanceReceiver() { |
1251 | 148k | if (getReceiverKind() == Instance) |
1252 | 138k | return static_cast<Expr *>(getReceiverPointer()); |
1253 | | |
1254 | 10.8k | return nullptr; |
1255 | 148k | } |
1256 | 121k | const Expr *getInstanceReceiver() const { |
1257 | 121k | return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); |
1258 | 121k | } |
1259 | | |
1260 | | /// Turn this message send into an instance message that |
1261 | | /// computes the receiver object with the given expression. |
1262 | 33 | void setInstanceReceiver(Expr *rec) { |
1263 | 33 | Kind = Instance; |
1264 | 33 | setReceiverPointer(rec); |
1265 | 33 | } |
1266 | | |
1267 | | /// Returns the type of a class message send, or NULL if the |
1268 | | /// message is not a class message. |
1269 | 12.6k | QualType getClassReceiver() const { |
1270 | 12.6k | if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) |
1271 | 12.5k | return TSInfo->getType(); |
1272 | | |
1273 | 113 | return {}; |
1274 | 12.6k | } |
1275 | | |
1276 | | /// Returns a type-source information of a class message |
1277 | | /// send, or nullptr if the message is not a class message. |
1278 | 25.0k | TypeSourceInfo *getClassReceiverTypeInfo() const { |
1279 | 25.0k | if (getReceiverKind() == Class) |
1280 | 15.2k | return reinterpret_cast<TypeSourceInfo *>(getReceiverPointer()); |
1281 | 9.88k | return nullptr; |
1282 | 25.0k | } |
1283 | | |
1284 | 7 | void setClassReceiver(TypeSourceInfo *TSInfo) { |
1285 | 7 | Kind = Class; |
1286 | 7 | setReceiverPointer(TSInfo); |
1287 | 7 | } |
1288 | | |
1289 | | /// Retrieve the location of the 'super' keyword for a class |
1290 | | /// or instance message to 'super', otherwise an invalid source location. |
1291 | 40 | SourceLocation getSuperLoc() const { |
1292 | 40 | if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass1 ) |
1293 | 40 | return SuperLoc; |
1294 | | |
1295 | 0 | return SourceLocation(); |
1296 | 40 | } |
1297 | | |
1298 | | /// Retrieve the receiver type to which this message is being directed. |
1299 | | /// |
1300 | | /// This routine cross-cuts all of the different kinds of message |
1301 | | /// sends to determine what the underlying (statically known) type |
1302 | | /// of the receiver will be; use \c getReceiverKind() to determine |
1303 | | /// whether the message is a class or an instance method, whether it |
1304 | | /// is a send to super or not, etc. |
1305 | | /// |
1306 | | /// \returns The type of the receiver. |
1307 | | QualType getReceiverType() const; |
1308 | | |
1309 | | /// Retrieve the Objective-C interface to which this message |
1310 | | /// is being directed, if known. |
1311 | | /// |
1312 | | /// This routine cross-cuts all of the different kinds of message |
1313 | | /// sends to determine what the underlying (statically known) type |
1314 | | /// of the receiver will be; use \c getReceiverKind() to determine |
1315 | | /// whether the message is a class or an instance method, whether it |
1316 | | /// is a send to super or not, etc. |
1317 | | /// |
1318 | | /// \returns The Objective-C interface if known, otherwise nullptr. |
1319 | | ObjCInterfaceDecl *getReceiverInterface() const; |
1320 | | |
1321 | | /// Retrieve the type referred to by 'super'. |
1322 | | /// |
1323 | | /// The returned type will either be an ObjCInterfaceType (for an |
1324 | | /// class message to super) or an ObjCObjectPointerType that refers |
1325 | | /// to a class (for an instance message to super); |
1326 | 8.11k | QualType getSuperType() const { |
1327 | 8.11k | if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass2.83k ) |
1328 | 5.36k | return QualType::getFromOpaquePtr(getReceiverPointer()); |
1329 | | |
1330 | 2.74k | return QualType(); |
1331 | 8.11k | } |
1332 | | |
1333 | 0 | void setSuper(SourceLocation Loc, QualType T, bool IsInstanceSuper) { |
1334 | 0 | Kind = IsInstanceSuper? SuperInstance : SuperClass; |
1335 | 0 | SuperLoc = Loc; |
1336 | 0 | setReceiverPointer(T.getAsOpaquePtr()); |
1337 | 0 | } |
1338 | | |
1339 | | Selector getSelector() const; |
1340 | | |
1341 | 0 | void setSelector(Selector S) { |
1342 | 0 | HasMethod = false; |
1343 | 0 | SelectorOrMethod = reinterpret_cast<uintptr_t>(S.getAsOpaquePtr()); |
1344 | 0 | } |
1345 | | |
1346 | 134k | const ObjCMethodDecl *getMethodDecl() const { |
1347 | 134k | if (HasMethod) |
1348 | 131k | return reinterpret_cast<const ObjCMethodDecl *>(SelectorOrMethod); |
1349 | | |
1350 | 2.56k | return nullptr; |
1351 | 134k | } |
1352 | | |
1353 | 26.6k | ObjCMethodDecl *getMethodDecl() { |
1354 | 26.6k | if (HasMethod) |
1355 | 25.3k | return reinterpret_cast<ObjCMethodDecl *>(SelectorOrMethod); |
1356 | | |
1357 | 1.24k | return nullptr; |
1358 | 26.6k | } |
1359 | | |
1360 | 40 | void setMethodDecl(ObjCMethodDecl *MD) { |
1361 | 40 | HasMethod = true; |
1362 | 40 | SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); |
1363 | 40 | } |
1364 | | |
1365 | 10.9k | ObjCMethodFamily getMethodFamily() const { |
1366 | 10.9k | if (HasMethod) return getMethodDecl()->getMethodFamily()10.9k ; |
1367 | 33 | return getSelector().getMethodFamily(); |
1368 | 10.9k | } |
1369 | | |
1370 | | /// Return the number of actual arguments in this message, |
1371 | | /// not counting the receiver. |
1372 | 152k | unsigned getNumArgs() const { return NumArgs; } |
1373 | | |
1374 | | /// Retrieve the arguments to this message, not including the |
1375 | | /// receiver. |
1376 | 248k | Expr **getArgs() { |
1377 | 248k | return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1); |
1378 | 248k | } |
1379 | 34.7k | const Expr * const *getArgs() const { |
1380 | 34.7k | return reinterpret_cast<const Expr *const *>(getTrailingObjects<void *>() + |
1381 | 34.7k | 1); |
1382 | 34.7k | } |
1383 | | |
1384 | | /// getArg - Return the specified argument. |
1385 | 9.49k | Expr *getArg(unsigned Arg) { |
1386 | 9.49k | assert(Arg < NumArgs && "Arg access out of range!"); |
1387 | 0 | return getArgs()[Arg]; |
1388 | 9.49k | } |
1389 | 9.53k | const Expr *getArg(unsigned Arg) const { |
1390 | 9.53k | assert(Arg < NumArgs && "Arg access out of range!"); |
1391 | 0 | return getArgs()[Arg]; |
1392 | 9.53k | } |
1393 | | |
1394 | | /// setArg - Set the specified argument. |
1395 | 944 | void setArg(unsigned Arg, Expr *ArgExpr) { |
1396 | 944 | assert(Arg < NumArgs && "Arg access out of range!"); |
1397 | 0 | getArgs()[Arg] = ArgExpr; |
1398 | 944 | } |
1399 | | |
1400 | | /// isDelegateInitCall - Answers whether this message send has been |
1401 | | /// tagged as a "delegate init call", i.e. a call to a method in the |
1402 | | /// -init family on self from within an -init method implementation. |
1403 | 12.8k | bool isDelegateInitCall() const { return IsDelegateInitCall; } |
1404 | 78 | void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; } |
1405 | | |
1406 | 189 | SourceLocation getLeftLoc() const { return LBracLoc; } |
1407 | 143 | SourceLocation getRightLoc() const { return RBracLoc; } |
1408 | | |
1409 | 190 | SourceLocation getSelectorStartLoc() const { |
1410 | 190 | if (isImplicit()) |
1411 | 37 | return getBeginLoc(); |
1412 | 153 | return getSelectorLoc(0); |
1413 | 190 | } |
1414 | | |
1415 | 1.13k | SourceLocation getSelectorLoc(unsigned Index) const { |
1416 | 1.13k | assert(Index < getNumSelectorLocs() && "Index out of range!"); |
1417 | 1.13k | if (hasStandardSelLocs()) |
1418 | 1.12k | return getStandardSelectorLoc(Index, getSelector(), |
1419 | 1.12k | getSelLocsKind() == SelLoc_StandardWithSpace, |
1420 | 1.12k | llvm::makeArrayRef(const_cast<Expr**>(getArgs()), |
1421 | 1.12k | getNumArgs()), |
1422 | 1.12k | RBracLoc); |
1423 | 16 | return getStoredSelLocs()[Index]; |
1424 | 1.13k | } |
1425 | | |
1426 | | void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const; |
1427 | | |
1428 | 1.99k | unsigned getNumSelectorLocs() const { |
1429 | 1.99k | if (isImplicit()) |
1430 | 47 | return 0; |
1431 | 1.94k | Selector Sel = getSelector(); |
1432 | 1.94k | if (Sel.isUnarySelector()) |
1433 | 1.30k | return 1; |
1434 | 644 | return Sel.getNumArgs(); |
1435 | 1.94k | } |
1436 | | |
1437 | 0 | void setSourceRange(SourceRange R) { |
1438 | 0 | LBracLoc = R.getBegin(); |
1439 | 0 | RBracLoc = R.getEnd(); |
1440 | 0 | } |
1441 | | |
1442 | 203k | SourceLocation getBeginLoc() const LLVM_READONLY { return LBracLoc; } |
1443 | 49.3k | SourceLocation getEndLoc() const LLVM_READONLY { return RBracLoc; } |
1444 | | |
1445 | | // Iterators |
1446 | | child_range children(); |
1447 | | |
1448 | | const_child_range children() const; |
1449 | | |
1450 | | using arg_iterator = ExprIterator; |
1451 | | using const_arg_iterator = ConstExprIterator; |
1452 | | |
1453 | 25.4k | llvm::iterator_range<arg_iterator> arguments() { |
1454 | 25.4k | return llvm::make_range(arg_begin(), arg_end()); |
1455 | 25.4k | } |
1456 | | |
1457 | 11.9k | llvm::iterator_range<const_arg_iterator> arguments() const { |
1458 | 11.9k | return llvm::make_range(arg_begin(), arg_end()); |
1459 | 11.9k | } |
1460 | | |
1461 | 43.4k | arg_iterator arg_begin() { return reinterpret_cast<Stmt **>(getArgs()); } |
1462 | | |
1463 | 43.4k | arg_iterator arg_end() { |
1464 | 43.4k | return reinterpret_cast<Stmt **>(getArgs() + NumArgs); |
1465 | 43.4k | } |
1466 | | |
1467 | 11.9k | const_arg_iterator arg_begin() const { |
1468 | 11.9k | return reinterpret_cast<Stmt const * const*>(getArgs()); |
1469 | 11.9k | } |
1470 | | |
1471 | 11.9k | const_arg_iterator arg_end() const { |
1472 | 11.9k | return reinterpret_cast<Stmt const * const*>(getArgs() + NumArgs); |
1473 | 11.9k | } |
1474 | | |
1475 | 9.04M | static bool classof(const Stmt *T) { |
1476 | 9.04M | return T->getStmtClass() == ObjCMessageExprClass; |
1477 | 9.04M | } |
1478 | | }; |
1479 | | |
1480 | | /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. |
1481 | | /// (similar in spirit to MemberExpr). |
1482 | | class ObjCIsaExpr : public Expr { |
1483 | | /// Base - the expression for the base object pointer. |
1484 | | Stmt *Base; |
1485 | | |
1486 | | /// IsaMemberLoc - This is the location of the 'isa'. |
1487 | | SourceLocation IsaMemberLoc; |
1488 | | |
1489 | | /// OpLoc - This is the location of '.' or '->' |
1490 | | SourceLocation OpLoc; |
1491 | | |
1492 | | /// IsArrow - True if this is "X->F", false if this is "X.F". |
1493 | | bool IsArrow; |
1494 | | |
1495 | | public: |
1496 | | ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, SourceLocation oploc, |
1497 | | QualType ty) |
1498 | | : Expr(ObjCIsaExprClass, ty, VK_LValue, OK_Ordinary), Base(base), |
1499 | 62 | IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) { |
1500 | 62 | setDependence(computeDependence(this)); |
1501 | 62 | } |
1502 | | |
1503 | | /// Build an empty expression. |
1504 | 0 | explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {} |
1505 | | |
1506 | 0 | void setBase(Expr *E) { Base = E; } |
1507 | 254 | Expr *getBase() const { return cast<Expr>(Base); } |
1508 | | |
1509 | 4 | bool isArrow() const { return IsArrow; } |
1510 | 0 | void setArrow(bool A) { IsArrow = A; } |
1511 | | |
1512 | | /// getMemberLoc - Return the location of the "member", in X->F, it is the |
1513 | | /// location of 'F'. |
1514 | 10 | SourceLocation getIsaMemberLoc() const { return IsaMemberLoc; } |
1515 | 0 | void setIsaMemberLoc(SourceLocation L) { IsaMemberLoc = L; } |
1516 | | |
1517 | 16 | SourceLocation getOpLoc() const { return OpLoc; } |
1518 | 0 | void setOpLoc(SourceLocation L) { OpLoc = L; } |
1519 | | |
1520 | 160 | SourceLocation getBeginLoc() const LLVM_READONLY { |
1521 | 160 | return getBase()->getBeginLoc(); |
1522 | 160 | } |
1523 | | |
1524 | 0 | SourceLocation getBaseLocEnd() const LLVM_READONLY { |
1525 | 0 | return getBase()->getEndLoc(); |
1526 | 0 | } |
1527 | | |
1528 | 30 | SourceLocation getEndLoc() const LLVM_READONLY { return IsaMemberLoc; } |
1529 | | |
1530 | 196 | SourceLocation getExprLoc() const LLVM_READONLY { return IsaMemberLoc; } |
1531 | | |
1532 | | // Iterators |
1533 | 184 | child_range children() { return child_range(&Base, &Base+1); } |
1534 | | |
1535 | 0 | const_child_range children() const { |
1536 | 0 | return const_child_range(&Base, &Base + 1); |
1537 | 0 | } |
1538 | | |
1539 | 18.5M | static bool classof(const Stmt *T) { |
1540 | 18.5M | return T->getStmtClass() == ObjCIsaExprClass; |
1541 | 18.5M | } |
1542 | | }; |
1543 | | |
1544 | | /// ObjCIndirectCopyRestoreExpr - Represents the passing of a function |
1545 | | /// argument by indirect copy-restore in ARC. This is used to support |
1546 | | /// passing indirect arguments with the wrong lifetime, e.g. when |
1547 | | /// passing the address of a __strong local variable to an 'out' |
1548 | | /// parameter. This expression kind is only valid in an "argument" |
1549 | | /// position to some sort of call expression. |
1550 | | /// |
1551 | | /// The parameter must have type 'pointer to T', and the argument must |
1552 | | /// have type 'pointer to U', where T and U agree except possibly in |
1553 | | /// qualification. If the argument value is null, then a null pointer |
1554 | | /// is passed; otherwise it points to an object A, and: |
1555 | | /// 1. A temporary object B of type T is initialized, either by |
1556 | | /// zero-initialization (used when initializing an 'out' parameter) |
1557 | | /// or copy-initialization (used when initializing an 'inout' |
1558 | | /// parameter). |
1559 | | /// 2. The address of the temporary is passed to the function. |
1560 | | /// 3. If the call completes normally, A is move-assigned from B. |
1561 | | /// 4. Finally, A is destroyed immediately. |
1562 | | /// |
1563 | | /// Currently 'T' must be a retainable object lifetime and must be |
1564 | | /// __autoreleasing; this qualifier is ignored when initializing |
1565 | | /// the value. |
1566 | | class ObjCIndirectCopyRestoreExpr : public Expr { |
1567 | | friend class ASTReader; |
1568 | | friend class ASTStmtReader; |
1569 | | |
1570 | | Stmt *Operand; |
1571 | | |
1572 | | // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1; |
1573 | | |
1574 | | explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty) |
1575 | 0 | : Expr(ObjCIndirectCopyRestoreExprClass, Empty) {} |
1576 | | |
1577 | 71 | void setShouldCopy(bool shouldCopy) { |
1578 | 71 | ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy; |
1579 | 71 | } |
1580 | | |
1581 | | public: |
1582 | | ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy) |
1583 | | : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary), |
1584 | 71 | Operand(operand) { |
1585 | 71 | setShouldCopy(shouldCopy); |
1586 | 71 | setDependence(computeDependence(this)); |
1587 | 71 | } |
1588 | | |
1589 | 72 | Expr *getSubExpr() { return cast<Expr>(Operand); } |
1590 | 197 | const Expr *getSubExpr() const { return cast<Expr>(Operand); } |
1591 | | |
1592 | | /// shouldCopy - True if we should do the 'copy' part of the |
1593 | | /// copy-restore. If false, the temporary will be zero-initialized. |
1594 | 27 | bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; } |
1595 | | |
1596 | 191 | child_range children() { return child_range(&Operand, &Operand+1); } |
1597 | | |
1598 | 0 | const_child_range children() const { |
1599 | 0 | return const_child_range(&Operand, &Operand + 1); |
1600 | 0 | } |
1601 | | |
1602 | | // Source locations are determined by the subexpression. |
1603 | 40 | SourceLocation getBeginLoc() const LLVM_READONLY { |
1604 | 40 | return Operand->getBeginLoc(); |
1605 | 40 | } |
1606 | 7 | SourceLocation getEndLoc() const LLVM_READONLY { |
1607 | 7 | return Operand->getEndLoc(); |
1608 | 7 | } |
1609 | | |
1610 | 159 | SourceLocation getExprLoc() const LLVM_READONLY { |
1611 | 159 | return getSubExpr()->getExprLoc(); |
1612 | 159 | } |
1613 | | |
1614 | 793k | static bool classof(const Stmt *s) { |
1615 | 793k | return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass; |
1616 | 793k | } |
1617 | | }; |
1618 | | |
1619 | | /// An Objective-C "bridged" cast expression, which casts between |
1620 | | /// Objective-C pointers and C pointers, transferring ownership in the process. |
1621 | | /// |
1622 | | /// \code |
1623 | | /// NSString *str = (__bridge_transfer NSString *)CFCreateString(); |
1624 | | /// \endcode |
1625 | | class ObjCBridgedCastExpr final |
1626 | | : public ExplicitCastExpr, |
1627 | | private llvm::TrailingObjects<ObjCBridgedCastExpr, CXXBaseSpecifier *> { |
1628 | | friend class ASTStmtReader; |
1629 | | friend class ASTStmtWriter; |
1630 | | friend class CastExpr; |
1631 | | friend TrailingObjects; |
1632 | | |
1633 | | SourceLocation LParenLoc; |
1634 | | SourceLocation BridgeKeywordLoc; |
1635 | | unsigned Kind : 2; |
1636 | | |
1637 | | public: |
1638 | | ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, |
1639 | | CastKind CK, SourceLocation BridgeKeywordLoc, |
1640 | | TypeSourceInfo *TSInfo, Expr *Operand) |
1641 | | : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), |
1642 | | VK_PRValue, CK, Operand, 0, false, TSInfo), |
1643 | 353 | LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {} |
1644 | | |
1645 | | /// Construct an empty Objective-C bridged cast. |
1646 | | explicit ObjCBridgedCastExpr(EmptyShell Shell) |
1647 | 2 | : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0, false) {} |
1648 | | |
1649 | 24 | SourceLocation getLParenLoc() const { return LParenLoc; } |
1650 | | |
1651 | | /// Determine which kind of bridge is being performed via this cast. |
1652 | 58 | ObjCBridgeCastKind getBridgeKind() const { |
1653 | 58 | return static_cast<ObjCBridgeCastKind>(Kind); |
1654 | 58 | } |
1655 | | |
1656 | | /// Retrieve the kind of bridge being performed as a string. |
1657 | | StringRef getBridgeKindName() const; |
1658 | | |
1659 | | /// The location of the bridge keyword. |
1660 | 24 | SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } |
1661 | | |
1662 | 1.60k | SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } |
1663 | | |
1664 | 156 | SourceLocation getEndLoc() const LLVM_READONLY { |
1665 | 156 | return getSubExpr()->getEndLoc(); |
1666 | 156 | } |
1667 | | |
1668 | 10.6k | static bool classof(const Stmt *T) { |
1669 | 10.6k | return T->getStmtClass() == ObjCBridgedCastExprClass; |
1670 | 10.6k | } |
1671 | | }; |
1672 | | |
1673 | | /// A runtime availability query. |
1674 | | /// |
1675 | | /// There are 2 ways to spell this node: |
1676 | | /// \code |
1677 | | /// @available(macos 10.10, ios 8, *); // Objective-C |
1678 | | /// __builtin_available(macos 10.10, ios 8, *); // C, C++, and Objective-C |
1679 | | /// \endcode |
1680 | | /// |
1681 | | /// Note that we only need to keep track of one \c VersionTuple here, which is |
1682 | | /// the one that corresponds to the current deployment target. This is meant to |
1683 | | /// be used in the condition of an \c if, but it is also usable as top level |
1684 | | /// expressions. |
1685 | | /// |
1686 | | class ObjCAvailabilityCheckExpr : public Expr { |
1687 | | friend class ASTStmtReader; |
1688 | | |
1689 | | VersionTuple VersionToCheck; |
1690 | | SourceLocation AtLoc, RParen; |
1691 | | |
1692 | | public: |
1693 | | ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc, |
1694 | | SourceLocation RParen, QualType Ty) |
1695 | | : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary), |
1696 | 110 | VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) { |
1697 | 110 | setDependence(ExprDependence::None); |
1698 | 110 | } |
1699 | | |
1700 | | explicit ObjCAvailabilityCheckExpr(EmptyShell Shell) |
1701 | 0 | : Expr(ObjCAvailabilityCheckExprClass, Shell) {} |
1702 | | |
1703 | 341 | SourceLocation getBeginLoc() const { return AtLoc; } |
1704 | 5 | SourceLocation getEndLoc() const { return RParen; } |
1705 | 22 | SourceRange getSourceRange() const { return {AtLoc, RParen}; } |
1706 | | |
1707 | | /// This may be '*', in which case this should fold to true. |
1708 | 0 | bool hasVersion() const { return !VersionToCheck.empty(); } |
1709 | 122 | VersionTuple getVersion() const { return VersionToCheck; } |
1710 | | |
1711 | 305 | child_range children() { |
1712 | 305 | return child_range(child_iterator(), child_iterator()); |
1713 | 305 | } |
1714 | | |
1715 | 0 | const_child_range children() const { |
1716 | 0 | return const_child_range(const_child_iterator(), const_child_iterator()); |
1717 | 0 | } |
1718 | | |
1719 | 669k | static bool classof(const Stmt *T) { |
1720 | 669k | return T->getStmtClass() == ObjCAvailabilityCheckExprClass; |
1721 | 669k | } |
1722 | | }; |
1723 | | |
1724 | | } // namespace clang |
1725 | | |
1726 | | #endif // LLVM_CLANG_AST_EXPROBJC_H |