@@ -28,6 +28,8 @@ class SyntaxIndexInTree {
2828 explicit SyntaxIndexInTree (size_t IndexInTree) : IndexInTree(IndexInTree) {}
2929
3030public:
31+ // / Create an *uninitialized* \c SyntaxIndexInTree.
32+ SyntaxIndexInTree () {}
3133 static SyntaxIndexInTree zero () { return SyntaxIndexInTree (0 ); }
3234
3335 // / Assuming that this index points to the start of \p Raw, advance it so that
@@ -68,6 +70,9 @@ class SyntaxIdentifier {
6870 SyntaxIndexInTree IndexInTree;
6971
7072public:
73+ // / Create an *uninitialized* \c SyntaxIdentifier.
74+ SyntaxIdentifier () {}
75+
7176 SyntaxIdentifier (RootIdType RootId, SyntaxIndexInTree IndexInTree)
7277 : RootId(RootId), IndexInTree(IndexInTree) {
7378 assert (RootId < NextUnusedRootId && " New RootIds should only be created "
@@ -124,6 +129,9 @@ class AbsoluteSyntaxPosition {
124129 IndexInParentType IndexInParent;
125130
126131public:
132+ // / Create an *uninitialized* \c AbsoluteSyntaxPosition.
133+ AbsoluteSyntaxPosition () {}
134+
127135 AbsoluteSyntaxPosition (OffsetType Offset, IndexInParentType IndexInParent)
128136 : Offset(Offset), IndexInParent(IndexInParent) {}
129137
@@ -156,6 +164,8 @@ class AbsoluteOffsetPosition {
156164 AbsoluteSyntaxPosition::OffsetType Offset;
157165
158166public:
167+ // / Create an *uninitialized* \c AbsoluteOffsetPosition.
168+ AbsoluteOffsetPosition () {}
159169 explicit AbsoluteOffsetPosition (AbsoluteSyntaxPosition::OffsetType Offset)
160170 : Offset(Offset) {}
161171 AbsoluteOffsetPosition (AbsoluteSyntaxPosition Position)
@@ -176,6 +186,8 @@ class AbsoluteSyntaxInfo {
176186 SyntaxIdentifier NodeId;
177187
178188public:
189+ // / Create an *uninitialized* \c AbsoluteSyntaxInfo.
190+ AbsoluteSyntaxInfo () {}
179191 AbsoluteSyntaxInfo (AbsoluteSyntaxPosition Position, SyntaxIdentifier NodeId)
180192 : Position(Position), NodeId(NodeId) {}
181193
@@ -213,16 +225,25 @@ class AbsoluteSyntaxInfo {
213225
214226// / A \c RawSyntax node that is enrichted with information of its position
215227// / 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+
217234 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 ) {}
219243
220244public:
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 () {}
226247
227248 // / Create a new \c AbsoluteRawData backed by \p Raw and with additional \p
228249 // / Info. The caller of this constructor is responsible to ensure that the
@@ -235,10 +256,6 @@ struct AbsoluteRawSyntax {
235256 " should always have a RawSyntax" );
236257 }
237258
238- // / Whether this is a null \c AbsoluteRawSyntax created through the default
239- // / constructor.
240- bool isNull () const { return Raw == nullptr ; }
241-
242259 // / Construct a \c AbsoluteRawSyntax for a \c RawSyntax node that represents
243260 // / the syntax tree's root.
244261 static AbsoluteRawSyntax forRoot (const RawSyntax *Raw) {
@@ -270,16 +287,8 @@ struct AbsoluteRawSyntax {
270287
271288 // / Get the child at \p Index if it exists. If the node does not have a child
272289 // / 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 ;
283292
284293 // / Get the child at \p Index, asserting that it exists. This is slightly
285294 // / more performant than \c getChild in these cases since the \c
@@ -305,46 +314,11 @@ struct AbsoluteRawSyntax {
305314
306315 // / Get the first non-missing token node in this tree. Return \c None if
307316 // / 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 ;
327318
328319 // / Get the last non-missing token node in this tree. Return \c None if
329320 // / 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 ;
348322
349323 // / Construct a new \c AbsoluteRawSyntax node that has the same info as the
350324 // / current one, but
@@ -366,6 +340,122 @@ struct AbsoluteRawSyntax {
366340namespace llvm {
367341raw_ostream &operator <<(raw_ostream &OS,
368342 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
369404} // end namespace llvm
370405
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+
371461#endif // SWIFT_SYNTAX_ABSOLUTERAWSYNTAX_H
0 commit comments