]> granicus.if.org Git - clang/commitdiff
Multiple improvements to the AST matcher tutorial.
authorManuel Klimek <klimek@google.com>
Thu, 18 Apr 2013 14:30:45 +0000 (14:30 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 18 Apr 2013 14:30:45 +0000 (14:30 +0000)
Patch by Jochen Eisinger.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179758 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibASTMatchersTutorial.rst

index 66071c16963a18807a7738b85e449f4393ad79a7..9fe45ccc4b64f07f510298f0dfb48554205c4fd5 100644 (file)
@@ -414,9 +414,9 @@ previous iteration of loop-convert, shows us the answer:
             (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 (identified by ConditionVarName,
 InitVarName, and IncrementVarName), we can obtain the matched nodes by
 using the ``getNodeAs()`` member function.
 
-In ``LoopActions.cpp``:
+In ``LoopConvert.cpp`` add
 
 .. 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 explaining that we found a loop.
 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++