@@ -218,31 +218,41 @@ class RawSyntax final
218218 }
219219
220220 // / Constructor for creating layout nodes.
221- // / If the node has been allocated inside the bump allocator of a
222- // / \c SyntaxArena, that arena must be passed as \p Arena to retain the node's
223- // / underlying storage.
221+ // / \p Children is an iterator that provides the child \c RawSyntax nodes.
222+ // / It is only traversed once.
223+ // / \p NumChildren is the number of elements provided by the \p Children
224+ // / iterator.
224225 // / If \p NodeId is \c None, the next free NodeId is used, if it is passed,
225226 // / the caller needs to assure that the node ID has not been used yet.
226- RawSyntax (SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
227- size_t TextLength, SourcePresence Presence,
227+ template <typename ChildrenIteratorType>
228+ RawSyntax (SyntaxKind Kind, ChildrenIteratorType ChildrenIt,
229+ uint32_t NumChildren, SourcePresence Presence,
228230 const RC<SyntaxArena> &Arena, llvm::Optional<SyntaxNodeId> NodeId)
229- : Arena(Arena.get()), TextLength(uint32_t (TextLength) ),
231+ : Arena(Arena.get()), TextLength(0 /* computed in body */ ),
230232 Presence (Presence), IsToken(false ),
231- Bits(LayoutData{uint32_t (Layout.size ()),
232- /* TotalSubNodeCount=*/ 0 , /* set in body*/
233- Kind}) {
233+ Bits(LayoutData{NumChildren,
234+ /* TotalSubNodeCount=*/ 0 /* computed in body*/ , Kind}) {
234235 assert (Arena && " RawSyntax nodes must always be allocated in an arena" );
235236 assert (
236237 Kind != SyntaxKind::Token &&
237238 " 'token' syntax node must be constructed with dedicated constructor" );
238239
239- for (auto Child : Layout) {
240+ const RawSyntax **TrailingChildren =
241+ getTrailingObjects<const RawSyntax *>();
242+ for (uint32_t I = 0 ; I < NumChildren;
243+ ++I, ++ChildrenIt, ++TrailingChildren) {
244+ const RawSyntax *Child = *ChildrenIt;
240245 if (Child) {
246+ // Compute TextLength and TotalSubNodeCount of this node in place.
247+ TextLength += Child->getTextLength ();
241248 Bits.Layout .TotalSubNodeCount += Child->getTotalSubNodeCount () + 1 ;
249+
242250 // If the child is stored in a different arena, it needs to stay alive
243251 // as long as this node's arena is alive.
244252 Arena->addChildArena (Child->Arena );
245253 }
254+
255+ *TrailingChildren = Child;
246256 }
247257
248258 if (NodeId.hasValue ()) {
@@ -251,10 +261,6 @@ class RawSyntax final
251261 } else {
252262 this ->NodeId = NextFreeNodeId++;
253263 }
254-
255- // Initialize layout data.
256- std::uninitialized_copy (Layout.begin (), Layout.end (),
257- getTrailingObjects<const RawSyntax *>());
258264 }
259265
260266 // / Constructor for creating token nodes
@@ -311,28 +317,26 @@ class RawSyntax final
311317 // / @{
312318
313319 // / Make a raw "layout" syntax node.
320+ template <typename ChildrenIteratorType>
314321 static const RawSyntax *
315- make (SyntaxKind Kind, ArrayRef< const RawSyntax *> Layout , size_t TextLength ,
322+ make (SyntaxKind Kind, ChildrenIteratorType ChildrenIt , size_t NumChildren ,
316323 SourcePresence Presence, const RC<SyntaxArena> &Arena,
317324 llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
318325 assert (Arena && " RawSyntax nodes must always be allocated in an arena" );
319- auto size = totalSizeToAlloc<const RawSyntax *>(Layout. size () );
326+ auto size = totalSizeToAlloc<const RawSyntax *>(NumChildren );
320327 void *data = Arena->Allocate (size, alignof (RawSyntax));
321328 return new (data)
322- RawSyntax (Kind, Layout, TextLength , Presence, Arena, NodeId);
329+ RawSyntax (Kind, ChildrenIt, NumChildren , Presence, Arena, NodeId);
323330 }
324331
332+ // / Convenience constructor to create a raw "layout" syntax node from an
333+ // / \c llvm::ArrayRef containing the children.
325334 static const RawSyntax *
326- makeAndCalcLength (SyntaxKind Kind, ArrayRef<const RawSyntax *> Layout,
327- SourcePresence Presence, const RC<SyntaxArena> &Arena,
328- llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
329- size_t TextLength = 0 ;
330- for (auto Child : Layout) {
331- if (Child) {
332- TextLength += Child->getTextLength ();
333- }
334- }
335- return make (Kind, Layout, TextLength, Presence, Arena, NodeId);
335+ make (SyntaxKind Kind, llvm::ArrayRef<const RawSyntax *> Children,
336+ SourcePresence Presence, const RC<SyntaxArena> &Arena,
337+ llvm::Optional<SyntaxNodeId> NodeId = llvm::None) {
338+ return make (Kind, Children.begin (), Children.size (), Presence, Arena,
339+ NodeId);
336340 }
337341
338342 // / Make a raw "token" syntax node.
@@ -367,7 +371,7 @@ class RawSyntax final
367371 // / Make a missing raw "layout" syntax node.
368372 static const RawSyntax *missing (SyntaxKind Kind,
369373 const RC<SyntaxArena> &Arena) {
370- return make (Kind, {}, /* TextLength= */ 0 , SourcePresence::Missing, Arena);
374+ return make (Kind, {}, SourcePresence::Missing, Arena);
371375 }
372376
373377 // / Make a missing raw "token" syntax node.
0 commit comments