[cfe-dev] AST matchers -> functionDecl finds definitions of structs
Stephen Kelly via cfe-dev
cfe-dev at lists.llvm.org
Thu Nov 1 13:03:34 PDT 2018
On 01/11/2018 14:52, Julian Mueller via cfe-dev wrote:
> Hello, I have a rather confusing problem.
> As the email's subject says, I happen to match record definitions with
> the matcher /functionDecl/.
>
> Using clang-query on simple example test files works perfectly, unless
> there is an include file involved. As soon, as clang-query (or my own
> tool) constructs an AST for a source, that refers to an include file,
> the matcher /functionDecl/ will match on ANY record that is defined in
> the include file - not matching any defined in the cpp file.
>
> The AST Matcher Reference on /functionDecl/ is rather simple:
> "/Matches function declarations./
>
> /Example matches f /
>
> / void f();/"
>
> No mentions of other node types, so how is this possible - any ideas to
> what i am doing wrong?
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
https://bugs.llvm.org/show_bug.cgi?id=39522
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.
More information about the cfe-dev
mailing list