<div dir="ltr"><div dir="ltr">On Mon, 6 Jan 2020 at 17:35, David Rector via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I have been experimenting with adjusting RecursiveASTVisitor to perform VisitPre* and VisitPost* (via corresponding WalkUpFromPre* and WalkUpFromPost* methods) surrounding the inner component traversals within each Traverse* definition. This would allow one to easily define visitors that can e.g. keep track of the current traversal state, do pushes/pops around traversals of selected node kinds, etc.<br></blockquote><div><br></div><div>Can you say more about what you want to do here? The kinds of things I think you're describing can already be done straightforwardly by overriding the Traverse* methods, and we have several visitors in Clang that do that kind of thing, so either I'm not understanding or there may already be a good way to do what you're trying to do. (For example, at the top of lib/Sema/SemaTemplateVariadic.cpp, the CollectUnexpandedParameterPacksVisitor keeps track of and pushes/pops traversal state while it's traversing a LambdaExpr.)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
This works great with Decl and Type nodes, as DEF_TRAVERSE_DECL and DEF_TRAVERSE_TYPE are straightforward: if a node D has children D1 and D2, which in turn have children d11 and d12 / d21 and d22 respectively, the descendants of D will be processed in this order:<br>
<br>
D1, d11, d12, D2, d21, d22<br>
<br>
So, my VisitPre*Decl(D1) and VisitPost*Decl(D1) would surround all the visitations of d11 and d12 and their descendants and none of D2’s visitations, as one might expect.<br>
<br>
However, DEF_TRAVERSE_STMT is another matter entirely. It endows each Traverse* function with a "DataRecursionQueue *" parameter. No specific traversals definitions seem to use it idiosyncratically though — instead, all that parameter seems to do is permit the root TraverseStmt definition to process descendants of a Stmt S in the following order, if I am not mistaken:<br>
<br>
S1, S2, s11, s12, s21, s22<br>
<br>
This defeats my intention of fully surrounding the processing of e.g. S1 and its descendants with pre and post visitation. But I can’t discern why it must be done this way — the reasoning is not documented anywhere. Anyone know why Stmts/Exprs are processed in this order, but not Decls and Types?<br></blockquote><div><br></div><div>The purpose is to perform data recursion: instead of recursing using the stack (and potentially overflowing the stack if a complex, deeply-nested expression is encountered), a worklist is maintained separate from the execution stack and a visitor can execute in mostly constant stack space.</div><div><br></div><div>This stack space optimization is automatically turned off when processing Stmt subclasses for which the visitor defines custom behavior (if that custom behavior doesn't support a data recursion queue) -- that's done by the TRAVERSE_STMT_BASE macro. If you want to support more hooks that need to turn off data recursion, you could follow a similar pattern there.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Thanks,<br>
<br>
Dave<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>