[cfe-dev] The QtReslot Clang plugin
Sean Silva via cfe-dev
cfe-dev at lists.llvm.org
Wed Feb 22 00:51:27 PST 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.llvm.org/pipermail/cfe-dev/attachments/20170222/797fc61f/attachment.html>
More information about the cfe-dev
mailing list