<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 18, 2015 at 5:17 PM, Richard <span dir="ltr"><<a href="mailto:legalize@xmission.com" target="_blank">legalize@xmission.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><br>
In article <<a href="mailto:CAAbBDD_8q2LS4V5hdBrkCjvL5SagR3Y%2BbtLrwfekqn08k7A29g@mail.gmail.com" target="_blank">CAAbBDD_8q2LS4V5hdBrkCjvL5SagR3Y+btLrwfekqn08k7A29g@mail.gmail.com</a>>,<br>
<span>    Jonathan Coe <<a href="mailto:jbcoe@me.com" target="_blank">jbcoe@me.com</a>> writes:<br>
<br>
> I'm finding it very hard to find information and examples on using the<br>
> matchers and API to do a number of things.<br>
<br>
</span>It took me a while to wrap my head around the matcher API, but I think<br>
I've got a handle on it now.</blockquote><div><br></div><div>For me, the insight after staring at the API for a while is that it is basically a tree-interpreter pattern, except that the "tree" that is "interpreted" actually ends up open-coded at compile time. E.g. allOf(foo(), bar()) basically is (in pseudocode pointer-leaky OO style):<br><br></div><div>class AbstractTreeInterpMatcher {<br></div><div>  virtual bool matches(Node *) = 0;  <br></div><div>};<br><br></div><div>class allOf : public AbstractTreeInterpMatcher {<br></div><div>  vector<AbstractTreeInterpMatcher*> SubMatchers;<br></div><div>  bool matches(Node *N) override {<br></div><div>    for (auto *M : SubMatchers)<br></div><div>      if (!M->matches(N))<br></div><div>        return false;<br></div><div>    return true;<br></div><div>  }<br></div><div>};<br><br></div><div>class foo : public AbstractTreeInterpMatcher {<br></div><div>  bool matches(Node *N) override { .... };<br></div><div>};<br><div>class bar : public AbstractTreeInterpMatcher {<br></div><div>  bool matches(Node *N) override { .... };<br></div>};<br></div><div><br></div><div>Then the matcher allOf(foo(), bar()) is basically `auto *M = new allOf{{new foo(), new bar()}}`, and the root matching process is just a call to `M->matches(TheNode)`. There's a bit more state that filters through in reality, but that's the essence of it.<br><br></div><div>The actual implementation is actually pretty close to what I have above, but less Java-like (but with lots of template and macro stuff; e.g. instead of AbstractTreeInterpMatcher there is a MatcherInterface<T>). I get the impression that the pattern is a lot more familiar when phrased in this textbook OO style (since there is a very clear "object recursion" happening), while the template/macro generated version is more difficult to see through since it is not as clear what is being recursed on (even though under the hood it is doing the exact same thing).</div><div><br></div><div>E.g. looking at <a href="http://clang.llvm.org/docs/LibASTMatchers.html" target="_blank">http://clang.llvm.org/docs/LibASTMatchers.html</a>,<br><br>VariadicDynCastAllOfMatcher<Base, Derived><br><br></div><div>is really just allOf together with (in pseudocode, but this could in fact be written essentially like this):<br><br><div>class dynCastMatcher : public AbstractTreeInterpMatcher {<br></div><div>  int BaseKindNum;</div><div>  int DerivedKindNum;</div><div>  bool matches(Node *N) override {</div><div><div>    switch (BaseKindNum) {<br></div><div>      case DeclKind: return N->getAsDecl() && N->getAsDecl()->getKind() == DerivedKindNum;<br></div><div>      case StmtKind: return N->getAsStmt() && N->getAsStmt()->getStmtClass() == DerivedKindNum;<br></div><div>      case TypeKind: return N->getAsType() && N->getAsType()->getTypeClass() == DerivedKindNum;<br></div><div>      default: return false;<br></div><div>    }</div></div><div>  };<br></div>};</div><div><br></div><div>then the code:</div><div><br></div><div>namespaceDecl(foo(), bar())</div><div><br></div><div>becomes</div><div><br></div><div>new allOf{{new dynCastMatcher{DeclKind, NamespaceDeclKind}, new foo(), new bar()}}</div><div><br></div><div>The role of `Node *` in this example is basically what clang::ast_type_traits::DynTypedNode does (see <a href="http://clang.llvm.org/doxygen/classclang_1_1ast__type__traits_1_1DynTypedNode.html" target="_blank">http://clang.llvm.org/doxygen/classclang_1_1ast__type__traits_1_1DynTypedNode.html</a>).</div><div><br></div><div>-- Sean Silva<br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">  I've got two reviews up with some new<br>
checks for clang-tidy:<br>
<br>
Add readability-simplify-boolean-expr check to clang-tidy<br>
<<a href="http://reviews.llvm.org/D7648" target="_blank">http://reviews.llvm.org/D7648</a>><br>
<br>
Add readability-remove-void-arg check to clang-tidy<br>
<<a href="http://reviews.llvm.org/D7639" target="_blank">http://reviews.llvm.org/D7639</a>><br>
<br>
(This is based on an earlier version I had as a tutorial on github:<br>
<<a href="https://github.com/LegalizeAdulthood/remove-void-args" target="_blank">https://github.com/LegalizeAdulthood/remove-void-args</a>>.  That<br>
tutorial needs updating to be based on clang-tidy and my final version<br>
of the check.)<br>
<span><br>
> I wondered if anyone knew of a<br>
> good source of introductory info that goes into some depth?<br>
<br>
</span>Definitely look at the links that Manuel Klimek posted.  Additionally,<br>
I find myself coming back to this page all the time:<br>
<<a href="http://clang.llvm.org/docs/LibASTMatchersReference.html" target="_blank">http://clang.llvm.org/docs/LibASTMatchersReference.html</a>><br>
<span><br>
> Eli Bendersky's<br>
> blogs are very good but I need more detail on specific things: I'm keen to<br>
> use matchers to match standard library types by name but that seems hard.<br>
<br>
</span>Have you tried using the hasName narrowing matcher?<br>
<span><br>
> I'm stuck on both:<br>
><br>
><br>
</span>>    - MissingNameSpaceStd can't cope with pointers, references or template<br>
<span>>    types like std::vector<std::pair<int,int>><br>
><br>
</span>>    - PropagateConst can't match smart pointers. Ideally it would do so by<br>
<span>>    duck-typing but I'd settle for name matching for now.<br>
<br>
</span>I find that I go back and forth between the AST matcher reference page,<br>
clang-query, and exploring the API by navigating in CLion.  If you<br>
haven't used clang-query yet, then build that from clang-tools-extra<br>
trunk and make sure you have the line edit library installed first.<br>
Without lineedit, you don't get tab completion so you can explore<br>
valid narrowing matchers and child matchers for the match expression<br>
you're building.  This is VERY useful in exploring what can be done<br>
with the matchers.<br>
<br>
However, not every single attribute or node traversal is exposed as a<br>
matcher.  For instance, just the other day I was exploring how you<br>
would identify constexpr functions.  Well, you can do it in code by<br>
matching a functionDecl and calling isConstexpr() in code on the<br>
matched node, but it sure would be nice to have this in a matcher so<br>
that your callback isn't invoked at all.<br>
<br>
So, matchers are a work in progress like most things in software.  The<br>
matchers that allow you to identify code expanded in the main file for<br>
the compilation unit appeared in clang trunk but weren't in the 3.5<br>
release.  Things are being added based on what's useful when writing<br>
checks in clang-tidy or other libtooling code.<br>
<br>
I see that you added a FileCheck test for your clang-tidy check.  This<br>
is great!  What I do is drive things forward one test case at a time<br>
from the FileCheck source file.  First I add a CHECK-MESSAGES to<br>
ensure that the proper diagnostic is being issued.  Then I add<br>
CHECK-FIXES to verify that the proper substitution is taking place.<br>
In between a failing test case and a passing test case is heavy use of<br>
the AST matcher reference page and clang-query.<br>
<span><font color="#888888">--<br>
"The Direct3D Graphics Pipeline" free book <<a href="http://tinyurl.com/d3d-pipeline" target="_blank">http://tinyurl.com/d3d-pipeline</a>><br>
     The Computer Graphics Museum <<a href="http://ComputerGraphicsMuseum.org" target="_blank">http://ComputerGraphicsMuseum.org</a>><br>
         The Terminals Wiki <<a href="http://terminals.classiccmp.org" target="_blank">http://terminals.classiccmp.org</a>><br>
  Legalize Adulthood! (my blog) <<a href="http://LegalizeAdulthood.wordpress.com" target="_blank">http://LegalizeAdulthood.wordpress.com</a>><br>
</font></span><div><div>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@cs.uiuc.edu" target="_blank">cfe-dev@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
</div></div></blockquote></div><br></div></div>