[cfe-dev] AST Matcher matches InitListExpr child twice

Stephan Bergmann via cfe-dev cfe-dev at lists.llvm.org
Mon Jun 12 00:29:27 PDT 2017


On 06/10/2017 03:31 PM, Ben Liblit via cfe-dev wrote:
> Consider the following C++11 (or later) code fragment, which uses an 
> initialization list that contains a function call:
> 
>      int f();
>      int i {f()};
> 
> The AST for that initialization list consists of an InitListExpr with a 
> single CallExpr child:
> 
>      InitListExpr 0x2df2b80 'int'
>      `-CallExpr 0x2df2b10 'int'
>        `-ImplicitCastExpr 0x2df2af8 ...
>          `-DeclRefExpr 0x2df2aa0 ...
> 
> If I use the Clang AST Matcher API to match on InitListExpr, then I get 
> one match as expected.  However, if I match on CallExpr, then the single 
> CallExpr in the above AST is matched *twice*.  Anything below that 
> CallExpr node is also matched twice; for example, I'd get two matches 
> for the DeclRefExpr if that's what my AST Matcher were looking for. This 
> is definitely a problem for my code, and would seem to be a bug in 
> general.  Surely that's not the intended behavior, is it?

That looks to be by design, cf. DEF_TRAVERSE_STMT(InitListExpr,...) in 
include/clang/AST/RecursiveASTVisitor.h calling into 
TraverseSynOrSemInitListExpr twice (for "syntactic" and "semantic" 
InitListExpr).

In some of our LibreOffice RecursiveASTVisitor implementations we use

>     bool TraverseInitListExpr(
>         InitListExpr * expr
> #if CLANG_VERSION >= 30800
>         , DataRecursionQueue * queue = nullptr
> #endif
>         )
>     {
>         return WalkUpFromInitListExpr(expr)
>             && TraverseSynOrSemInitListExpr(
>                 expr->isSemanticForm() ? expr : expr->getSemanticForm()
> #if CLANG_VERSION >= 30800
>                 , queue
> #endif
>                 );
>     }

to traverse only once (where CLANG_VERSION is LibreOffice's way of 
supporting multiple versions of Clang).



More information about the cfe-dev mailing list