ASTMatchers: isVirtual and isOverride

Hi again,

Sorry to make so much questions, but I hope a good structure of my tool will save me a lot of time in future.

I’m using something like this in http://clang.llvm.org/docs/LibASTMatchersTutorial.html:

class LoopPrinter : public MatchFinder::MatchCallback {public :  virtual void run(const MatchFinder::MatchResult &Result) {    if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop"))      FS->dump();  }};

So, now I have two questions:

  1. Imagine that I need to print something after all the nodes have been matched. For example, the number of nodes matched. How can I do that?

  2. Imagine that I have two methods within the run method to separate two kind of nodes I want to bind. Something like this:


class LoopPrinter : public MatchFinder::MatchCallback {public :  virtual void run(const MatchFinder::MatchResult &Result) {    applyMatch1();
    applyMatch2();  }

void applyMatch1(){
 if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop__1"))
}

void apply2(){
if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop_2"))
}
};

How does the ‘run’ method behave in this case? I mean that I don’t know if it retrieves, one by one, all the nodes in applyMatch1 and ,after that, all the nodes in applyMatch2 or it matches one in applyMatch1 and then other in applyMatch2 in each iteration. I hope you can understand me because this is very important in my case.

Thanks in advance.

Pedro

El dia 06 may 2013 22:32, “Vane, Edwin” edwin.vane@intel.com escribió:

Hi,

1. Imagine that I need to print something after all the nodes have been matched. For example, the number of nodes matched. How can I do that?

You collect information about the matches into e.g. a vector, and you can use the MatchCallback’s onStartOfTranslationUnit to process the previous TU’s matches.

How does the ‘run’ method behave in this case? I mean that I don’t know if it retrieves, one by one, all the nodes in applyMatch1 and ,after that, all the nodes in applyMatch2 or it matches one in applyMatch1 and then other in applyMatch2 in each iteration.

So the matchers run regardless of whether you ever access the bound nodes. What this means is that your run() method will be called for every match, with the appropriate nodes bound to the names you defined. So a MatchResult only contains information about one single match (i.e. a subtree of the AST, if you will). Hope this clears things up.

Gabor

From: Pedro Delgado Perez [mailto:pedro.delgadoperez@mail.uca.es]
Sent: Tuesday, May 07, 2013 8:22 AM
To: klimek@google.com; Vane, Edwin; kozargabor@gmail.com
Cc: cfe-dev@cs.uiuc.edu
Subject: RE: [cfe-dev] ASTMatchers: isVirtual and isOverride

Hi again,

Sorry to make so much questions, but I hope a good structure of my tool will
save me a lot of time in future.

I'm using something like this in
http://clang.llvm.org/docs/LibASTMatchersTutorial.html:

class LoopPrinter : public MatchFinder::MatchCallback {public : virtual void
run(const MatchFinder::MatchResult &Result) { if (const ForStmt *FS =
Result.Nodes.getNodeAs<clang::ForStmt>("forLoop")) FS->dump(); }};

So, now I have two questions:

1. Imagine that I need to print something after all the nodes have been matched.
For example, the number of nodes matched. How can I do that?

You can just count how many times your match callback is called and then print that number after run() returns.

2. Imagine that I have two methods within the run method to separate two kind
of nodes I want to bind. Something like this:

class LoopPrinter : public MatchFinder::MatchCallback {public : virtual void
run(const MatchFinder::MatchResult &Result) { applyMatch1();
    applyMatch2(); }

void applyMatch1(){
if (const ForStmt *FS =
Result.Nodes.getNodeAs<clang::ForStmt>("forLoop__1"))
}

void apply2(){
if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop_2"))
}
};

I'm not sure what order you're interested in but you can create two match callbacks one to use for each matcher. The callbacks will be called in the order the nodes are found in the tree by doing a depth-first pre-order traversal as is usual for RecursiveASTVisitor. If both matchers match a given node, the callbacks are called in the order they are registered.

What sort of order are you looking for?

From: Vane, Edwin
Sent: Wednesday, May 08, 2013 10:26 AM
To: 'Pedro Delgado Perez'; klimek@google.com; kozargabor@gmail.com
Cc: cfe-dev@cs.uiuc.edu
Subject: RE: [cfe-dev] ASTMatchers: isVirtual and isOverride

> From: Pedro Delgado Perez [mailto:pedro.delgadoperez@mail.uca.es]
> Sent: Tuesday, May 07, 2013 8:22 AM
> To: klimek@google.com; Vane, Edwin; kozargabor@gmail.com
> Cc: cfe-dev@cs.uiuc.edu
> Subject: RE: [cfe-dev] ASTMatchers: isVirtual and isOverride
>
> Hi again,
>
> Sorry to make so much questions, but I hope a good structure of my
> tool will save me a lot of time in future.
>
> I'm using something like this in
> http://clang.llvm.org/docs/LibASTMatchersTutorial.html:
>
>
> class LoopPrinter : public MatchFinder::MatchCallback {public : virtual void
> run(const MatchFinder::MatchResult &Result) { if (const ForStmt *FS =
> Result.Nodes.getNodeAs<clang::ForStmt>("forLoop")) FS->dump(); }};
>
>
> So, now I have two questions:
>
> 1. Imagine that I need to print something after all the nodes have been
matched.
> For example, the number of nodes matched. How can I do that?

You can just count how many times your match callback is called and then print
that number after run() returns.

> 2. Imagine that I have two methods within the run method to separate
> two kind of nodes I want to bind. Something like this:
>
>
>
>
> class LoopPrinter : public MatchFinder::MatchCallback {public : virtual void
> run(const MatchFinder::MatchResult &Result) { applyMatch1();
> applyMatch2(); }
>
> void applyMatch1(){
> if (const ForStmt *FS =
> Result.Nodes.getNodeAs<clang::ForStmt>("forLoop__1"))
> }
>
> void apply2(){
> if (const ForStmt *FS =
> Result.Nodes.getNodeAs<clang::ForStmt>("forLoop_2"))
> }
> };

I'm not sure what order you're interested in but you can create two match
callbacks one to use for each matcher. The callbacks will be called in the order
the nodes are found in the tree by doing a depth-first pre-order traversal as is
usual for RecursiveASTVisitor. If both matchers match a given node, the
callbacks are called in the order they are registered.

What sort of order are you looking for?

Sorry, missed the comment in one of your more recent emails. So you basically want all matches by matcher1 to be found before all matchers by matcher2. I think the easiest way to do this is just have two MatchFinder classes. Add matcher1 and its callback to the first MatchFinder and call run(). Add matcher2 and its callback to the second MatchFinder and call run() after the first run() returns. You won't have to reparse the file but you will have to traverse the AST twice. There's not much you can do about this given the order you want. However, if the second matcher has no deps on the information collected by matcher1 you could just get away with a single MatchFinder and two callbacks that just store their finds in two vectors which you process after run returns.

> From: Vane, Edwin
> Sent: Wednesday, May 08, 2013 10:26 AM
> To: 'Pedro Delgado Perez'; klimek@google.com; kozargabor@gmail.com
> Cc: cfe-dev@cs.uiuc.edu
> Subject: RE: [cfe-dev] ASTMatchers: isVirtual and isOverride
>
>
>
> > From: Pedro Delgado Perez [mailto:pedro.delgadoperez@mail.uca.es]
> > Sent: Tuesday, May 07, 2013 8:22 AM
> > To: klimek@google.com; Vane, Edwin; kozargabor@gmail.com
> > Cc: cfe-dev@cs.uiuc.edu
> > Subject: RE: [cfe-dev] ASTMatchers: isVirtual and isOverride
> >
> > Hi again,
> >
> > Sorry to make so much questions, but I hope a good structure of my
> > tool will save me a lot of time in future.
> >
> > I'm using something like this in
> > http://clang.llvm.org/docs/LibASTMatchersTutorial.html:
> >
> >
> > class LoopPrinter : public MatchFinder::MatchCallback {public :
virtual void
> > run(const MatchFinder::MatchResult &Result) { if (const ForStmt *FS

> > Result.Nodes.getNodeAs<clang::ForStmt>("forLoop")) FS->dump();
}};
> >
> >
> > So, now I have two questions:
> >
> > 1. Imagine that I need to print something after all the nodes have been
> matched.
> > For example, the number of nodes matched. How can I do that?
>
> You can just count how many times your match callback is called and then
print
> that number after run() returns.
>
> > 2. Imagine that I have two methods within the run method to separate
> > two kind of nodes I want to bind. Something like this:
> >
> >
> >
> >
> > class LoopPrinter : public MatchFinder::MatchCallback {public :
virtual void
> > run(const MatchFinder::MatchResult &Result) { applyMatch1();
> > applyMatch2(); }
> >
> > void applyMatch1(){
> > if (const ForStmt *FS =
> > Result.Nodes.getNodeAs<clang::ForStmt>("forLoop__1"))
> > }
> >
> > void apply2(){
> > if (const ForStmt *FS =
> > Result.Nodes.getNodeAs<clang::ForStmt>("forLoop_2"))
> > }
> > };
>
> I'm not sure what order you're interested in but you can create two match
> callbacks one to use for each matcher. The callbacks will be called in
the order
> the nodes are found in the tree by doing a depth-first pre-order
traversal as is
> usual for RecursiveASTVisitor. If both matchers match a given node, the
> callbacks are called in the order they are registered.
>
> What sort of order are you looking for?

Sorry, missed the comment in one of your more recent emails. So you
basically want all matches by matcher1 to be found before all matchers by
matcher2. I think the easiest way to do this is just have two MatchFinder
classes. Add matcher1 and its callback to the first MatchFinder and call
run(). Add matcher2 and its callback to the second MatchFinder and call
run() after the first run() returns. You won't have to reparse the file but
you will have to traverse the AST twice. There's not much you can do about
this given the order you want. However, if the second matcher has no deps
on the information collected by matcher1 you could just get away with a
single MatchFinder and two callbacks that just store their finds in two
vectors which you process after run returns.

What is often faster is to produce a superset of the information needed
during the traversal / match phase, and then combine / filter the results
after everything's done...