[cfe-dev] ASTMatchers: isVirtual and isOverride
Manuel Klimek
klimek at google.com
Wed May 8 08:01:27 PDT 2013
On Wed, May 8, 2013 at 4:38 PM, Vane, Edwin <edwin.vane at intel.com> wrote:
>
>
> > -----Original Message-----
> > From: Vane, Edwin
> > Sent: Wednesday, May 08, 2013 10:26 AM
> > To: 'Pedro Delgado Perez'; klimek at google.com; kozargabor at gmail.com
> > Cc: cfe-dev at cs.uiuc.edu
> > Subject: RE: [cfe-dev] ASTMatchers: isVirtual and isOverride
> >
> >
> >
> > > -----Original Message-----
> > > From: Pedro Delgado Perez [mailto:pedro.delgadoperez at mail.uca.es]
> > > Sent: Tuesday, May 07, 2013 8:22 AM
> > > To: klimek at google.com; Vane, Edwin; kozargabor at gmail.com
> > > Cc: cfe-dev at 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...
>
> >
> > >
> > >
> > >
> > > 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 at intel.com>
> escribió:
> > >
> > > Given your description, I'm not sure matchers are what you want. If
> > > you just want to print information on certain types of nodes, you
> > > could use a RecursiveASTVisitor for that.
> > >
> > > However, if what you're looking for is a little more complex then
> > > matchers may be what you want after all.
> > >
> > > As for the two classes, you want to use tooling::MatchFinder as
> shown
> > > in the tutorial. The other is just an implementation detail of the
> > > match finding code.
> > >
> > > newASTConsumer() is a function that's required to be defined for
> > > objects passed to newFrontendActionFactory(). You don't need to
> implement
> > it.
> > > It's implemented by MatchFinder. Again, it's an implementation detail
> > > you don't need to worry about at this point.
> > >
> > > The use of ASTConsumers is not necessary if you're using
> MatchFinder
> > > and ClangTool as described in the tutorial. MatchFinder is an
> > > abstraction around RecursiveASTVisitor so all that stuff in
> > > RecursiveASTVisitor you'd normally have to use is actually hidden away.
> > >
> > > I think you should first decide which route you want to go:
> > > MatchFinder or RecursiveASTVisitor. The first question I'd ask is: how
> > > hard is it to find the nodes I want to print info on in the AST. If
> all I want is
> > every for loop that's easy.
> > > If I want for loops within member functions of a specific class,
> > > that's hard and an excellent use case for ASTMatchers.
> > >
> > > -----Original Message-----
> > > From: cfe-dev-bounces at cs.uiuc.edu [mailto:cfe-dev-
> > > bounces at cs.uiuc.edu] On
> > > Behalf Of Pedro Delgado Perez
> > > Sent: Monday, May 06, 2013 12:58 PM
> > > To: klimek at google.com; kozargabor at gmail.com
> > > Cc: cfe-dev at cs.uiuc.edu
> > > Subject: Re: [cfe-dev] ASTMatchers: isVirtual and
> isOverride
> > >
> > > Hi,
> > >
> > > I need your help again. Look, in my tool I was trying to
> use the
> > > syntax that's
> > > shown here:
> > >
> > > http://clang.llvm.org/docs/LibASTMatchersTutorial.html
> > >
> > > Namely I'm referring to this part:
> > >
> > > int main(int argc, const char **argv) {
> > > CommonOptionsParser OptionsParser(argc, argv);
> > > ClangTool Tool(OptionsParser.getCompilations(),
> > > OptionsParser.getSourcePathList());
> > >
> > > LoopPrinter Printer;
> > > MatchFinder Finder;
> > > Finder.addMatcher(LoopMatcher, &Printer);
> > >
> > > return Tool.run(newFrontendActionFactory(&Finder));
> > > }
> > >
> > > However, now I want to create a object "Printer" with
> different
> > > features
> > > depending on the arguments provided in command line. So I
> > was
> > > thinking on
> > > implement a factory method pattern to create a different
> > LoopPrinter
> > > object:
> > > class OptionsFactory {
> > > public:
> > > LoopPrinter getOption() {
> > > if(...)
> > > return LoopPrinter(attribute1, attribute2);
> > > else
> > > return LoopPrinter(attribute1);
> > > }
> > > };
> > >
> > > I was searching for a better solution and there are some
> things
> > that
> > > I can't
> > > completely understand.
> > >
> > > - Why are there two classes MatchFinder:
> > >
> > > http://clang.llvm.org/doxygen/classclang_1_1tooling_1_1MatchFinder
> .
> > > html
> > >
> > > http://clang.llvm.org/doxygen/classclang_1_1ast__matchers_1_1Matc
> > > hFinder.
> > > html
> > >
> > > - What the method in ast_matchers:MatchFinder
> > >
> > > clang::ASTConsumer
> > >
> > > <http://clang.llvm.org/doxygen/classclang_1_1ASTConsumer.html> *
> > >
> > > newASTConsumer
> > >
> > > <http://clang.llvm.org/doxygen/classclang_1_1ast__matchers_1_1Mat
> > > chFinder
> > > .html#a4807049e6e39572d19ff127406df3d81> ()
> > >
> > > is used for? I see we can 'associate' an ASTConsumer to the
> > Frontend
> > > as in:
> > > http://clang.llvm.org/docs/RAVFrontendAction.html
> > >
> > > but, is this possible using Matchers? Would it have any
> sense to
> > > create an
> > > ASTConsumer in my class OptionsFactory?
> > >
> > > I have improved a lot since you last helped me, but clang
> is too
> > > big!
> > >
> > > By the way, do you know how to use CommandLine? I posted a
> > new
> > > thread
> > >
> > > http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-
> > > May/029473.html
> > >
> > > If you know how to solve that problem, please, let me know.
> > >
> > > Thanks in advance,
> > >
> > > Pedro.
> > >
> > >
> > > El dia 27 abr 2013 18:39, Manuel Klimek <klimek at google.com
> >
> > > escribió:
> > >
> > > On Sat, Apr 27, 2013 at 6:36 PM, Gábor Kozár
> > > <kozargabor at gmail.com> wrote:
> > >
> > >
> > >
> > > 2013/4/27 Manuel Klimek <klimek at google.com>
> > >
> > >
> > > Just use the empty string for binding and getNodeAs :)
> > >
> > >
> > > That would potentially lead to confusion when there are
> more
> > > nodes bound, but the programmer forgot to supply the proper
> > name. In
> > > my
> > > suggestion, the parameterless getNodeAs would have an
> assert
> > to
> > > check there is
> > > exactly one node bound (and whose name is the default
> name).
> > >
> > > If you put everything behind constants, I think it'll be
> easy
> > enough
> > > to see
> > > what's happening - and that's a generally good strategy
> > anyway, as
> > > you get a
> > > compile error if you mistype...
> > > Thus, I think it'd not add enough value to special case the
> > > interface.
> > >
> > >
> > >
> > >
> > > 2013/4/27 Manuel Klimek <klimek at google.com>
> > >
> > >
> > > On Sat, Apr 27, 2013 at 6:28 PM, Gábor Kozár
> > > <kozargabor at gmail.com> wrote:
> > >
> > > Hi,
> > > 2013/4/26 Pedro Delgado Perez
> > > <pedro.delgadoperez at mail.uca.es>
> > >
> > >
> > > Hehehe... I found the problem with
> > > this. I was binding wrongly the matcher! I used a id in the
> > matcher
> > > thas was
> > > different from the id in the function that retrieves the
> nodes... I
> > > think this will be
> > > a typical mistake for newbies...
> > >
> > > Ah, yes, that happens a lot to me as well. Now
> > > that I think about it, it might be worthwhile adding a
> > parameterless
> > > .bind() and
> > > .getNodeAs<T>() for situations where only one node is
> bound.
> > > Should be fairly
> > > trivial, but also not all that useful...
> > >
> > > Just use the empty string for binding and getNodeAs :)
> > >
> > >
> > >
> > > 2013/4/26 Pedro Delgado Perez
> > > <pedro.delgadoperez at mail.uca.es>
> > >
> > >
> > > Thanks both! Now I can see all this
> > > much clearer and I have the enough knowledge to start out
> with
> > > clang.
> > >
> > >
> > > You're welcome. Good luck!
> > >
> > >
> > > 2013/4/25 Manuel Klimek <klimek at google.com>
> > >
> > >
> > > And btw thanks a lot for all the great user support you're
> giving
> > > here!
> > >
> > >
> > > Thank you, I'm happy to help. Clang is a great project!
> > >
> > > As soon as the university term is over, I'm also planning
> on
> > trying
> > > to
> > > contribute code-wise, mainly to the Static Analyzer but I
> guess
> > also
> > > on just about
> > > anything that catches my attention. :) I'm quite excited -
> this is
> > > going to be the
> > > first open source project I contribute to.
> > > Gabor
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130508/c061e115/attachment.html>
More information about the cfe-dev
mailing list