# r179758 - Multiple improvements to the AST matcher tutorial.

Thu Apr 18 07:30:45 PDT 2013

```Author: klimek
Date: Thu Apr 18 09:30:45 2013
New Revision: 179758

URL: http://llvm.org/viewvc/llvm-project?rev=179758&view=rev
Log:
Multiple improvements to the AST matcher tutorial.

Patch by Jochen Eisinger.

Modified:
cfe/trunk/docs/LibASTMatchersTutorial.rst

Modified: cfe/trunk/docs/LibASTMatchersTutorial.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersTutorial.rst?rev=179758&r1=179757&r2=179758&view=diff
==============================================================================
--- cfe/trunk/docs/LibASTMatchersTutorial.rst (original)
+++ cfe/trunk/docs/LibASTMatchersTutorial.rst Thu Apr 18 09:30:45 2013
@@ -414,9 +414,9 @@ previous iteration of loop-convert, show
(IntegerLiteral 0x173afa8 'int' 0)")
<<>>
(BinaryOperator 0x173b060 '_Bool' '<'
-          (ImplicitCastExpr 0x173b030 'int'
+          (ImplicitCastExpr 0x173b030 'int'
(DeclRefExpr 0x173afe0 'int' lvalue Var 0x173af50 'i' 'int'))
-          (ImplicitCastExpr 0x173b048 'int'
+          (ImplicitCastExpr 0x173b048 'int'
(DeclRefExpr 0x173b008 'const int' lvalue Var 0x170fa80 'N' 'const int')))
(UnaryOperator 0x173b0b0 'int' lvalue prefix '++'
(DeclRefExpr 0x173b088 'int' lvalue Var 0x173af50 'i' 'int'))
@@ -463,32 +463,60 @@ Since we bind three variables (identifie
InitVarName, and IncrementVarName), we can obtain the matched nodes by
using the ``getNodeAs()`` member function.

-In ``LoopActions.cpp``:

.. code-block:: c++

#include "clang/AST/ASTContext.h"

+Change ``LoopMatcher`` to
+
+.. code-block:: c++
+
+      StatementMatcher LoopMatcher =
+          forStmt(hasLoopInit(declStmt(
+                      hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
+                                        .bind("initVarName")))),
+                  hasIncrement(unaryOperator(
+                      hasOperatorName("++"),
+                      hasUnaryOperand(declRefExpr(
+                          to(varDecl(hasType(isInteger())).bind("incVarName")))))),
+                  hasCondition(binaryOperator(
+                      hasOperatorName("<"),
+                      hasLHS(ignoringParenImpCasts(declRefExpr(
+                          to(varDecl(hasType(isInteger())).bind("condVarName"))))),
+                      hasRHS(expr(hasType(isInteger())))))).bind("forLoop");
+
+And change ``LoopPrinter::run`` to
+
+.. code-block:: c++
+
void LoopPrinter::run(const MatchFinder::MatchResult &Result) {
ASTContext *Context = Result.Context;
-        const ForStmt *FS = Result.Nodes.getStmtAs<ForStmt>(LoopName);
+        const ForStmt *FS = Result.Nodes.getStmtAs<ForStmt>("forLoop");
// We do not want to convert header files!
if (!FS || !Context->getSourceManager().isFromMainFile(FS->getForLoc()))
return;
-        const VarDecl *IncVar = Result.Nodes.getNodeAs<VarDecl>(IncrementVarName);
-        const VarDecl *CondVar = Result.Nodes.getNodeAs<VarDecl>(ConditionVarName);
-        const VarDecl *InitVar = Result.Nodes.getNodeAs<VarDecl>(InitVarName);
+        const VarDecl *IncVar = Result.Nodes.getNodeAs<VarDecl>("incVarName");
+        const VarDecl *CondVar = Result.Nodes.getNodeAs<VarDecl>("condVarName");
+        const VarDecl *InitVar = Result.Nodes.getNodeAs<VarDecl>("initVarName");
+
+        if (!areSameVariable(IncVar, CondVar) || !areSameVariable(IncVar, InitVar))
+          return;
+        llvm::outs() << "Potential array-based loop discovered.\n";
+      }

-Now that we have the three variables, represented by their respective
-declarations, let's make sure that they're all the same, using a helper
-function I call ``areSameVariable()``.
+Clang associates a ``VarDecl`` with each variable to represent the variable's
+declaration. Since the "canonical" form of each declaration is unique by
+address, all we need to do is make sure neither ``ValueDecl`` (base class of
+``VarDecl``) is ``NULL`` and compare the canonical Decls.

.. code-block:: c++

-      if (!areSameVariable(IncVar, CondVar) || !areSameVariable(IncVar, InitVar))
-        return;
-      llvm::outs() << "Potential array-based loop discovered.\n";
-    }
+      static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
+        return First && Second &&
+               First->getCanonicalDecl() == Second->getCanonicalDecl();
+      }

If execution reaches the end of ``LoopPrinter::run()``, we know that the
loop shell that looks like
@@ -501,21 +529,8 @@ For now, we will just print a message ex
The next section will deal with recursively traversing the AST to
discover all changes needed.

-As a side note, here is the implementation of ``areSameVariable``. Clang
-associates a ``VarDecl`` with each variable to represent the variable's
-declaration. Since the "canonical" form of each declaration is unique by
-address, all we need to do is make sure neither ``ValueDecl`` (base
-class of ``VarDecl``) is ``NULL`` and compare the canonical Decls.
-
-.. code-block:: c++
-
-      static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
-        return First && Second &&
-               First->getCanonicalDecl() == Second->getCanonicalDecl();
-      }
-
-It's not as trivial to test if two expressions are the same, though
-Clang has already done the hard work for us by providing a way to
+As a side note, it's not as trivial to test if two expressions are the same,
+though Clang has already done the hard work for us by providing a way to
canonicalize expressions:

.. code-block:: c++

```