From 74df03a0d1d52f73239dcc5567d3a1c85518d59a Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Thu, 18 Apr 2013 14:30:45 +0000 Subject: [PATCH] Multiple improvements to the AST matcher tutorial. Patch by Jochen Eisinger. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179758 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersTutorial.rst | 73 ++++++++++++++++++++------------- 1 file 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(LoopName); + const ForStmt *FS = Result.Nodes.getStmtAs("forLoop"); // We do not want to convert header files! if (!FS || !Context->getSourceManager().isFromMainFile(FS->getForLoc())) return; - const VarDecl *IncVar = Result.Nodes.getNodeAs(IncrementVarName); - const VarDecl *CondVar = Result.Nodes.getNodeAs(ConditionVarName); - const VarDecl *InitVar = Result.Nodes.getNodeAs(InitVarName); + const VarDecl *IncVar = Result.Nodes.getNodeAs("incVarName"); + const VarDecl *CondVar = Result.Nodes.getNodeAs("condVarName"); + const VarDecl *InitVar = Result.Nodes.getNodeAs("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++ -- 2.40.0