ASTMatchers: isVirtual and isOverride

Hi again,

Well, I’ve just understood that not all the methods in a class have a matcher related. For instance, I’m trying to match the default constructor declaration of a class:

class Foo {
public:
Foo(){}
Foo(int a){… …}
}

And in CXXConstructorDecl we have isDefaultConstructor(), but I can’t find an AST_MATCHER to do this. So, I suppose I would have to implement a new AST_MATCHER like this:

AST_MATCHER(CXXConstructorDecl, isDefaultConstructor){
return Node.isDefaultConstructor();
}

Wouldn’t it? But, this happens often, so… would you recommend me use AST_MATCHERS? Or it would be better to do something like it is explained in http://clang.llvm.org/docs/RAVFrontendAction.html ? This way, I can directly use the methods in the classes. For instance:

 bool VisitCXXConstructorDecl(CXXConstructorDecl *Declaration) {    if (Declaration->isDefaultConstructor()) {

I have to visit a lot of kind of nodes with different features, not only this.

Please, I need a path to get down to work.

Thanks in advance,

Pedro.

El dia 19 abr 2013 01:58, Gábor Kozár kozargabor@gmail.com escribió:

Hi,

Indeed, there are matchers that are not currently implemented, although their implementation would be fairly trivial. Check out the documentation about writing AST matchers: http://clang.llvm.org/docs/LibASTMatchers.html

Sorry, you’re correct, argumentCountIs wrong here, I meant parameterCountIs(). By the way, the list of available matchers is listed here: http://clang.llvm.org/docs/LibASTMatchersReference.html - try looking through the list to find if what you need it available.

As for your further requirement that the constructor not be empty, I’m fairly sure that there is no such matcher readily available for you to use, but it shouldn’t be too difficult to implement one, all the information you need is in the documentation for CXXConstructorDecl: http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html

I have put together quickly the matcher that I believe suits your needs, just so that you can see how it works:

namespace clang {
namespace ast_matchers {

using namespace clang::ast_matchers::internal;

AST_MATCHER(CXXConstructorDecl, defaultNonTrivialCtor)
{
return Node.isThisDeclarationADefinition()
&& Node.isDefaultConstructor()
&& (Node.getNumCtorInitializers() != 0 || !Node.hasTrivialBody());
}

} // ast_matchers
} // clang

(Don’t forget to include ASTMatchers.h, ASTMatchersInternal.h and ASTMatchersMacros.h)

Meanwhile I found that you can actually put this together using existing matchers, which should be the preferred method:

constructorDecl(isDefinition(), parameterCountIs(0),
anyOf(hasAnyConstructorInitializer(anything()), has(compoundStmt(has(stmt())))));

(I did a quick test, and seems to work as intended, but you should make sure to test it thoroughly yourself.)

The matcher you put together looks good, and those macros are there for you to use when implementing matchers.

You can, of course, use AST visitors (RecursiveASTVisitor) to find the node that satisfies these conditions, but usually matchers are preferred, as a higher-level and (usually) much less messy solution. However, in some situations AST Visitors are preferred - this is your choice to make, depending on your use case.

Don’t worry about matcher performance: if you’re using MatchFinder to run your matchers, then it is guaranteed that all matchers will be executed in just one traversal of the AST, i.e. two matchers won’t need two traversals.

Hope this helps,

Gabor

Hi again,

Well, I've just understood that not all the methods in a class have a
matcher related. For instance, I'm trying to match the default constructor
declaration of a class:

class Foo {
public:
*Foo(){}*
Foo(int a){... ...}
}

And in CXXConstructorDecl we have isDefaultConstructor(), but I can't find
an AST_MATCHER to do this. So, I suppose I would have to implement a new
AST_MATCHER like this:

*AST_MATCHER(CXXConstructorDecl, isDefaultConstructor){*
*return Node.isDefaultConstructor();*
*}*

Wouldn't it? But, this happens often, so... would you recommend me use
AST_MATCHERS? Or it would be better to do something like it is explained in
How to write RecursiveASTVisitor based ASTFrontendActions. — Clang 18.0.0git documentation ? This way, I can
directly use the methods in the classes. For instance:

bool VisitCXXConstructorDecl(CXXConstructorDecl *Declaration) { if (Declaration->isDefaultConstructor()) {

I have to visit a lot of kind of nodes with different features, not only
this.

All of the ways you cite make sense. What you want really depends on what
kind of control you want. Note that you can always easily start with AST
matchers to find higher level things you're interested in, and then drill
down through the AST nodes by calling the methods or even by using a
RecursiveASTVisitor on a node...

Cheers,
/Manuel