@@ -28,6 +28,8 @@ class SyntaxIndexInTree {
28
28
explicit SyntaxIndexInTree (size_t IndexInTree) : IndexInTree(IndexInTree) {}
29
29
30
30
public:
31
+ // / Create an *uninitialized* \c SyntaxIndexInTree.
32
+ SyntaxIndexInTree () {}
31
33
static SyntaxIndexInTree zero () { return SyntaxIndexInTree (0 ); }
32
34
33
35
// / Assuming that this index points to the start of \p Raw, advance it so that
@@ -68,6 +70,9 @@ class SyntaxIdentifier {
68
70
SyntaxIndexInTree IndexInTree;
69
71
70
72
public:
73
+ // / Create an *uninitialized* \c SyntaxIdentifier.
74
+ SyntaxIdentifier () {}
75
+
71
76
SyntaxIdentifier (RootIdType RootId, SyntaxIndexInTree IndexInTree)
72
77
: RootId(RootId), IndexInTree(IndexInTree) {
73
78
assert (RootId < NextUnusedRootId && " New RootIds should only be created "
@@ -124,6 +129,9 @@ class AbsoluteSyntaxPosition {
124
129
IndexInParentType IndexInParent;
125
130
126
131
public:
132
+ // / Create an *uninitialized* \c AbsoluteSyntaxPosition.
133
+ AbsoluteSyntaxPosition () {}
134
+
127
135
AbsoluteSyntaxPosition (OffsetType Offset, IndexInParentType IndexInParent)
128
136
: Offset(Offset), IndexInParent(IndexInParent) {}
129
137
@@ -156,6 +164,8 @@ class AbsoluteOffsetPosition {
156
164
AbsoluteSyntaxPosition::OffsetType Offset;
157
165
158
166
public:
167
+ // / Create an *uninitialized* \c AbsoluteOffsetPosition.
168
+ AbsoluteOffsetPosition () {}
159
169
explicit AbsoluteOffsetPosition (AbsoluteSyntaxPosition::OffsetType Offset)
160
170
: Offset(Offset) {}
161
171
AbsoluteOffsetPosition (AbsoluteSyntaxPosition Position)
@@ -176,6 +186,8 @@ class AbsoluteSyntaxInfo {
176
186
SyntaxIdentifier NodeId;
177
187
178
188
public:
189
+ // / Create an *uninitialized* \c AbsoluteSyntaxInfo.
190
+ AbsoluteSyntaxInfo () {}
179
191
AbsoluteSyntaxInfo (AbsoluteSyntaxPosition Position, SyntaxIdentifier NodeId)
180
192
: Position(Position), NodeId(NodeId) {}
181
193
@@ -213,16 +225,25 @@ class AbsoluteSyntaxInfo {
213
225
214
226
// / A \c RawSyntax node that is enrichted with information of its position
215
227
// / within the syntax tree it lives in.
216
- struct AbsoluteRawSyntax {
228
+ class AbsoluteRawSyntax {
229
+ // / OptionalStorage is a friend so it can access the \c nullptr initializer
230
+ // / and \c isNull.
231
+ template <typename , bool >
232
+ friend class llvm ::optional_detail::OptionalStorage;
233
+
217
234
const RawSyntax *Raw;
218
- const AbsoluteSyntaxInfo Info;
235
+ AbsoluteSyntaxInfo Info;
236
+
237
+ // / Whether this is a null \c AbsoluteRawSyntax.
238
+ bool isNull () const { return Raw == nullptr ; }
239
+
240
+ // / Create a null \c AbsoluteRawSyntax. This should only be used in \c
241
+ // / AbsoluteRawSyntax's \c OptionalStorage.
242
+ explicit AbsoluteRawSyntax (std::nullptr_t ) : Raw(nullptr ) {}
219
243
220
244
public:
221
- // / Create a null \c AbsoluteRawSyntax to which a real \c AbsoluteRawSyntax
222
- // / can be stored later.
223
- explicit AbsoluteRawSyntax ()
224
- : Raw(nullptr ), Info(AbsoluteSyntaxPosition(0 , 0 ),
225
- SyntaxIdentifier(0 , SyntaxIndexInTree::zero())) {}
245
+ // / Create an *uninitialized* \c AbsoluteRawSyntax.
246
+ explicit AbsoluteRawSyntax () {}
226
247
227
248
// / Create a new \c AbsoluteRawData backed by \p Raw and with additional \p
228
249
// / Info. The caller of this constructor is responsible to ensure that the
@@ -235,10 +256,6 @@ struct AbsoluteRawSyntax {
235
256
" should always have a RawSyntax" );
236
257
}
237
258
238
- // / Whether this is a null \c AbsoluteRawSyntax created through the default
239
- // / constructor.
240
- bool isNull () const { return Raw == nullptr ; }
241
-
242
259
// / Construct a \c AbsoluteRawSyntax for a \c RawSyntax node that represents
243
260
// / the syntax tree's root.
244
261
static AbsoluteRawSyntax forRoot (const RawSyntax *Raw) {
@@ -270,16 +287,8 @@ struct AbsoluteRawSyntax {
270
287
271
288
// / Get the child at \p Index if it exists. If the node does not have a child
272
289
// / at \p Index, return \c None. Asserts that \p Index < \c NumChildren
273
- Optional<AbsoluteRawSyntax>
274
- getChild (AbsoluteSyntaxPosition::IndexInParentType Index) const {
275
- assert (Index < getNumChildren () && " Index out of bounds" );
276
- auto RawChild = getRaw ()->getChild (Index);
277
- if (RawChild) {
278
- return getPresentChild (Index);
279
- } else {
280
- return None;
281
- }
282
- }
290
+ inline Optional<AbsoluteRawSyntax>
291
+ getChild (AbsoluteSyntaxPosition::IndexInParentType Index) const ;
283
292
284
293
// / Get the child at \p Index, asserting that it exists. This is slightly
285
294
// / more performant than \c getChild in these cases since the \c
@@ -305,46 +314,11 @@ struct AbsoluteRawSyntax {
305
314
306
315
// / Get the first non-missing token node in this tree. Return \c None if
307
316
// / this node does not contain non-missing tokens.
308
- Optional<AbsoluteRawSyntax> getFirstToken () const {
309
- if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
310
- return *this ;
311
- }
312
-
313
- size_t NumChildren = getNumChildren ();
314
- for (size_t I = 0 ; I < NumChildren; ++I) {
315
- if (auto Child = getChild (I)) {
316
- if (Child->getRaw ()->isMissing ()) {
317
- continue ;
318
- }
319
-
320
- if (auto Token = Child->getFirstToken ()) {
321
- return Token;
322
- }
323
- }
324
- }
325
- return None;
326
- }
317
+ inline Optional<AbsoluteRawSyntax> getFirstToken () const ;
327
318
328
319
// / Get the last non-missing token node in this tree. Return \c None if
329
320
// / this node does not contain non-missing tokens.
330
- Optional<AbsoluteRawSyntax> getLastToken () const {
331
- if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
332
- return *this ;
333
- }
334
-
335
- for (int I = getNumChildren () - 1 ; I >= 0 ; --I) {
336
- if (auto Child = getChild (I)) {
337
- if (Child->getRaw ()->isMissing ()) {
338
- continue ;
339
- }
340
-
341
- if (auto Token = Child->getLastToken ()) {
342
- return Token;
343
- }
344
- }
345
- }
346
- return None;
347
- }
321
+ inline Optional<AbsoluteRawSyntax> getLastToken () const ;
348
322
349
323
// / Construct a new \c AbsoluteRawSyntax node that has the same info as the
350
324
// / current one, but
@@ -366,6 +340,122 @@ struct AbsoluteRawSyntax {
366
340
namespace llvm {
367
341
raw_ostream &operator <<(raw_ostream &OS,
368
342
swift::syntax::AbsoluteOffsetPosition Pos);
343
+
344
+ namespace optional_detail {
345
+
346
+ using swift::syntax::AbsoluteRawSyntax;
347
+
348
+ // / A custom \c OptionalStorage implementation for \c AbsoluteRawSyntax that
349
+ // / makes \c Optional<AbsoluteRawSyntax> a zero-cost wrapper around \c
350
+ // / AbsoluteRawSyntax by using a special (externally not accessible) null \c
351
+ // / AbsoluteRawSyntax to represent a missing value.
352
+ template <>
353
+ class OptionalStorage <AbsoluteRawSyntax> {
354
+ AbsoluteRawSyntax Storage;
355
+
356
+ public:
357
+ OptionalStorage () : Storage(nullptr ) {}
358
+ OptionalStorage (OptionalStorage const &other) = default ;
359
+ OptionalStorage (OptionalStorage &&other) = default ;
360
+
361
+ template <class ... ArgTypes>
362
+ explicit OptionalStorage (llvm::optional_detail::in_place_t ,
363
+ ArgTypes &&...Args)
364
+ : Storage(std::forward<ArgTypes>(Args)...) {}
365
+
366
+ void reset () { Storage = AbsoluteRawSyntax (nullptr ); }
367
+
368
+ bool hasValue () const { return !Storage.isNull (); }
369
+
370
+ AbsoluteRawSyntax &getValue () LLVM_LVALUE_FUNCTION {
371
+ assert (hasValue ());
372
+ return Storage;
373
+ }
374
+ AbsoluteRawSyntax const &getValue () const LLVM_LVALUE_FUNCTION {
375
+ assert (hasValue ());
376
+ return Storage;
377
+ }
378
+ #if LLVM_HAS_RVALUE_REFERENCE_THIS
379
+ AbsoluteRawSyntax &&getValue() &&noexcept {
380
+ assert (hasValue ());
381
+ return std::move (Storage);
382
+ }
383
+ #endif
384
+
385
+ template <class ... Args>
386
+ void emplace (Args &&...args) {
387
+ Storage = AbsoluteRawSyntax (std::forward<Args>(args)...);
388
+ }
389
+
390
+ OptionalStorage &operator =(const AbsoluteRawSyntax &AbsoluteRaw) {
391
+ Storage = AbsoluteRaw;
392
+ return *this ;
393
+ }
394
+
395
+ OptionalStorage &operator =(AbsoluteRawSyntax &&AbsoluteRaw) {
396
+ Storage = std::move (AbsoluteRaw);
397
+ return *this ;
398
+ }
399
+
400
+ OptionalStorage &operator =(OptionalStorage const &other) = default ;
401
+ OptionalStorage &operator =(OptionalStorage &&other) = default ;
402
+ };
403
+ } // namespace optional_detail
369
404
} // end namespace llvm
370
405
406
+ namespace swift {
407
+ namespace syntax {
408
+
409
+ Optional<AbsoluteRawSyntax> AbsoluteRawSyntax::getChild (
410
+ AbsoluteSyntaxPosition::IndexInParentType Index) const {
411
+ assert (Index < getNumChildren () && " Index out of bounds" );
412
+ if (getRaw ()->getChild (Index)) {
413
+ return getPresentChild (Index);
414
+ } else {
415
+ return None;
416
+ }
417
+ }
418
+
419
+ Optional<AbsoluteRawSyntax> AbsoluteRawSyntax::getFirstToken () const {
420
+ if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
421
+ return *this ;
422
+ }
423
+
424
+ size_t NumChildren = getNumChildren ();
425
+ for (size_t I = 0 ; I < NumChildren; ++I) {
426
+ if (auto Child = getChild (I)) {
427
+ if (Child->getRaw ()->isMissing ()) {
428
+ continue ;
429
+ }
430
+
431
+ if (auto Token = Child->getFirstToken ()) {
432
+ return Token;
433
+ }
434
+ }
435
+ }
436
+ return None;
437
+ }
438
+
439
+ Optional<AbsoluteRawSyntax> AbsoluteRawSyntax::getLastToken () const {
440
+ if (getRaw ()->isToken () && !getRaw ()->isMissing ()) {
441
+ return *this ;
442
+ }
443
+
444
+ for (int I = getNumChildren () - 1 ; I >= 0 ; --I) {
445
+ if (auto Child = getChild (I)) {
446
+ if (Child->getRaw ()->isMissing ()) {
447
+ continue ;
448
+ }
449
+
450
+ if (auto Token = Child->getLastToken ()) {
451
+ return Token;
452
+ }
453
+ }
454
+ }
455
+ return None;
456
+ }
457
+
458
+ } // end namespace syntax
459
+ } // end namespace swift
460
+
371
461
#endif // SWIFT_SYNTAX_ABSOLUTERAWSYNTAX_H
0 commit comments