How to reconstruct the stack of template instantiations.

Our application visits the C++ AST _after_ it has been built.
As a consequence, we do not have access to Sema: in particular, we have
no access to the stack of active template instantiations.
Nonetheless, when visiting the implicit instantiations of function/class
templates, we need to reconstruct the chain of template instantiations
that caused the generation of the visited node.
Besides our specific application requirements, we think that similar
needs could be common to other applications working on an already built
C++ AST (such as inter-procedural and/or whole-program analysis tools).

In the following (besides explaining our problem in a little more
detail) we present a possible solution: we would like to hear opinions
on it.

As said above, when visiting the implicit instantiation of a function or
class template, we sometimes need to reconstruct the chain of template
instantiations that caused the generation of an AST node A.
We can obtain the innermost declaration node Decl_A containing A
(keeping track of the last declaration entered during the visit).

From this declaration Decl_A we can query the source location for its

point of instantiation (POI_A), possibly after some climbing of the
DeclContext chain. Alas, our search has to stop here: as far as we can
tell, there is no effective way of obtaining from POI_A the AST node B
that caused the instantiation of Decl_A. Moreover, if such a node B is a
not a declaration node (e.g., it is a DeclRefExpr node), we won't be
able to retrieve the innermost declaration node Decl_B containing it
(because the chain of entered declarations we were tracking for node A
is useless as far as node B is concerned).

One possibility is to change the AST construction phase so that it
stores more information for each point of instantiation. Instead of
saving just a source location, a "POI_Info" structure could store a triple:

- POI_Loc: source location
- POI_Node: pointer to the AST node referred by POI_Loc;
- POI_Decl: pointer to the Decl node containing POI_Node.

If deemed useful, a map/table of POI_Info triples could be saved in the
ASTContext so that no change will be required to AST nodes. Clearly, all
Sema routines that could cause the generation of a new POI will have to
be modified so that they bring along the info required to
fill in the POI_Info structure.

Does this approach sounds reasonable?
Are there simpler ways to achieve the same end result?


} Are there simpler ways to achieve the same end result?

What I do in include-what-you-use
( is to just keep track
of the entire call-stack as I'm traversing the AST. The relevant
parts are the ASTNode class (in iwyu_ast_util.h), and the ASTNode
updaters in TraverseDecl, TraverseStmt, and TraverseType.

Using this, whenever you see a template node, you can go up the
ASTNode chain to see all the parents in the AST, which includes the
parents that caused the various template instantiations. Does that
work for you?