[cfe-dev] ASTMatchers: isVirtual and isOverride

Manuel Klimek klimek at google.com
Fri Apr 19 07:04:27 PDT 2013


On Fri, Apr 19, 2013 at 3:49 PM, Pedro Delgado Perez <
pedro.delgadoperez at mail.uca.es> wrote:

>  Thank you ver much both of you, it really helps:
>
> 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...
>
>  Ok, Manuel. I need to study this a bit more to catch on the best way for
> me, but it's good to know I can merge both strategies.
>
> 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)
>
> Thank you for your time Gábor. I have put this, but I don't know why it
> doesn't fetch any nodes at all... Could you test this?
>
> 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.)
>
> I have put this as well and this time does it works, but indeed it needs
> something more, because if we have:
>
> class A{
> public:
> A(){}
> ...
> };
>
> class B: public A{
> public:
> B(){}
> ...
> };
>
> An implicit node is detected: the default constructor of class A in the
> list of constructors in default constructor of class B. So, I tried to fix
> this doing  this:
>
> constructorDecl(isDefinition(), parameterCountIs(0),
>         anyOf(hasAnyConstructorInitializer(*
> unless(withInitializer(constructorDecl(isImplicit())))*)),
> has(compoundStmt(has(stmt())))));
>
> But, I newbie in this and it doesn't work as constructorDecl returns a
> Decl and withInitializer a Expr (i think). How could I do this? Sorry for
> this, but I would like to have at least an example complete.
>
Yes, withInitializer takes an Matcher<Expr> (see
http://clang.llvm.org/docs/LibASTMatchersReference.html)

But more importantly isImplicit() returns a Matcher<CXXConstructorDecl> -
and constructorDecl takes those.
So, if you insert
anyOf( constructorDecl(isImplicit()), ...)
that should do what you want...


> In addition, I would like to work only with the code that is explicit and
> for example when I try to match "methodDecl(isOverride())" a lot of
> implicit methods  (and even methods from other files apart of mine) are
> detected with this matcher. How can I avoid this?
>
> Thanks,
>
> Pedro.
> *El dia 19 abr 2013 13:50, Manuel Klimek <klimek at google.com> escribió:*
>
> On Fri, Apr 19, 2013 at 12:18 PM, Pedro Delgado Perez <
> pedro.delgadoperez at mail.uca.es> wrote:
>
>> 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.
>>
> 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
>
>
>> 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 at gmail.com> escribió:*
>>
>> Hi,
>>
>> What version are you using? The matchers isOverride() and isVirtual() I
>> know for certain were not in version 3.2, and can only be found on SVN (in
>> this file:
>> http://llvm.org/svn/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
>> ).
>>
>> Nonetheless, you can implement them all very easily manually, or just
>> indeed copy their implementation from the link above. Also, instead of
>> isDefaultConstructor(), you could use argumentCountIs(0).
>>
>> Gabor
>>
>>
>> 2013/4/18 Pedro Delgado Perez <pedro.delgadoperez at mail.uca.es>
>>
>>> Hi,
>>>
>>> I'm newbie using ASTMatchers and I'm trying to learn little by little
>>> how to use them.
>>>
>>> I was basing on the matcher recordDecl(hasName("Foo"), isDerivedFrom("Bar"))
>>> shown in http://clang.llvm.org/docs/LibASTMatchers.html trying to
>>> include new features. For instance, I tried to look for classes which have
>>> at least one virtual method:
>>>
>>> recordDecl(hasName("Foo"), isDerivedFrom("Bar"), hasMethod(isVirtual()))
>>>
>>> Or I tried to match protected overriden methods:
>>>
>>> methodDecl(allOf(isProtected(), isOverride());
>>>
>>> But neither of them worked as it couldn't find "isOverride" and
>>> "isVirtual" identifiers. I was trying a lot of combinations, but I can't
>>> understand this well.
>>>
>>> Finally, I tried to look for the the default constructor of a certain
>>> class:
>>>
>>> constructorDecl(hasName("Foo"), isDefaultConstructor())
>>>
>>> but this is wrong. What I'm doing bad? Please, any information you give
>>> me will be fine to me to understand how to use matchers.
>>>
>>> Thanks in advance,
>>>
>>> Pedro.
>>>
>>>
>>> _______________________________________________
>>> cfe-dev mailing list
>>> cfe-dev at cs.uiuc.edu
>>>
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>>
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130419/1c7fb1ee/attachment.html>


More information about the cfe-dev mailing list