You're hitting a confusing part of the AST as it relates to AST Matchers.
The AST contains lots of implicit things which get added in various situations. Consider this:
$ cat struct.cpp
class A
{
int foo();
};
#ifdef DEFINE_B_STRUCT
class B
{
virtual int foo();
};
#endif
$ cat cmds.txt
m functionDecl()
set output dump
m functionDecl()
$ clang-query-6.0 -f cmds.txt struct.cpp --
Match #1:
struct.cpp:4:2: note: "root" binds here
int foo();
^~~~~~~~~
1 match.
Match #1:
Binding for "root":
CXXMethodDecl 0x560d88cee3f8 <struct.cpp:4:2, col:10> col:6 foo 'int ()'
1 match.
Which is what you expect.
However, if the struct with a virtual method is part of the AST, you get lots of things you don't expect:
clang-query-6.0 -f cmds.txt struct.cpp -- -DDEFINE_B_STRUCT
Match #1:
struct.cpp:4:2: note: "root" binds here
int foo();
^~~~~~~~~
Match #2:
struct.cpp:10:3: note: "root" binds here
virtual int foo();
^~~~~~~~~~~~~~~~~
Match #3:
Match #4:
Match #5:
struct.cpp:8:7: note: "root" binds here
class B
^
5 matches.
Match #1:
Binding for "root":
CXXMethodDecl 0x55df7fd37458 <struct.cpp:4:2, col:10> col:6 foo 'int ()'
Match #2:
Binding for "root":
CXXMethodDecl 0x55df7fd37720 <struct.cpp:10:3, col:19> col:15 foo 'int ()' virtual
Match #3:
Binding for "root":
CXXMethodDecl 0x55df7fd37818 <struct.cpp:8:7, <invalid sloc>> col:7 implicit constexpr operator= 'B &(const B &)' inline default noexcept-unevaluated 0x55df7fd37818
`-ParmVarDecl 0x55df7fd37940 <col:7> col:7 'const B &'
Match #4:
Binding for "root":
CXXMethodDecl 0x55df7fd379d8 <struct.cpp:8:7, <invalid sloc>> col:7 implicit constexpr operator= 'B &(B &&)' inline default noexcept-unevaluated 0x55df7fd379d8
`-ParmVarDecl 0x55df7fd37b00 <col:7> col:7 'B &&'
Match #5:
Binding for "root":
CXXDestructorDecl 0x55df7fd37b88 <struct.cpp:8:7> col:7 implicit ~B 'void ()' inline default trivial noexcept-unevaluated 0x55df7fd37b88
5 matches.
Anyway, I have already prototyped the removal of these nodes, but I haven't submitted a patch yet. I submitted
39522 – Remove implicit nodes from AST when using AST Matchers
to track the task.
Meanwhile I suggest you simply ignore those nodes (they will disappear when you make a more-specific matcher anyway), or use
m functionDecl(unless(isImplicit()))
if you are just exploring.
Thanks,
Stephen.