LibASTMatchersTutorial.rst 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. ===============================================================
  2. Tutorial for building tools using LibTooling and LibASTMatchers
  3. ===============================================================
  4. NOTE: this document applies to the original Clang project, not the DirectX
  5. Compiler. It's made available for informational purposes only.
  6. This document is intended to show how to build a useful source-to-source
  7. translation tool based on Clang's `LibTooling <LibTooling.html>`_. It is
  8. explicitly aimed at people who are new to Clang, so all you should need
  9. is a working knowledge of C++ and the command line.
  10. In order to work on the compiler, you need some basic knowledge of the
  11. abstract syntax tree (AST). To this end, the reader is incouraged to
  12. skim the :doc:`Introduction to the Clang
  13. AST <IntroductionToTheClangAST>`
  14. Step 0: Obtaining Clang
  15. =======================
  16. As Clang is part of the LLVM project, you'll need to download LLVM's
  17. source code first. Both Clang and LLVM are maintained as Subversion
  18. repositories, but we'll be accessing them through the git mirror. For
  19. further information, see the `getting started
  20. guide <http://llvm.org/docs/GettingStarted.html>`_.
  21. .. code-block:: console
  22. mkdir ~/clang-llvm && cd ~/clang-llvm
  23. git clone http://llvm.org/git/llvm.git
  24. cd llvm/tools
  25. git clone http://llvm.org/git/clang.git
  26. cd clang/tools
  27. git clone http://llvm.org/git/clang-tools-extra.git extra
  28. Next you need to obtain the CMake build system and Ninja build tool. You
  29. may already have CMake installed, but current binary versions of CMake
  30. aren't built with Ninja support.
  31. .. code-block:: console
  32. cd ~/clang-llvm
  33. git clone https://github.com/martine/ninja.git
  34. cd ninja
  35. git checkout release
  36. ./bootstrap.py
  37. sudo cp ninja /usr/bin/
  38. cd ~/clang-llvm
  39. git clone git://cmake.org/stage/cmake.git
  40. cd cmake
  41. git checkout next
  42. ./bootstrap
  43. make
  44. sudo make install
  45. Okay. Now we'll build Clang!
  46. .. code-block:: console
  47. cd ~/clang-llvm
  48. mkdir build && cd build
  49. cmake -G Ninja ../llvm -DLLVM_BUILD_TESTS=ON # Enable tests; default is off.
  50. ninja
  51. ninja check # Test LLVM only.
  52. ninja clang-test # Test Clang only.
  53. ninja install
  54. And we're live.
  55. All of the tests should pass, though there is a (very) small chance that
  56. you can catch LLVM and Clang out of sync. Running ``'git svn rebase'``
  57. in both the llvm and clang directories should fix any problems.
  58. Finally, we want to set Clang as its own compiler.
  59. .. code-block:: console
  60. cd ~/clang-llvm/build
  61. ccmake ../llvm
  62. The second command will bring up a GUI for configuring Clang. You need
  63. to set the entry for ``CMAKE_CXX_COMPILER``. Press ``'t'`` to turn on
  64. advanced mode. Scroll down to ``CMAKE_CXX_COMPILER``, and set it to
  65. ``/usr/bin/clang++``, or wherever you installed it. Press ``'c'`` to
  66. configure, then ``'g'`` to generate CMake's files.
  67. Finally, run ninja one last time, and you're done.
  68. Step 1: Create a ClangTool
  69. ==========================
  70. Now that we have enough background knowledge, it's time to create the
  71. simplest productive ClangTool in existence: a syntax checker. While this
  72. already exists as ``clang-check``, it's important to understand what's
  73. going on.
  74. First, we'll need to create a new directory for our tool and tell CMake
  75. that it exists. As this is not going to be a core clang tool, it will
  76. live in the ``tools/extra`` repository.
  77. .. code-block:: console
  78. cd ~/clang-llvm/llvm/tools/clang
  79. mkdir tools/extra/loop-convert
  80. echo 'add_subdirectory(loop-convert)' >> tools/extra/CMakeLists.txt
  81. vim tools/extra/loop-convert/CMakeLists.txt
  82. CMakeLists.txt should have the following contents:
  83. ::
  84. set(LLVM_LINK_COMPONENTS support)
  85. set(LLVM_USED_LIBS clangTooling clangBasic clangAST)
  86. add_clang_executable(loop-convert
  87. LoopConvert.cpp
  88. )
  89. target_link_libraries(loop-convert
  90. clangTooling
  91. clangBasic
  92. clangASTMatchers
  93. )
  94. With that done, Ninja will be able to compile our tool. Let's give it
  95. something to compile! Put the following into
  96. ``tools/extra/loop-convert/LoopConvert.cpp``. A detailed explanation of
  97. why the different parts are needed can be found in the `LibTooling
  98. documentation <LibTooling.html>`_.
  99. .. code-block:: c++
  100. // Declares clang::SyntaxOnlyAction.
  101. #include "clang/Frontend/FrontendActions.h"
  102. #include "clang/Tooling/CommonOptionsParser.h"
  103. #include "clang/Tooling/Tooling.h"
  104. // Declares llvm::cl::extrahelp.
  105. #include "llvm/Support/CommandLine.h"
  106. using namespace clang::tooling;
  107. using namespace llvm;
  108. // Apply a custom category to all command-line options so that they are the
  109. // only ones displayed.
  110. static llvm::cl::OptionCategory MyToolCategory("my-tool options");
  111. // CommonOptionsParser declares HelpMessage with a description of the common
  112. // command-line options related to the compilation database and input files.
  113. // It's nice to have this help message in all tools.
  114. static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
  115. // A help message for this specific tool can be added afterwards.
  116. static cl::extrahelp MoreHelp("\nMore help text...");
  117. int main(int argc, const char **argv) {
  118. CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  119. ClangTool Tool(OptionsParser.getCompilations(),
  120. OptionsParser.getSourcePathList());
  121. return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
  122. }
  123. And that's it! You can compile our new tool by running ninja from the
  124. ``build`` directory.
  125. .. code-block:: console
  126. cd ~/clang-llvm/build
  127. ninja
  128. You should now be able to run the syntax checker, which is located in
  129. ``~/clang-llvm/build/bin``, on any source file. Try it!
  130. .. code-block:: console
  131. echo "int main() { return 0; }" > test.cpp
  132. bin/loop-convert test.cpp --
  133. Note the two dashes after we specify the source file. The additional
  134. options for the compiler are passed after the dashes rather than loading
  135. them from a compilation database - there just aren't any options needed
  136. right now.
  137. Intermezzo: Learn AST matcher basics
  138. ====================================
  139. Clang recently introduced the :doc:`ASTMatcher
  140. library <LibASTMatchers>` to provide a simple, powerful, and
  141. concise way to describe specific patterns in the AST. Implemented as a
  142. DSL powered by macros and templates (see
  143. `ASTMatchers.h <../doxygen/ASTMatchers_8h_source.html>`_ if you're
  144. curious), matchers offer the feel of algebraic data types common to
  145. functional programming languages.
  146. For example, suppose you wanted to examine only binary operators. There
  147. is a matcher to do exactly that, conveniently named ``binaryOperator``.
  148. I'll give you one guess what this matcher does:
  149. .. code-block:: c++
  150. binaryOperator(hasOperatorName("+"), hasLHS(integerLiteral(equals(0))))
  151. Shockingly, it will match against addition expressions whose left hand
  152. side is exactly the literal 0. It will not match against other forms of
  153. 0, such as ``'\0'`` or ``NULL``, but it will match against macros that
  154. expand to 0. The matcher will also not match against calls to the
  155. overloaded operator ``'+'``, as there is a separate ``operatorCallExpr``
  156. matcher to handle overloaded operators.
  157. There are AST matchers to match all the different nodes of the AST,
  158. narrowing matchers to only match AST nodes fulfilling specific criteria,
  159. and traversal matchers to get from one kind of AST node to another. For
  160. a complete list of AST matchers, take a look at the `AST Matcher
  161. References <LibASTMatchersReference.html>`_
  162. All matcher that are nouns describe entities in the AST and can be
  163. bound, so that they can be referred to whenever a match is found. To do
  164. so, simply call the method ``bind`` on these matchers, e.g.:
  165. .. code-block:: c++
  166. variable(hasType(isInteger())).bind("intvar")
  167. Step 2: Using AST matchers
  168. ==========================
  169. Okay, on to using matchers for real. Let's start by defining a matcher
  170. which will capture all ``for`` statements that define a new variable
  171. initialized to zero. Let's start with matching all ``for`` loops:
  172. .. code-block:: c++
  173. forStmt()
  174. Next, we want to specify that a single variable is declared in the first
  175. portion of the loop, so we can extend the matcher to
  176. .. code-block:: c++
  177. forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl()))))
  178. Finally, we can add the condition that the variable is initialized to
  179. zero.
  180. .. code-block:: c++
  181. forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(
  182. hasInitializer(integerLiteral(equals(0))))))))
  183. It is fairly easy to read and understand the matcher definition ("match
  184. loops whose init portion declares a single variable which is initialized
  185. to the integer literal 0"), but deciding that every piece is necessary
  186. is more difficult. Note that this matcher will not match loops whose
  187. variables are initialized to ``'\0'``, ``0.0``, ``NULL``, or any form of
  188. zero besides the integer 0.
  189. The last step is giving the matcher a name and binding the ``ForStmt``
  190. as we will want to do something with it:
  191. .. code-block:: c++
  192. StatementMatcher LoopMatcher =
  193. forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(
  194. hasInitializer(integerLiteral(equals(0)))))))).bind("forLoop");
  195. Once you have defined your matchers, you will need to add a little more
  196. scaffolding in order to run them. Matchers are paired with a
  197. ``MatchCallback`` and registered with a ``MatchFinder`` object, then run
  198. from a ``ClangTool``. More code!
  199. Add the following to ``LoopConvert.cpp``:
  200. .. code-block:: c++
  201. #include "clang/ASTMatchers/ASTMatchers.h"
  202. #include "clang/ASTMatchers/ASTMatchFinder.h"
  203. using namespace clang;
  204. using namespace clang::ast_matchers;
  205. StatementMatcher LoopMatcher =
  206. forStmt(hasLoopInit(declStmt(hasSingleDecl(varDecl(
  207. hasInitializer(integerLiteral(equals(0)))))))).bind("forLoop");
  208. class LoopPrinter : public MatchFinder::MatchCallback {
  209. public :
  210. virtual void run(const MatchFinder::MatchResult &Result) {
  211. if (const ForStmt *FS = Result.Nodes.getNodeAs<clang::ForStmt>("forLoop"))
  212. FS->dump();
  213. }
  214. };
  215. And change ``main()`` to:
  216. .. code-block:: c++
  217. int main(int argc, const char **argv) {
  218. CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
  219. ClangTool Tool(OptionsParser.getCompilations(),
  220. OptionsParser.getSourcePathList());
  221. LoopPrinter Printer;
  222. MatchFinder Finder;
  223. Finder.addMatcher(LoopMatcher, &Printer);
  224. return Tool.run(newFrontendActionFactory(&Finder).get());
  225. }
  226. Now, you should be able to recompile and run the code to discover for
  227. loops. Create a new file with a few examples, and test out our new
  228. handiwork:
  229. .. code-block:: console
  230. cd ~/clang-llvm/llvm/llvm_build/
  231. ninja loop-convert
  232. vim ~/test-files/simple-loops.cc
  233. bin/loop-convert ~/test-files/simple-loops.cc
  234. Step 3.5: More Complicated Matchers
  235. ===================================
  236. Our simple matcher is capable of discovering for loops, but we would
  237. still need to filter out many more ourselves. We can do a good portion
  238. of the remaining work with some cleverly chosen matchers, but first we
  239. need to decide exactly which properties we want to allow.
  240. How can we characterize for loops over arrays which would be eligible
  241. for translation to range-based syntax? Range based loops over arrays of
  242. size ``N`` that:
  243. - start at index ``0``
  244. - iterate consecutively
  245. - end at index ``N-1``
  246. We already check for (1), so all we need to add is a check to the loop's
  247. condition to ensure that the loop's index variable is compared against
  248. ``N`` and another check to ensure that the increment step just
  249. increments this same variable. The matcher for (2) is straightforward:
  250. require a pre- or post-increment of the same variable declared in the
  251. init portion.
  252. Unfortunately, such a matcher is impossible to write. Matchers contain
  253. no logic for comparing two arbitrary AST nodes and determining whether
  254. or not they are equal, so the best we can do is matching more than we
  255. would like to allow, and punting extra comparisons to the callback.
  256. In any case, we can start building this sub-matcher. We can require that
  257. the increment step be a unary increment like this:
  258. .. code-block:: c++
  259. hasIncrement(unaryOperator(hasOperatorName("++")))
  260. Specifying what is incremented introduces another quirk of Clang's AST:
  261. Usages of variables are represented as ``DeclRefExpr``'s ("declaration
  262. reference expressions") because they are expressions which refer to
  263. variable declarations. To find a ``unaryOperator`` that refers to a
  264. specific declaration, we can simply add a second condition to it:
  265. .. code-block:: c++
  266. hasIncrement(unaryOperator(
  267. hasOperatorName("++"),
  268. hasUnaryOperand(declRefExpr())))
  269. Furthermore, we can restrict our matcher to only match if the
  270. incremented variable is an integer:
  271. .. code-block:: c++
  272. hasIncrement(unaryOperator(
  273. hasOperatorName("++"),
  274. hasUnaryOperand(declRefExpr(to(varDecl(hasType(isInteger())))))))
  275. And the last step will be to attach an identifier to this variable, so
  276. that we can retrieve it in the callback:
  277. .. code-block:: c++
  278. hasIncrement(unaryOperator(
  279. hasOperatorName("++"),
  280. hasUnaryOperand(declRefExpr(to(
  281. varDecl(hasType(isInteger())).bind("incrementVariable"))))))
  282. We can add this code to the definition of ``LoopMatcher`` and make sure
  283. that our program, outfitted with the new matcher, only prints out loops
  284. that declare a single variable initialized to zero and have an increment
  285. step consisting of a unary increment of some variable.
  286. Now, we just need to add a matcher to check if the condition part of the
  287. ``for`` loop compares a variable against the size of the array. There is
  288. only one problem - we don't know which array we're iterating over
  289. without looking at the body of the loop! We are again restricted to
  290. approximating the result we want with matchers, filling in the details
  291. in the callback. So we start with:
  292. .. code-block:: c++
  293. hasCondition(binaryOperator(hasOperatorName("<"))
  294. It makes sense to ensure that the left-hand side is a reference to a
  295. variable, and that the right-hand side has integer type.
  296. .. code-block:: c++
  297. hasCondition(binaryOperator(
  298. hasOperatorName("<"),
  299. hasLHS(declRefExpr(to(varDecl(hasType(isInteger()))))),
  300. hasRHS(expr(hasType(isInteger())))))
  301. Why? Because it doesn't work. Of the three loops provided in
  302. ``test-files/simple.cpp``, zero of them have a matching condition. A
  303. quick look at the AST dump of the first for loop, produced by the
  304. previous iteration of loop-convert, shows us the answer:
  305. ::
  306. (ForStmt 0x173b240
  307. (DeclStmt 0x173afc8
  308. 0x173af50 "int i =
  309. (IntegerLiteral 0x173afa8 'int' 0)")
  310. <<>>
  311. (BinaryOperator 0x173b060 '_Bool' '<'
  312. (ImplicitCastExpr 0x173b030 'int'
  313. (DeclRefExpr 0x173afe0 'int' lvalue Var 0x173af50 'i' 'int'))
  314. (ImplicitCastExpr 0x173b048 'int'
  315. (DeclRefExpr 0x173b008 'const int' lvalue Var 0x170fa80 'N' 'const int')))
  316. (UnaryOperator 0x173b0b0 'int' lvalue prefix '++'
  317. (DeclRefExpr 0x173b088 'int' lvalue Var 0x173af50 'i' 'int'))
  318. (CompoundStatement ...
  319. We already know that the declaration and increments both match, or this
  320. loop wouldn't have been dumped. The culprit lies in the implicit cast
  321. applied to the first operand (i.e. the LHS) of the less-than operator,
  322. an L-value to R-value conversion applied to the expression referencing
  323. ``i``. Thankfully, the matcher library offers a solution to this problem
  324. in the form of ``ignoringParenImpCasts``, which instructs the matcher to
  325. ignore implicit casts and parentheses before continuing to match.
  326. Adjusting the condition operator will restore the desired match.
  327. .. code-block:: c++
  328. hasCondition(binaryOperator(
  329. hasOperatorName("<"),
  330. hasLHS(ignoringParenImpCasts(declRefExpr(
  331. to(varDecl(hasType(isInteger())))))),
  332. hasRHS(expr(hasType(isInteger())))))
  333. After adding binds to the expressions we wished to capture and
  334. extracting the identifier strings into variables, we have array-step-2
  335. completed.
  336. Step 4: Retrieving Matched Nodes
  337. ================================
  338. So far, the matcher callback isn't very interesting: it just dumps the
  339. loop's AST. At some point, we will need to make changes to the input
  340. source code. Next, we'll work on using the nodes we bound in the
  341. previous step.
  342. The ``MatchFinder::run()`` callback takes a
  343. ``MatchFinder::MatchResult&`` as its parameter. We're most interested in
  344. its ``Context`` and ``Nodes`` members. Clang uses the ``ASTContext``
  345. class to represent contextual information about the AST, as the name
  346. implies, though the most functionally important detail is that several
  347. operations require an ``ASTContext*`` parameter. More immediately useful
  348. is the set of matched nodes, and how we retrieve them.
  349. Since we bind three variables (identified by ConditionVarName,
  350. InitVarName, and IncrementVarName), we can obtain the matched nodes by
  351. using the ``getNodeAs()`` member function.
  352. In ``LoopConvert.cpp`` add
  353. .. code-block:: c++
  354. #include "clang/AST/ASTContext.h"
  355. Change ``LoopMatcher`` to
  356. .. code-block:: c++
  357. StatementMatcher LoopMatcher =
  358. forStmt(hasLoopInit(declStmt(
  359. hasSingleDecl(varDecl(hasInitializer(integerLiteral(equals(0))))
  360. .bind("initVarName")))),
  361. hasIncrement(unaryOperator(
  362. hasOperatorName("++"),
  363. hasUnaryOperand(declRefExpr(
  364. to(varDecl(hasType(isInteger())).bind("incVarName")))))),
  365. hasCondition(binaryOperator(
  366. hasOperatorName("<"),
  367. hasLHS(ignoringParenImpCasts(declRefExpr(
  368. to(varDecl(hasType(isInteger())).bind("condVarName"))))),
  369. hasRHS(expr(hasType(isInteger())))))).bind("forLoop");
  370. And change ``LoopPrinter::run`` to
  371. .. code-block:: c++
  372. void LoopPrinter::run(const MatchFinder::MatchResult &Result) {
  373. ASTContext *Context = Result.Context;
  374. const ForStmt *FS = Result.Nodes.getStmtAs<ForStmt>("forLoop");
  375. // We do not want to convert header files!
  376. if (!FS || !Context->getSourceManager().isFromMainFile(FS->getForLoc()))
  377. return;
  378. const VarDecl *IncVar = Result.Nodes.getNodeAs<VarDecl>("incVarName");
  379. const VarDecl *CondVar = Result.Nodes.getNodeAs<VarDecl>("condVarName");
  380. const VarDecl *InitVar = Result.Nodes.getNodeAs<VarDecl>("initVarName");
  381. if (!areSameVariable(IncVar, CondVar) || !areSameVariable(IncVar, InitVar))
  382. return;
  383. llvm::outs() << "Potential array-based loop discovered.\n";
  384. }
  385. Clang associates a ``VarDecl`` with each variable to represent the variable's
  386. declaration. Since the "canonical" form of each declaration is unique by
  387. address, all we need to do is make sure neither ``ValueDecl`` (base class of
  388. ``VarDecl``) is ``NULL`` and compare the canonical Decls.
  389. .. code-block:: c++
  390. static bool areSameVariable(const ValueDecl *First, const ValueDecl *Second) {
  391. return First && Second &&
  392. First->getCanonicalDecl() == Second->getCanonicalDecl();
  393. }
  394. If execution reaches the end of ``LoopPrinter::run()``, we know that the
  395. loop shell that looks like
  396. .. code-block:: c++
  397. for (int i= 0; i < expr(); ++i) { ... }
  398. For now, we will just print a message explaining that we found a loop.
  399. The next section will deal with recursively traversing the AST to
  400. discover all changes needed.
  401. As a side note, it's not as trivial to test if two expressions are the same,
  402. though Clang has already done the hard work for us by providing a way to
  403. canonicalize expressions:
  404. .. code-block:: c++
  405. static bool areSameExpr(ASTContext *Context, const Expr *First,
  406. const Expr *Second) {
  407. if (!First || !Second)
  408. return false;
  409. llvm::FoldingSetNodeID FirstID, SecondID;
  410. First->Profile(FirstID, *Context, true);
  411. Second->Profile(SecondID, *Context, true);
  412. return FirstID == SecondID;
  413. }
  414. This code relies on the comparison between two
  415. ``llvm::FoldingSetNodeIDs``. As the documentation for
  416. ``Stmt::Profile()`` indicates, the ``Profile()`` member function builds
  417. a description of a node in the AST, based on its properties, along with
  418. those of its children. ``FoldingSetNodeID`` then serves as a hash we can
  419. use to compare expressions. We will need ``areSameExpr`` later. Before
  420. you run the new code on the additional loops added to
  421. test-files/simple.cpp, try to figure out which ones will be considered
  422. potentially convertible.