steveire created this revision. steveire added a reviewer: aaron.ballman. Herald added a project: clang. Herald added a subscriber: cfe-commits. steveire requested review of this revision.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D91639 Files: clang/docs/LibASTMatchersReference.html
Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -96,6 +96,337 @@ </pre> </p> +<!-- ======================================================================= --> +<h2 id="traverse-mode">Traverse Mode</h2> +<!-- ======================================================================= --> + +<p>The default mode of operation of AST Matchers visits all nodes in the AST, +even if they are not spelled in the source. This is AsIs mode. This mode is +hard to use correctly and requires more development iteration because it means +that the user must write AST Matchers to explicitly traverse or ignore nodes +which are not visible.</p> + +<p>In addition, because template instantations are matched in the default mode, +transformations can be accidentally made to template declarations. Finally, +because implicit nodes are matched by default, transformations can be made on +entirely incorrect places in the code.</p> + +<p>For these reasons, it is possible to ignore AST nodes which are not spelled in +the source using the IgnoreUnlessSpelledInSource mode. This is likely to be far +less error-prone for users who are not already very familiar with the AST. It is +also likely to be less error-prone for experienced AST users, as difficult cases +do not need to be encountered and matcher expressions adjusted for these +cases.</p> + +<p>In clang-query, the mode can be changed with +<pre> +set traversal IgnoreUnlessSpelledInSource +</pre> +</p> +This affects both matchers and AST dump output in results. + +<p>When using the C++ API such as in clang-tidy checks, the traverse() matcher +is used to set the mode: +<pre> +Finder->addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, + returnStmt(hasReturnArgument(integerLiteral(equals(0)))) + ), this); +</pre> +</p> +<p>The following table compares the AsIs mode with the IgnoreUnlessSpelledInSource +mode:</p> + + +<style> +.traverse_compare, .traverse_compare td, .traverse_compare th { + border: 1px solid black; + border-collapse: collapse; +} +</style> +<table class="traverse_compare"> +<tr> +<th></th><th>AsIs</th><th>IgnoreUnlessSpelledInSource</th> +</tr> +<tr> + <td>AST dump of func1: +<pre> +struct B +{ + B(int); +}; + +B func1() { + return 42; +} +</pre> + + </td> + <td> +C++98 dialect: +<pre> +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-ImplicitCastExpr + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 +</pre> +C++11, C++14 dialect: +<pre> +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-ExprWithCleanups + `-CXXConstructExpr + `-MaterializeTemporaryExpr + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 +</pre> +C++17, C++20 dialect: +<pre> +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-ImplicitCastExpr + `-CXXConstructExpr + `-IntegerLiteral 'int' 42 +</pre> +</td> + <td> +All dialects: + <pre> +FunctionDecl +`-CompoundStmt + `-ReturnStmt + `-IntegerLiteral 'int' 42 +</pre></td> +</tr> + +<tr> +<td>Matcher for returned '42': +<pre> +struct B +{ + B(int); +}; + +B func1() { + return 42; +} +</pre> + + </td> + <td> +All dialects: +<pre> +returnStmt(hasReturnValue( + ignoringImplicit( + ignoringElidableConstructorCall( + ignoringImplicit( + cxxConstructExpr(hasArgument(0, + ignoringImplicit( + integerLiteral().bind("returnVal") + ) + )) + ) + ) + ) + )) +</pre></td> + <td> +All dialects: +<pre> +returnStmt(hasReturnValue( + integerLiteral().bind("returnVal") +)) +</pre></td> +</tr> +<tr> +<td>Match result for +<pre>implicitCastExpr()</pre> +given: +<pre> +struct B +{ + B(int); +}; + +B func1() { + return 42; +} +</pre> + +</td> +<td> +Match found.</td> + <td> +No match.</td> +</tr> +<tr> + <td>Match result for: +<pre> +cxxConstructorDecl( + isCopyConstructor() + ).bind("prepend_explicit") +</pre> +given: +<pre> +struct Other { +}; +struct Copyable { + Other m_o; + Copyable(); +}; +</pre> +</td> +<td> +Match found! Insertion produces incorrect output: +<pre> +struct Other { +}; +struct explicit Copyable { + Other m_o; + Copyable(); +}; +</pre> +</td> +<td> +No match found. Incorrect replacement not possible. +</td> +</tr> +<tr> + <td>Replacement of `begin()` with `cbegin()`: +<pre> +cxxMemberCallExpr( + on(ConstContainerExpr), + callee(cxxMethodDecl(hasName("begin"))) + ).bind("replace_with_cbegin") +</pre> +given: +<pre> +void foo() +{ + const Container c; + c.begin(); + + for (auto i : c) + { + + } +} +</pre> +</td> +<td> +2 matches found! Replacement produces incorrect output: +<pre> +void foo() +{ + const Container c; + c.cbegin(); + + for (auto i :.cbegin() c) + { + + } +} +</pre> +</td> +<td> +1 match found! Replacement produces correct output: +<pre> +void foo() +{ + const Container c; + c.cbegin(); + + for (auto i : c) + { + + } +} +</pre> +</td> +</tr> +<tr> + <td>Replacement of int member with safe_int: +<pre> +fieldDecl( + hasType(asString("int")) + ).bind("use_safe_int") +</pre> +given: +<pre> +struct S { + int m_i; +}; + +template<typename T> +struct TemplStruct { + TemplStruct() {} + ~TemplStruct() {} + +private: + T m_t; +}; + +void instantiate() +{ + TemplStruct<int> ti; +} +</pre> +</td> +<td> +2 matches found! Replacement produces incorrect output: +<pre> +struct S { + safe_int m_i; +}; + +template<typename T> +struct TemplStruct { + TemplStruct() {} + ~TemplStruct() {} + +private: + safe_int m_t; +}; + +void instantiate() +{ + TemplStruct<int> ti; +} +</pre> +</td> +<td> +1 match found! Replacement produces correct output: +<pre> +struct S { + safe_int m_i; +}; + +template<typename T> +struct TemplStruct { + TemplStruct() {} + ~TemplStruct() {} + +private: + T m_t; +}; + +void instantiate() +{ + TemplStruct<int> ti; +} +</pre> +</td> +</tr> +</table> + <table> <tr style="text-align:left"><th>Return type</th><th>Name</th><th>Parameters</th></tr> <!-- START_DECL_MATCHERS -->
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits