forked from OSchip/llvm-project
parent
dcb0e72e6f
commit
68a0668453
|
@ -21,7 +21,7 @@ repositories, but we'll be accessing them through the git mirror. For
|
|||
further information, see the `getting started
|
||||
guide <http://llvm.org/docs/GettingStarted.html>`_.
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
mkdir ~/clang-llvm && cd ~/clang-llvm
|
||||
git clone http://llvm.org/git/llvm.git
|
||||
|
@ -32,7 +32,7 @@ Next you need to obtain the CMake build system and Ninja build tool. You
|
|||
may already have CMake installed, but current binary versions of CMake
|
||||
aren't built with Ninja support.
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cd ~/clang-llvm
|
||||
git clone https://github.com/martine/ninja.git
|
||||
|
@ -51,7 +51,7 @@ aren't built with Ninja support.
|
|||
|
||||
Okay. Now we'll build Clang!
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cd ~/clang-llvm
|
||||
mkdir build && cd build
|
||||
|
@ -69,7 +69,7 @@ in both the llvm and clang directories should fix any problems.
|
|||
|
||||
Finally, we want to set Clang as its own compiler.
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cd ~/clang-llvm/build
|
||||
ccmake ../llvm
|
||||
|
@ -94,7 +94,7 @@ First, we'll need to create a new directory for our tool and tell CMake
|
|||
that it exists. As this is not going to be a core clang tool, it will
|
||||
live in the ``tools/extra`` repository.
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cd ~/clang-llvm/llvm/tools/clang
|
||||
mkdir tools/extra/loop-convert
|
||||
|
@ -123,7 +123,7 @@ something to compile! Put the following into
|
|||
why the different parts are needed can be found in the `LibTooling
|
||||
documentation <LibTooling.html>`_.
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
// Declares clang::SyntaxOnlyAction.
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
|
@ -153,7 +153,7 @@ documentation <LibTooling.html>`_.
|
|||
And that's it! You can compile our new tool by running ninja from the
|
||||
``build`` directory.
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cd ~/clang-llvm/build
|
||||
ninja
|
||||
|
@ -161,7 +161,7 @@ And that's it! You can compile our new tool by running ninja from the
|
|||
You should now be able to run the syntax checker, which is located in
|
||||
``~/clang-llvm/build/bin``, on any source file. Try it!
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cat "void main() {}" > test.cpp
|
||||
bin/loop-convert test.cpp --
|
||||
|
@ -186,7 +186,7 @@ For example, suppose you wanted to examine only binary operators. There
|
|||
is a matcher to do exactly that, conveniently named ``binaryOperator``.
|
||||
I'll give you one guess what this matcher does:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
binaryOperator(hasOperatorName("+"), hasLHS(integerLiteral(equals(0))))
|
||||
|
||||
|
@ -207,7 +207,7 @@ All matcher that are nouns describe entities in the AST and can be
|
|||
bound, so that they can be referred to whenever a match is found. To do
|
||||
so, simply call the method ``bind`` on these matchers, e.g.:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
variable(hasType(isInteger())).bind("intvar")
|
||||
|
||||
|
@ -218,21 +218,21 @@ Okay, on to using matchers for real. Let's start by defining a matcher
|
|||
which will capture all ``for`` statements that define a new variable
|
||||
initialized to zero. Let's start with matching all ``for`` loops:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
forStmt()
|
||||
|
||||
Next, we want to specify that a single variable is declared in the first
|
||||
portion of the loop, so we can extend the matcher to
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl()))))
|
||||
|
||||
Finally, we can add the condition that the variable is initialized to
|
||||
zero.
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(
|
||||
hasInitializer(integerLiteral(equals(0))))))))
|
||||
|
@ -247,7 +247,7 @@ zero besides the integer 0.
|
|||
The last step is giving the matcher a name and binding the ``ForStmt``
|
||||
as we will want to do something with it:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
StatementMatcher LoopMatcher =
|
||||
forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(
|
||||
|
@ -260,7 +260,8 @@ from a ``ClangTool``. More code!
|
|||
|
||||
Add the following to ``LoopConvert.cpp``:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
|
||||
|
@ -280,7 +281,7 @@ Add the following to ``LoopConvert.cpp``:
|
|||
|
||||
And change ``main()`` to:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
CommonOptionsParser OptionsParser(argc, argv);
|
||||
|
@ -298,7 +299,7 @@ Now, you should be able to recompile and run the code to discover for
|
|||
loops. Create a new file with a few examples, and test out our new
|
||||
handiwork:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
cd ~/clang-llvm/llvm/llvm_build/
|
||||
ninja loop-convert
|
||||
|
@ -336,7 +337,7 @@ would like to allow, and punting extra comparisons to the callback.
|
|||
In any case, we can start building this sub-matcher. We can require that
|
||||
the increment step be a unary increment like this:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasIncrement(unaryOperator(hasOperatorName("++")))
|
||||
|
||||
|
@ -346,7 +347,7 @@ reference expressions") because they are expressions which refer to
|
|||
variable declarations. To find a ``unaryOperator`` that refers to a
|
||||
specific declaration, we can simply add a second condition to it:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasIncrement(unaryOperator(
|
||||
hasOperatorName("++"),
|
||||
|
@ -355,7 +356,7 @@ specific declaration, we can simply add a second condition to it:
|
|||
Furthermore, we can restrict our matcher to only match if the
|
||||
incremented variable is an integer:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasIncrement(unaryOperator(
|
||||
hasOperatorName("++"),
|
||||
|
@ -364,7 +365,7 @@ incremented variable is an integer:
|
|||
And the last step will be to attach an identifier to this variable, so
|
||||
that we can retrieve it in the callback:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasIncrement(unaryOperator(
|
||||
hasOperatorName("++"),
|
||||
|
@ -383,14 +384,14 @@ without looking at the body of the loop! We are again restricted to
|
|||
approximating the result we want with matchers, filling in the details
|
||||
in the callback. So we start with:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasCondition(binaryOperator(hasOperatorName("<"))
|
||||
|
||||
It makes sense to ensure that the left-hand side is a reference to a
|
||||
variable, and that the right-hand side has integer type.
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasCondition(binaryOperator(
|
||||
hasOperatorName("<"),
|
||||
|
@ -427,7 +428,7 @@ in the form of ``ignoringParenImpCasts``, which instructs the matcher to
|
|||
ignore implicit casts and parentheses before continuing to match.
|
||||
Adjusting the condition operator will restore the desired match.
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
hasCondition(binaryOperator(
|
||||
hasOperatorName("<"),
|
||||
|
@ -461,7 +462,7 @@ using the ``getNodeAs()`` member function.
|
|||
|
||||
In ``LoopActions.cpp``:
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
||||
|
@ -479,7 +480,7 @@ 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()``.
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
if (!areSameVariable(IncVar, CondVar) || !areSameVariable(IncVar, InitVar))
|
||||
return;
|
||||
|
@ -489,7 +490,7 @@ function I call ``areSameVariable()``.
|
|||
If execution reaches the end of ``LoopPrinter::run()``, we know that the
|
||||
loop shell that looks like
|
||||
|
||||
::
|
||||
.. code-block:: c++
|
||||
|
||||
for (int i= 0; i < expr(); ++i) { ... }
|
||||
|
||||
|
@ -503,7 +504,7 @@ 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 &&
|
||||
|
@ -514,9 +515,9 @@ 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++
|
||||
|
||||
static bool areSameExpr(ASTContext* Context, const Expr *First,
|
||||
static bool areSameExpr(ASTContext *Context, const Expr *First,
|
||||
const Expr *Second) {
|
||||
if (!First || !Second)
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue