AST matchers -> functionDecl finds definitions of structs

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.

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.