AST for DeclRefExpr of NonTypeTemplateParm

Hi all,

I’m trying to parse a C++ program that uses templates but I’m having some trouble with the generated AST.

The program:

template <const char *N>

struct A { static const char *p; };

template <const char *N>

const char *A::stuck_out_tongue: = N;

int main()

{

A<B::c> a;

return 0;

}

The generated AST is:

-ClassTemplateDecl 0x450f720 </home/mramalho/esbmc/regression/esbmc-cpp/gcc-template-tests/qualified-id2/main.cpp:5:1, line:6:34> col:8 A

-NonTypeTemplateParmDecl 0x450f620 <line:5:11, col:23> col:23 ‘const char *’ N
-CXXRecordDecl 0x450f690 <line:6:1, col:34> col:8 struct A definition

-CXXRecordDecl 0x450f9b8 <col:1, col:8> col:8 implicit struct A
-VarDecl 0x450fa58 <col:12, col:31> col:31 p 'const char *' static -ClassTemplateSpecializationDecl 0x4516a30 <line:5:1, line:6:34> col:8 struct A definition
-TemplateArgument decl
-Var 0x4516818 'c' 'const char [1]' -CXXRecordDecl 0x4516c98 prev 0x4516a30 <col:1, col:8> col:8 implicit struct A -VarDecl 0x4516d28 <col:12, col:31> col:31 p 'const char *' static -CXXConstructorDecl 0x4516db8 <col:8> col:8 implicit used A 'void (void) throw()' inline -CompoundStmt 0x4517100 col:8
-CXXConstructorDecl 0x4516f18 <col:8> col:8 implicit A 'void (const struct A<&B::c> &)' inline noexcept-unevaluated 0x4516f18 -ParmVarDecl 0x4517060 col:8 col:8 ‘const struct A<&B::c> &’
|-VarDecl 0x450fdc0 parent 0x450f690 prev 0x450fa58 <line:10:1, line:11:23> col:19 p ‘const char *’ cinit

| `-DeclRefExpr 0x450fe60 col:23 ‘const char *’ NonTypeTemplateParm 0x450fb38 ‘N’ ‘const char *’

-CXXRecordDecl 0x450fe88 <line:27:1, line:30:1> line:27:8 struct B definition

-CXXRecordDecl 0x450ffa0 <col:1, col:8> col:8 implicit struct B
-VarDecl 0x4516818 <line:29:3, col:24> col:21 used c 'const char [1]' static -FunctionDecl 0x45168d0 <line:33:1, line:44:1> line:33:5 main ‘int (void)’
-CompoundStmt 0x4517160 <line:34:1, line:44:1> -DeclStmt 0x4517148 <line:35:3, col:12>
-VarDecl 0x4516bd8 <col:3, col:11> col:11 a 'A<struct B::c>':'struct A<&B::c>' callinit -CXXConstructExpr 0x4517118 col:11 ‘A’:‘struct A<&B::c>’ ‘void (void) throw()’

Which is quite simple, but I’m having trouble getting the instantiated varDecl. Does anyone knows:

  1. How can I ignore any non instantiated varDecl?

I tried to check getTemplateSpecializationKind() but it always returns TSK_Undeclared. I also tried to check all redecls() but it only shows:

VarDecl 0x3182ce0 parent 0x31825b0 prev 0x3182978 </home/mramalho/esbmc/regression/esbmc-cpp/gcc-template-tests/qualified-id2/main.cpp:10:1, line:11:23> col:19 p ‘const char *’ cinit
`-DeclRefExpr 0x3182d80 col:23 ‘const char *’ NonTypeTemplateParm 0x3182a58 ‘N’ ‘const char *’

VarDecl 0x3182978 </home/mramalho/esbmc/regression/esbmc-cpp/gcc-template-tests/qualified-id2/main.cpp:6:12, col:31> col:31 p ‘const char *’ static

I tried to cast the VarDecl to TemplateDecl, but also without succes.

  1. How can I get the instantiated VarDecl? (Actually, the opposite of the first question).

I mean, somewhere there must be a VarDecl with a SubstNonTypeTemplateParmExpr, right?

  1. Is it possible to generate the AST without any template? I’m only interested in the instantiated templates. It seems a long shot, but who knows.

Thank you,

1. How can I ignore any non instantiated varDecl?

Check if the variable lives in a dependent DeclContext, something like
'VD->getDeclContext()->isDependentContext()'.

2. How can I get the instantiated VarDecl? (Actually, the opposite of the
first question).

I mean, somewhere there must be a VarDecl with
a SubstNonTypeTemplateParmExpr, right?

If you instantiate it, then yes, it will be there. Changing the last line
of your program to 'return *A<&B::c>::p;' adds this AST node to the dump:

`-VarDecl 0xcc3f08 parent 0xcc2380 prev 0xcc2698 <line:5:1, col:23> col:19
used p 'const char *' cinit
  `-SubstNonTypeTemplateParmExpr 0xcc4110 <col:23> 'const char *'
    `-UnaryOperator 0xcc40f0 <col:23> 'const char *' prefix '&'
      `-DeclRefExpr 0xcc40c8 <col:23> 'const char' lvalue Var 0xcc20b0 'c'
'const char'

3. Is it possible to generate the AST without any template? I'm only
interested in the instantiated templates. It seems a long shot, but who
knows.

No.

Hi Reid,

Thank you for the fast answer! I was struggling with this for a couple of days already! I was already checking isDependentContext() for functions and methods, but completely forgot about that on VarDecls!

Thanks again,