Is ASTPrinter supposed to emit valid C++ code?


Is it possible to emit a valid C++ from AST?

I’ve tried ASTPrinter in Clang-5.0, but it seems to emit some internal Clang representations. For example for template specialization I got:

template struct test<T, int> : sc_core::sc_module {
typedef test<type-parameter-0-0, int> this_t;

This “type-parameter-0-0” seem to be some Clang specifics.


We generally try to preserve type sugar, and printing "type-parameter-0-0"
here is undesirable. If you could figure out how we're losing the type
sugar and fix it, we would probably take the fix. However, while we make a
best-effort attempt to produce valid code from the AST printer, there is in
general no guarantee that the output is valid C++; it is intended for
consumption primarily by humans, not by a compiler.

Usually, people asking about the AST printer are trying to perform some
kind of refactoring by mutating the AST and pretty-printing the output. We
do not recommend this approach. Instead, we recommend that you treat the
AST as an immutable representation of the original code, decide on what
transformations you want to perform, and then produce a set of edits to the
original source code that have the desired effect. Clang's Tooling library
provides support utilities for doing this.

Thanks for response!
No, I don’t really need to mutate the AST.
I just had a wrong impression that AST printer is supposed to emit valid code, since it was doing it nicely in most cases. I can certainly grab everything I need to modify from original code.


Well… it turned out I actually need to generate valid code from AST. In some cases I need to generate replacements for particular template instantiations. But template instantiations exist only in AST, but not in the original source code.

Hopefully I will be able to extend AST printer to work reliably in those scenarios;

So here is a reproducer for original email letter:

template <typename Type1, typename Type2>
struct test {
typedef test this_t; // ASTPrint output : typedef test<Type1, Type2> this_t;

struct test<TT, int> {
typedef test this_t; // ASTPrint output : typedef test<type-parameter-0-0, int> this_t;

And here is AST Dump:

-ClassTemplateDecl 0x4f6ad80 <simple.cpp:1:2, line:4:2> line:2:9 test

-TemplateTypeParmDecl 0x4f6ab88 <line:1:12, col:21> col:21 typename depth 0 index 0 Type1
-TemplateTypeParmDecl 0x4f6ac28 <col:28, col:37> col:37 typename depth 0 index 1 Type2
-CXXRecordDecl 0x4f6ace8 <line:2:2, line:4:2> line:2:9 struct test definition -CXXRecordDecl 0x4f6b020 <col:2, col:9> col:9 implicit referenced struct test -TypedefDecl 0x4f6b0c8 <line:3:6, col:19> col:19 this_t ‘test<Type1, Type2>’
-InjectedClassNameType 0x4f6af90 'test<Type1, Type2>' dependent -CXXRecord 0x4f6ace8 ‘test’
-ClassTemplatePartialSpecializationDecl 0x4f6b320 <line:6:2, line:9:2> line:7:10 struct test definition -TemplateArgument type 'type-parameter-0-0' -TemplateArgument type 'int' -**TemplateTypeParmDecl 0x4f6b140 <line:6:12, col:21> col:21 referenced typename depth 0 index 0 TT** -CXXRecordDecl 0x4f6b5b0 <line:7:2, col:10> col:10 implicit referenced struct test -TypedefDecl 0x4f6b658 <line:8:7, col:20> col:20 this_t ‘test<type-parameter-0-0, int>’
-InjectedClassNameType 0x4f6b440 'test<type-parameter-0-0, int>' dependent -ClassTemplatePartialSpecialization 0x4f6b320 ‘test’

Unfortunately I’ve just started to learn Clang, so I’m not yet able to improve it.

typedef here has a reference to ClassTemplatePartialSpecializationDecl, and it has a TemplateTypeParmDecl that has original parameter name “TT”. So it looks like information to print valid code is available in AST.

I have not encountered yet other cases when ASTPrinter emits invalid code. I hope it is the only one.