[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