[Interest] [cfe-dev] The QtReslot Clang plugin

Sean Silva chisophugis at gmail.com
Wed Feb 22 09:51:27 CET 2017


On Wed, Feb 15, 2017 at 5:39 AM, Richard Braun via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> On Wed, Feb 15, 2017 at 10:00:25AM +0000, Manuel Klimek wrote:
> > Both of these projects duplicate a lot of code from clang-tidy and the
> AST
> > matcher infrastructure in clang.
> >
> > I'd be curious what the reasons are to not use those, so we can try to
> > address them :)
>
> I tried using matchers at some point, but couldn't understand the
> processing flow and felt a lot more comfortable with the current result
> despite writing more code.
>


The thing that made it click for me is that the way it works is basically a
classic "tree interpreter" type pattern. I wrote up some ideas for
improving the documentation a long time ago when I was staring at it,
though I don't think it ever made it to the mailing list (oops!).

https://docs.google.com/document/d/1foYulTnUXumiuGzzgoAbGQLFJerk4
X1WjR2cKBUUMJI/edit?usp=sharing

I think this started out as a reply in an email and then I saved it into a
document as it morphed into ideas for implementing the dynamic AST matches
in a way that doesn't require stamping out huge amounts of text (as in
machine code; essentially it instantiates each matcher separately resulting
in huge .o files instead of using a "data-driven" approach based on the
node type enums). Don't really clearly remember though.

In a more traditional OO implementation of the tree interpreter pattern it
would look something like (pseudocode):


class MatcherBase {
  std::vector<std::unique_ptr<MatcherBase>> Children;

  virtual bool matches(ASTNode &Node) = 0;

...

}

class AllOfMatcher : public MatcherBase {
  bool matches(ASTNode &Node) override {
    for (auto &Matcher : Children)
      if (!Matcher->matches(Node))
        return false;
    return true;
  }

...

}

std::unique_ptr<MatcherBase> allOf(std::vector<std::unique_ptr<MatcherBase>>
Children) {
  return make_unique<AllOfMatcher>(Children);
}

class CallExprMatcher : public AllOfMatcher {
  bool matches(ASTNode &Node) override {
    if (!AllOfMatcher::matches(Node))
      return false;
    return isa<CallExpr(Node);
  }

...

}


std::unique_ptr<MatcherBase> callExpr(std::vector<std::unique_ptr<MatcherBase>>
Children) {
  return make_unique<CallExprMatcher>(Children);
}


The implementation actually looks essentially like this, except that it is
static instead of dynamic and so the body of the `matches` virtual method
essentially ends up inside templates and macros somewhere and isn't
actually a virtual function)

For example, if you look at the implementation of the `callExpr` matcher,
you see:

```
const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr;
```

"dyn_cast AllOfMatcher" does pretty much what you expect based on looking
at the toy OO pseudocode above. (the need to pass the Stmt template
argument is not that relevant; it could probably be inferred by following
the inheritance chain from CallExpr up to the top of the inheritance
hierarchy)




(I've been totally out of the loop for quite a while for all the stuff that
Manuel et al. have been doing with Clang tooling; so all of this is subject
to being out of date or just remembered incorrectly)

-- Sean Silva


>
> --
> Richard Braun
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20170222/797fc61f/attachment.html>


More information about the Interest mailing list