aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/LibASTMatchersTutorial.rst73
1 files changed, 44 insertions, 29 deletions
diff --git a/docs/LibASTMatchersTutorial.rst b/docs/LibASTMatchersTutorial.rst
index 66071c1696..9fe45ccc4b 100644
--- a/docs/LibASTMatchersTutorial.rst
+++ b/docs/LibASTMatchersTutorial.rst
@@ -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++