[cfe-dev] ASTMatchers: isVirtual and isOverride

Manuel Klimek klimek at google.com
Wed Apr 24 01:56:04 PDT 2013


On Wed, Apr 24, 2013 at 10:48 AM, Pedro Delgado Perez <
pedro.delgadoperez at mail.uca.es> wrote:

>  Hi,
>
> Thank you for all your explanations, now everything is much clearer. But,
> please, let me ask you another last question regarding:
>
>
> *The problem for me is that I'll have to make some source-to-source
> translations: sometimes I'll have to modify the .cpp file and sometimes the
> .h (or even both of them) For instance, if i want to know if a certain
> method is declared as "virtual", I would need to examinate the .h file.
> Thus, I cannot exclude all .h files. So, how can I manage this?*
> *
> *
> Well, you exclude just the system header files in the match callback, as
> I've showed before, using SourceManager :: isInSystemHeader and
> isInExternCSystemHeader.
>
> Ok, I see that i can exclude all the system headers, but imagine the next
> cpp:
>
> #include "A.h"
> #include "B.h"
>
> A::A() {
> ... ...
> }
>
> int A::m() {
> B b;  //B.h header has been included because it's needed in a member
> function of A
> ... ...
> }
>
> ... ...
>
> And I only want to retrieve nodes inside class A (in A.h and A.cpp), but
> not inside B.h because I'm not interested in this class. How can I avoid
> this?
>
What I usually do is: in the callback, take the source location of the
node, look at the file name, and do a regexp on the file to determine
whether you want to examine the node or not.


> In addition, in the matcher we've working on, we looked for default
> constructors declarations defined inline. But several options more were
> possible:
> 1. I have both declaration and definition inline in A.h
> 2. I have both declaration and definition inline in A.cpp
> 3. I have declaration in A.h and definition in A.cpp (the example above)
> 4. I have declaration and definition (but not inline) in A.cpp
>
> We have considered 1 and 2, but not 3 nor 4. Imagine that we have the case
> 3 and I want to delete the constructor both in A.h(declaration) and
> A.cpp(definition). Do I have to prepare two different matchers to look for
> them? Or is there a way that, for example, I find the definition and then I
> can refer its declaration? Of course, I need to make sure that both,
> definition and declaration are deleted.
>

I'd say you'd want to delete all declarations of A::A() (and as such, look
for all constructor declarations), and then use
isThisDeclarationADefinition() to figure out whether there's a body to
delete, too...

Cheers,
/Manuel


> I hope you know what I mean.
>
> Thanks for everything Gábor,
>
> Pedro.
>
>
>
>
> *El dia 22 abr 2013 21:52, Gábor Kozár <kozargabor at gmail.com> escribió:*
>
> Hi,
> > *I found isWritten() member for CXXCtorInitializer:*
> Nice find, I actually did not know about this.*
> *
> > *Ok. But I don't know where I should put or send these matchers to
> share them. Could you indicate me?*
> *
> *
> In the source code, the place for these is ASTMatchers.h. When you have
> something that you would like to propose to be integrated into the clang
> repository, I think what you need to do is send an e-mail to this mailing
> list, with the diff attached (that shows what changes you made), and ask
> for it to reviewed. But you probably should look at the website and see if
> there's any guideline for this - or just ask it on the mailing list.*
> *
> > *When you say "they allow you to run a matcher on the specified node,
> not the whole AST." you mean something like this?:*
> *
> *
> The code snippet you sent shows how to retrieve a node that has been
> accepted and bound by a matcher.*
> *
> What I mean is that if you have a CXXRecordDecl* object for example (from
> whatever source), and you want to find some nodes in it that match a
> specific condition - for example, you want to check if another type is used
> anywhere within this specific C++ class - you can use
> clang::ast_matchers::match, because you only need the nodes that satisfy
> this condition inside the record declaration that you have, and not
> anywhere in the AST.
> To be honest I'm not sure what causes the confusion here, I think this is
> fairly self-explanatory.
> > *The problem for me is that I'll have to make some source-to-source
> translations: sometimes I'll have to modify the .cpp file and sometimes the
> .h (or even both of them) For instance, if i want to know if a certain
> method is declared as "virtual", I would need to examinate the .h file.
> Thus, I cannot exclude all .h files. So, how can I manage this?*
> *
> *
> Well, you exclude just the system header files in the match callback, as
> I've showed before, using SourceManager :: isInSystemHeader and
> isInExternCSystemHeader.*
> *
> > *but it is still matching nodes in other files, such as ostream,
> bits/basic_ios.h or bits/streambuf_interator.h because I included the
> iostream header. I need to avoid all these nodes, but I don't know how to
> do it.*
> *
> *
> You'll need to show me some more code than that. How does your match
> callback function look like? What is FullLocation?*
> *
> > *I see that I can retrieve some nodes using matchers and then use a
> RecursiveASTVisitor on that nodes, but I can't clearly see the contrary: if
> I'm visiting only a kind of node, I know that I can directly use the
> methods of that class, but how could I use a matcher in the same way as in
> the example below?:*
> *
> *
> Both RecursiveASTVisitor and the matchers serve the exact same purpose,
> and they work in exactly the same way (in fact, the matchers use
> RecursiveASTVisitor internally) - the only different is that matchers are
> higher-level concepts, allowing for a more intuitive definition of match
> conditions. It's like a regular expression for ASTs.
> *
> *
> When you work with matchers, you need two things: a matcher expression,
> constructed from the matcher functions like functionDecl(), isDefinition(),
> has(), allOf(), etc. and a match callback, i.e. a function that will be
> called for every AST node the matcher accepts while it is traversing the
> AST (i.e. running). You can use the .bind() method of the matchers to bind
> nodes accepted by the specified matcher to a name, and later retrieve it in
> the callback using result.Nodes.getNodeAs<T>. For example: *
> functionDecl(has(compoundStmt().bind("c"))).bind("f")*. When this matcher
> expression accepts an AST node, and runs the callback, you can access the
> matched FunctionDecl and CompoundStmt nodes by *
> result.Nodes.getNodeAs<FunctionDecl>("f")* and *
> result.Nodes.getNodeAs<CompoundStmt>("c")*, respectively. What you with
> these afterwards is up to you - if you want, you can even run another
> matcher on them using clang::ast_matchers::match, as I've already explained
> above.*
> *
> In your example code, the matcher callback retrieves a bound node (a
> ForStmt) with the name of "forLoop", and then writes its AST to the
> console. For example you can use with this matcher expression: *
> forStmt(unless(has(compoundStmt())))*, which will cause the AST of all
> for loops whose body is just a single statement with the {} brackets to
> appear on the screen.
> Gabor
>
>
> 2013/4/21 Pedro Delgado Perez <pedro.delgadoperez at mail.uca.es>
>
>> Hi,
>>
>> This is indeed something I haven't considered, but should be easy to fix.
>> Looking at the documentation for CXXCtorInitializer, you'll see that
>> there's a member called isBaseInitializer(). The other thing you'll need to
>> check (probably, if that is what you need) for is whether the base ctor
>> call is implicit, which is probably done best by constraining the
>> CXXConstructExpr with argumentCountIs(0). Putting together a custom matcher
>> using these should be simple.
>>
>> I found isWritten() member  for CXXCtorInitializer:
>> "Returns true if this initializer is explicitly written in the source
>> code."
>> And finally, I accomplished what I wanted. Now, only B constructor is
>> matched in:
>>
>> class A{
>>     public: A(){}
>> };
>>
>> class B: public A{
>>     public: int b, h;
>>         B():A(){b=0; h=0;}
>> };
>>
>> class C: public A{
>>     public C(){}
>> };
>>
>> But thanks for the members you have indicated: i'm sure I'll have to use
>> them in the future.
>>
>>
>> Also keep in mind that if you put together a generic and useful enough
>> matcher, you should totally contribute it as a patch, so that others in
>> need of a similar thing have it available in the future.
>>
>> Ok. But I don't know where I should put or send these matchers to share
>> them. Could you indicate me?
>>
>>
>> Yes, you need to use these in the matcher callback. It is indeed
>> inefficient, but we've been unable to come up with any better solution. The
>> problem is in the underlying compiler technology, i.e. the nature of header
>> files.*
>> *
>> > *Is it possible to search for nodes only in some files indicated by
>> the user?*
>> *
>> *
>> Sure, take a look at the clang::ast_matchers::match functions - they
>> allow you to run a matcher on the specified node, not the whole AST.
>> Unfortunately I do not think this will help you in this case, as you cannot
>> distinguish the parts of the TU coming from system header files and the
>> parts coming from user files at the AST level.
>>
>> Ok, that's a setback i should have in mind. When you say "they allow you
>> to run a matcher on the specified node, not the whole AST." you mean
>> something like this?:
>>
>> Result.Nodes.getNodeAs<clang::ForStmt>("forLoop"))
>>
>> This is the way I retrieve the nodes I need to match at this moment.
>>
>> The problem for me is that I'll have to make some source-to-source
>> translations: sometimes I'll have to modify the .cpp file and sometimes the
>> .h (or even both of them) For instance, if i want to know if a certain
>> method is declared as "virtual", I would need to examinate the .h file.
>> Thus, I cannot exclude all .h files. So, how can I manage this?
>>
>> *> I have seen that every file has "id" and, for instance, instead of
>> using "isInSystemHeader" and "isInExternCSystemHeader" could i do the next?:
>> *
>> *
>> *
>> I'm not sure I understand what you're trying to do here... As the error
>> you're getting, it's because getSourceManager is missing the paranthesis,
>> i.e. the () that would indicate it's a method call.
>>
>> What I was trying to do is to examinate the nodes only from the file
>> provided by the user in the execution (for instance, if I run
>> bin/default-constructor test.cpp, I only want the nodes from test.cpp) I
>> tought that with member getMainFileID() I would achieve what I wanted, but
>> this isn't working as expected (sorry for the error of getSourceManager(),
>> but I tested it really quick and late only to write the message). I have
>> also tried with:
>> if (!Context->getSourceManager().isInSystemHeader(FullLocation) && !
>> Context->getSourceManager().isInExternCSystemHeader(FullLocation)){
>> ...
>> }
>>
>> but it is still matching nodes in other files, such as ostream,
>>  bits/basic_ios.h or bits/streambuf_interator.h because I included the
>> iostream header. I need to avoid all these nodes, but I don't know how to
>> do it.
>>
>> Yes, that's quite possible, as I'm using clang 3.2. Nonetheless, you
>> should be able to figure out what the issue is, as I've given you a draft
>> (a pattern, if you will).
>>
>> Ok. I'm going to check this like you taugth me ;)
>>
>> And a last question if you don't mind. I based my examples for the moment
>> in the matcher shown in:
>> http://clang.llvm.org/docs/LibASTMatchersTutorial.html
>> But you told me that it's possible to merge the usage of Matchers and
>> RecursiveASTVisitor as in:
>> http://clang.llvm.org/docs/RAVFrontendAction.html
>> I see that I can retrieve some nodes using matchers and then use a
>> RecursiveASTVisitor on that nodes, but I can't clearly see the contrary: if
>> I'm visiting only a kind of node, I know that I can directly use the
>> methods of that class, but how could I use a matcher in the same way as in
>> the example below?:
>>
>> virtual void run(const MatchFinder::MatchResult &Result) {    if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop"))      FS->dump();  }
>>
>> I hope you can understand what I mean.
>>
>> Thank you for all your help,
>>
>> Pedro
>>
>> *El dia 21 abr 2013 01:43, Gábor Kozár <kozargabor at gmail.com> escribió:*
>>
>> Hi,
>> > *The default constructor of C is also matched as there is an implicit
>> call to the default constructor of class A (and effectively, this is an
>> expression and not a declaration as I said in the last message). So, I've
>> been thinking about it and, though I don't have the solution, I'm quite
>> sure we have to change "anything()" inside "hasAnyConstructorInitializer()"
>> to avoid this exception. Any suggestion?*
>> *
>> *
>> This is indeed something I haven't considered, but should be easy to fix.
>> Looking at the documentation for CXXCtorInitializer, you'll see that
>> there's a member called isBaseInitializer(). The other thing you'll need to
>> check (probably, if that is what you need) for is whether the base ctor
>> call is implicit, which is probably done best by constraining the
>> CXXConstructExpr with argumentCountIs(0). Putting together a custom matcher
>> using these should be simple.*
>> *
>> Also keep in mind that if you put together a generic and useful enough
>> matcher, you should totally contribute it as a patch, so that others in
>> need of a similar thing have it available in the future.
>> > *On the other hand, I've been trying to use the methods you told me,
>> but I have to use those methods after the matcher execution, haven't I?
>> This is a bit inefficiently as the mathcer is looking up in some files that
>> are not needed.*
>> *
>> *
>> Yes, you need to use these in the matcher callback. It is indeed
>> inefficient, but we've been unable to come up with any better solution. The
>> problem is in the underlying compiler technology, i.e. the nature of header
>> files.*
>> *
>> > *Is it possible to search for nodes only in some files indicated by
>> the user?*
>> *
>> *
>> Sure, take a look at the clang::ast_matchers::match functions - they
>> allow you to run a matcher on the specified node, not the whole AST.
>> Unfortunately I do not think this will help you in this case, as you cannot
>> distinguish the parts of the TU coming from system header files and the
>> parts coming from user files at the AST level.
>> *
>> *
>> *> I have seen that every file has "id" and, for instance, instead of
>> using "isInSystemHeader" and "isInExternCSystemHeader" could i do the next?:
>> *
>> *
>> *
>> I'm not sure I understand what you're trying to do here... As the error
>> you're getting, it's because getSourceManager is missing the paranthesis,
>> i.e. the () that would indicate it's a method call.
>> > *Umm... What a strange thing... I will get over this one more time and
>> see if I did something wrong.
>> Maybe something is missing or is different in AStMatchersInternal or
>> ASTMatchersMacros.*
>> Yes, that's quite possible, as I'm using clang 3.2. Nonetheless, you
>> should be able to figure out what the issue is, as I've given you a draft
>> (a pattern, if you will).*
>> *
>> Good luck!
>> Gabor
>>
>>
>> 2013/4/21 Pedro Delgado Perez <pedro.delgadoperez at mail.uca.es>
>>
>>> Hi and thanks again,
>>>
>>> I clearly expressed incorretly the problem. I'll try to explain it more
>>> in detail:
>>>
>>> If we have the classes below:
>>>
>>> class A{
>>>     public: A(){}
>>> };
>>>
>>> class B: public A{
>>>     public: int b, h;
>>>         B():A(){b=0; h=0;}
>>> };
>>>
>>> class C: public A{
>>>     public C(){}
>>> };
>>>
>>> I want my matcher retrieves ONLY the default constructor declaration of
>>> B. However this is what happened with the matcher you proposed me:
>>>
>>> CXXConstructorDecl 0xa1f6080
>>> </home/pedro/clang-llvm/build/testClases.cpp:14:3, col:25> B 'void (void)'
>>> |-CXXCtorInitializer 'class A'
>>> | |-CXXConstructExpr 0xa1f6608 <col:8, col:10> 'class A' 'void (void)'
>>> `-CompoundStmt 0xa1f6710 <col:11, col:25>
>>>   |-BinaryOperator 0xa1f6698 <col:12, col:16> 'int' lvalue '='
>>>   | |-MemberExpr 0xa1f6660 <col:12> 'int' lvalue ->b 0xa1f6100
>>>   | | `-CXXThisExpr 0xa1f6650 <col:12> 'class B *' this
>>>   | `-IntegerLiteral 0xa1f6680 <col:16> 'int' 0
>>>   `-BinaryOperator 0xa1f66f8 <col:19, col:23> 'int' lvalue '='
>>>     |-MemberExpr 0xa1f66c0 <col:19> 'int' lvalue ->h 0xa1f6140
>>>     | `-CXXThisExpr 0xa1f66b0 <col:19> 'class B *' this
>>>     `-IntegerLiteral 0xa1f66e0 <col:23> 'int' 0
>>> Found declaration at 14:3
>>> CXXConstructorDecl 0xa1f68b0
>>> </home/pedro/clang-llvm/build/testClases.cpp:25:3, col:7> C 'void (void)'
>>> |-CXXCtorInitializer 'class A'
>>> | |-CXXConstructExpr 0xa1f6c08 <col:3> 'class A' 'void (void)'
>>> `-CompoundStmt 0xa1f6c58 <col:6, col:7>
>>> Found declaration at 25:3
>>>
>>> The default constructor of C is also matched as there is an implicit
>>> call to the default constructor of class A (and effectively, this is an
>>> expression and not a declaration as I said in the last message). So, I've
>>> been thinking about it and, though I don't have the solution, I'm quite
>>> sure we have to change "anything()" inside "hasAnyConstructorInitializer()"
>>> to avoid this exception. Any suggestion?
>>>
>>>
>>> On the other hand, I've been trying to use the methods you told me, but
>>> I have to use those methods after the matcher execution, haven't I? This is
>>> a bit inefficiently as the mathcer is looking up in some files that are not
>>> needed. Is it possible to search for nodes only in some files indicated by
>>> the user? Normally, a class is declared in a .h file and defined in the
>>> .cpp file and i would like to search in both of them.
>>> I have seen that every file has "id" and, for instance, instead of using
>>> "isInSystemHeader" and "isInExternCSystemHeader" could i do the next?:
>>>
>>> class DefaultConstructor : public MatchFinder::MatchCallback {
>>> public :
>>>   virtual void run(const MatchFinder::MatchResult &Result) {
>>>   ASTContext *Context = Result.Context;
>>>   FileID mainFileID = Context->getSourceManager.getMainFileID();
>>>   if (const CXXConstructorDecl *FS =
>>> Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("methods")){
>>>       FullSourceLoc FullLocation =
>>> Context->getFullLoc(FS->getLocStart());
>>>       if (FullLocation.isValid() && FullLocation.getFileID() ==
>>> mainFileID)
>>>         ... ...
>>>     }
>>>   }
>>> };
>>>
>>> ( I got an error with this: reference to non-static member function must
>>> be called
>>>   FileID mainFileID = (Context->getSourceManager).getMainFileID();
>>>                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~ )
>>>
>>> > *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?
>>>
>>> *
>>> I did test it, and worked fine for me. Not sure what could be the issue.
>>>
>>> Umm... What a strange thing... I will get over this one more time and
>>> see if I did something wrong.
>>> Maybe something is missing or is different in AStMatchersInternal or
>>> ASTMatchersMacros.
>>>
>>> Thanks,
>>>
>>> Pedro.
>>>
>>> *El dia 19 abr 2013 16:28, Gábor Kozár <kozargabor at gmail.com> escribió:*
>>>
>>> Hi,
>>>
>>> > *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?
>>>
>>> *
>>>
>>> I did test it, and worked fine for me. Not sure what could be the issue.
>>>
>>> > *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:*
>>>
>>> I believe this is what you need then, as Manuel suggested:
>>>
>>> constructorDecl(isDefinition(), parameterCountIs(0),
>>> unless(isImplicit()),
>>>         anyOf(hasAnyConstructorInitializer(anything()),
>>> has(compoundStmt(has(stmt())))));
>>> How you compose your matchers dictate how they will behave. Lets take a
>>> simple example: functionDecl(isDefinition()). Here the fact that
>>> isDefinition() was given as a parameter to functionDecl() indicates that it
>>> refines that matcher, i.e. imposes further conditions that have to be met
>>> in order for a node to be matched.
>>> Now with this logic, lets look at what you tried:
>>> withInitializer(constructorDecl(isImplicit()))
>>>
>>> This means something like "an initializer that is an implicit
>>> constructor declaration" - which obviously makes no sense, and thanks to
>>> template voodoo magic, it doesn't compile either. The reason is that
>>> withInitializer expects a Matcher<Expr>, that is, a matcher that matches
>>> certain Exprs (that meet a certain criteria). constructorDecl() yields a
>>> Matcher<CXXConstructorDecl>, because it is a matcher that accepts
>>> CXXConstructorDecl objects.
>>>
>>> > *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?*
>>>
>>> I'm not sure what you mean by "implicit" methods here. Obviously you'll
>>> get matches in header files as well, most notably, system header files.
>>> SourceManager::isInSystemHeader and isInExternCSystemHeader is what you're
>>> looking for if you want to avoid that - you'll place such a check in your
>>> matcher callback function.
>>>
>>> Gabor
>>>
>>>
>>> 2013/4/19 Pedro Delgado Perez <pedro.delgadoperez at mail.uca.es>
>>>
>>>> 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.
>>>>
>>>> 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/20130424/4b93ef41/attachment.html>


More information about the cfe-dev mailing list