[cfe-dev] [RecursiveASTVisitor] How to prevent AST expanding when dealing with PCH?

Yafei Liu via cfe-dev cfe-dev at lists.llvm.org
Thu Dec 3 04:11:21 PST 2020


I found that if I call `TraverseDecl()` or `TraverseAST()` on a visitor,
the AST will expand, I dumped the context of the TranslateUnitDecl before
and after `TraverseDecl()` is called:
before:

TranslationUnitDecl 0x5577ffd893a8 <<invalid sloc>> <invalid sloc>
<undeserialized declarations>
|-CXXMethodDecl 0x5577ffdb4670 parent 0x5577ffdb40a8 prev 0x5577ffdb4280
</home/liu/source/helloworld/main.cpp:1:1, line:3:1> line:1:11 used test
'void ()'
| |-Overrides: [ 0x5577ffdb43c8 Foo::test 'void ()' ]
| |-CompoundStmt 0x5577ffdb47e0 <col:18, line:3:1>
| |-OverrideAttr 0x5577ffdb4790 </home/liu/source/helloworld/test.h:11:15>
Inherited
| `-FinalAttr 0x5577ffdb47b8 <col:24> Inherited final
`-FunctionDecl 0x5577ffdb4840 </home/liu/source/helloworld/main.cpp:5:1,
line:6:1> line:5:5 main 'int ()'
  `-CompoundStmt 0x5577ffdb4968 <col:12, line:6:1>

As you can see, this is a method definition, pretty simple, it is indeed
what I write in a cpp file.

but after calling `TraverseAST()`, the result of of the TranslateUnitDecl:

TranslationUnitDecl 0x5577ffd893a8 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x5577ffd8a048 <<invalid sloc>> <invalid sloc> implicit
__int128_t '__int128'
| `-BuiltinType 0x5577ffd89940 '__int128'
|-TypedefDecl 0x5577ffd8a0b8 <<invalid sloc>> <invalid sloc> implicit
__uint128_t 'unsigned __int128'
| `-BuiltinType 0x5577ffd89960 'unsigned __int128'
|-TypedefDecl 0x5577ffd89fb8 <<invalid sloc>> <invalid sloc> implicit
__NSConstantString '__NSConstantString_tag'
| `-RecordType 0x5577ffd89d30 '__NSConstantString_tag' imported
|   `-CXXRecord 0x5577ffd89c88 '__NSConstantString_tag'
|-TypedefDecl 0x5577ffd8a150 <<invalid sloc>> <invalid sloc> implicit
__builtin_ms_va_list 'char *'
| `-PointerType 0x5577ffd8a110 'char *'
|   `-BuiltinType 0x5577ffd89440 'char'
|-TypedefDecl 0x5577ffdb4048 <<invalid sloc>> <invalid sloc> implicit
__builtin_va_list '__va_list_tag [1]'
| `-ConstantArrayType 0x5577ffdb3ff0 '__va_list_tag [1]' 1
|   `-RecordType 0x5577ffd8a250 '__va_list_tag'
|     `-CXXRecord 0x5577ffd8a1a8 '__va_list_tag'
|-CXXRecordDecl 0x5577ffdb4470 </home/liu/source/helloworld/test.h:3:1,
line:8:1> line:3:8 imported referenced struct Foo definition
| |-DefinitionData polymorphic literal has_constexpr_non_copy_move_ctor
can_const_default_init
| | |-DefaultConstructor exists non_trivial constexpr needs_implicit
defaulted_is_constexpr
| | |-CopyConstructor simple non_trivial has_const_param needs_implicit
implicit_has_const_param
| | |-MoveConstructor exists simple non_trivial needs_implicit
| | |-CopyAssignment simple non_trivial has_const_param
implicit_has_const_param
| | |-MoveAssignment exists simple non_trivial
| | `-Destructor simple irrelevant trivial
| |-CXXRecordDecl 0x5577ffdb49a8 <col:1, col:8> col:8 imported implicit
struct Foo
| |-CXXMethodDecl 0x5577ffdb43c8 <line:5:3, col:24> col:16 imported test
'void ()' virtual
| | |-CompoundStmt 0x5577ffdb7e68 <col:23, col:24>
| | `-AnnotateAttr 0x5577ffdb45a0 <line:4:5, col:12> "call_super"
| |-CXXMethodDecl 0x5577ffdb4a58 <line:7:3, col:31> col:16 imported used
test2 'void ()' virtual
| | |-CompoundStmt 0x5577ffdb7e58 <col:30, col:31>
| | |-AnnotateAttr 0x5577ffdb4af8 <line:6:5, col:12> "call_super"
| | `-FinalAttr 0x5577ffdb4b50 <line:7:24> final
| |-CXXMethodDecl 0x5577ffdb4bd0 <line:3:8> col:8 imported implicit
constexpr operator= 'Foo &(const Foo &)' inline default
noexcept-unevaluated 0x5577ffdb4bd0
| | `-ParmVarDecl 0x5577ffdb4d40 <col:8> col:8 imported 'const Foo &'
| |-CXXMethodDecl 0x5577ffdb4db8 <col:8> col:8 imported implicit constexpr
operator= 'Foo &(Foo &&)' inline default noexcept-unevaluated 0x5577ffdb4db8
| | `-ParmVarDecl 0x5577ffdb7678 <col:8> col:8 imported 'Foo &&'
| `-CXXDestructorDecl 0x5577ffdb76f0 <col:8> col:8 imported implicit ~Foo
'void ()' inline default trivial noexcept-unevaluated 0x5577ffdb76f0
|-CXXRecordDecl 0x5577ffdb40a8 <line:10:1, line:12:1> line:10:8 imported
struct Bar definition
| |-DefinitionData polymorphic literal has_constexpr_non_copy_move_ctor
can_const_default_init
| | |-DefaultConstructor exists non_trivial constexpr needs_implicit
defaulted_is_constexpr
| | |-CopyConstructor simple non_trivial has_const_param needs_implicit
implicit_has_const_param
| | |-MoveConstructor exists simple non_trivial needs_implicit
| | |-CopyAssignment simple non_trivial has_const_param
implicit_has_const_param
| | |-MoveAssignment exists simple non_trivial
| | `-Destructor simple irrelevant trivial
| |-public 'Foo'
| |-CXXRecordDecl 0x5577ffdb7888 <col:1, col:8> col:8 imported implicit
struct Bar
| |-CXXMethodDecl 0x5577ffdb4280 <line:11:3, col:24> col:8 imported used
test 'void ()'
| | |-Overrides: [ 0x5577ffdb43c8 Foo::test 'void ()' ]
| | |-OverrideAttr 0x5577ffdb4320 <col:15>
| | `-FinalAttr 0x5577ffdb4348 <col:24> final
| |-CXXMethodDecl 0x5577ffdb7938 <line:10:8> col:8 imported implicit
constexpr operator= 'Bar &(const Bar &)' inline default
noexcept-unevaluated 0x5577ffdb7938
| | `-ParmVarDecl 0x5577ffdb7ab0 <col:8> col:8 imported 'const Bar &'
| |-CXXMethodDecl 0x5577ffdb7b28 <col:8> col:8 imported implicit constexpr
operator= 'Bar &(Bar &&)' inline default noexcept-unevaluated 0x5577ffdb7b28
| | `-ParmVarDecl 0x5577ffdb7c70 <col:8> col:8 imported 'Bar &&'
| `-CXXDestructorDecl 0x5577ffdb7ce8 <col:8> col:8 imported implicit ~Bar
'void ()' inline default trivial noexcept-unevaluated 0x5577ffdb7ce8
|-CXXMethodDecl 0x5577ffdb4670 parent 0x5577ffdb40a8 prev 0x5577ffdb4280
</home/liu/source/helloworld/main.cpp:1:1, line:3:1> line:1:11 used test
'void ()'
| |-Overrides: [ 0x5577ffdb43c8 Foo::test 'void ()' ]
| |-CompoundStmt 0x5577ffdb47e0 <col:18, line:3:1>
| |-OverrideAttr 0x5577ffdb4790 </home/liu/source/helloworld/test.h:11:15>
Inherited
| `-FinalAttr 0x5577ffdb47b8 <col:24> Inherited final
`-FunctionDecl 0x5577ffdb4840 </home/liu/source/helloworld/main.cpp:5:1,
line:6:1> line:5:5 main 'int ()'
  `-CompoundStmt 0x5577ffdb4968 <col:12, line:6:1>

And this will 100% happen even if I implemented nothing in a visitor.

Since the code of the traverse highly depends on macros, it hard for me to
debug what's going on.

So can anyone help:
1. Why does the AST expand?
2. Can I prevent it from expanding if I don't need the information of the
PCH? Less traverse means better performance.
3. If the expansion is not the common case, are there any good break
points for me to debug?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20201203/ebc8a40b/attachment.html>


More information about the cfe-dev mailing list