# [PATCH] More updates to LibASTMatcherTutorial

Thu Apr 18 07:17:36 PDT 2013

```Hi klimek,

I cleaned up the last part of the tutorial. However, the tutorial is incomplete, so it ends somewhat abrupt...

http://llvm-reviews.chandlerc.com/D691

Files:
docs/LibASTMatchersTutorial.rst

Index: docs/LibASTMatchersTutorial.rst
===================================================================
--- docs/LibASTMatchersTutorial.rst
+++ docs/LibASTMatchersTutorial.rst
@@ -414,9 +414,9 @@
(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 @@
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 @@
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++
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D691.1.patch
Type: text/x-patch
Size: 5068 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130418/74b61a44/attachment.bin>
```