https://github.com/pseudomanifold/libclang-experiments
Experiments with `libclang`
https://github.com/pseudomanifold/libclang-experiments
abstract-syntax-tree clang code-analysis cplusplus libclang llvm
Last synced: 6 months ago
JSON representation
Experiments with `libclang`
- Host: GitHub
- URL: https://github.com/pseudomanifold/libclang-experiments
- Owner: Pseudomanifold
- License: mit
- Created: 2017-09-08T06:30:46.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2017-09-08T07:22:25.000Z (about 8 years ago)
- Last Synced: 2025-03-24T15:47:23.449Z (7 months ago)
- Topics: abstract-syntax-tree, clang, code-analysis, cplusplus, libclang, llvm
- Language: C++
- Size: 8.23 MB
- Stars: 23
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# `libclang-experiments` — Some experiments with `libclang`
This repository contains some of [my](http://bastian.rieck.ru)
experiments with `libclang`, or, to be more precise, the `C` bindings of
`libclang`. I already detailed some of my experiments in two blog posts.
The first deals with [walking an abstract syntax tree](http://bastian.rieck.ru/blog/posts/2015/baby_steps_libclang_ast),
while the second deals with [counting the extents of a function](http://bastian.rieck.ru/blog/posts/2016/baby_steps_libclang_function_extents).# Requirements
* `libclang` (for parsing ASTs)
* `clang` (for creating ASTs)# Building the examples
$ mkdir build
$ cd build
$ cmake ../
$ make# Obtaining an AST
Some of the example programs require the explicit creation of an
abstract syntax tree, while others make use of a database of compile
commands. In order to obtain an abstract syntax tree, call `clang` with
the following parameters:clang++ -std=c++11 -emit-ast FILE
Optionally, you can add `-I` or any other parameter that is required for
compiling a given program.# The experiments
Let me briefly explain how to use some of the experiments.
## `ast-dumper` & `ast-walker`
These programs walk an abstract syntax tree. They roughly follow the
implementation given in [this blog post](http://bastian.rieck.ru/blog/posts/2015/baby_steps_libclang_ast).
To use one of them (I am exemplarily demonstrating `ast-walker`),
you require the creation of an abstract syntax tree:$ clang++ -std=c++11 -emit-ast ../examples/tuple.cc
$ ./ast-walker tuple.astThis should result in an output similar to this:
ClassDecl (foo)
- CXXAccessSpecifier ()
- CXXConstructor (foo)
-- ParmDecl (n_)
-- ParmDecl (c_)
-- ParmDecl (d_)
-- MemberRef (n)
-- InitListExpr ()
--- UnexposedExpr (n_)
---- DeclRefExpr (n_)
-- MemberRef (c)
-- InitListExpr ()
--- UnexposedExpr (c_)
---- DeclRefExpr (c_)
-- MemberRef (d)
-- InitListExpr ()
--- UnexposedExpr (d_)
---- DeclRefExpr (d_)
-- CompoundStmt ()
- FriendDecl ()
-- FunctionDecl (operator<)
--- ParmDecl (lh)
---- TypeRef (class foo)
--- ParmDecl (rh)
---- TypeRef (class foo)
--- CompoundStmt ()
---- ReturnStmt ()
----- UnexposedExpr ()
------ CallExpr (operator<)
------- UnexposedExpr ()
-------- UnexposedExpr (tie)
--------- CallExpr (tie)
---------- UnexposedExpr (tie)
----------- DeclRefExpr (tie)
------------ NamespaceRef (std)
---------- MemberRefExpr (n)
----------- DeclRefExpr (lh)
---------- MemberRefExpr (c)
----------- DeclRefExpr (lh)
---------- MemberRefExpr (d)
----------- DeclRefExpr (lh)
------- UnexposedExpr (operator<)
-------- DeclRefExpr (operator<)
------- UnexposedExpr ()
-------- UnexposedExpr (tie)
--------- CallExpr (tie)
---------- UnexposedExpr (tie)
----------- DeclRefExpr (tie)
------------ NamespaceRef (std)
---------- MemberRefExpr (n)
----------- DeclRefExpr (rh)
---------- MemberRefExpr (c)
----------- DeclRefExpr (rh)
---------- MemberRefExpr (d)
----------- DeclRefExpr (rh)
- CXXAccessSpecifier ()
- FieldDecl (n)
- FieldDecl (c)
- FieldDecl (d)## `count-function-extents`
Getting this program to run can be a *tiny* bit more trickier. We should
supply it with the default paths required by `clang++`. To determine
them, call$ clang++ -v -c FILE
where `FILE` is a source file of your choice. The resulting output
should contain the line#include <...> search starts here:
and a list of paths. Copy them and put them into one command-line
variable, like so:$ export CPLUS_INCLUDE_PATH=/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1:/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1/x86_64-pc-linux-gnu:/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/7.1.1/../../../../include/c++/7.1.1/backward:/usr/local/include:/usr/bin/../lib/clang/4.0.1/include
Afterwards, you can call the program on a test executable:
$ ./count-function-extents ../examples/functions.cc
This should result in the following output:
Obtained 0 compile commands
theAnswerToLifeTheUniverseAndEverything: 3
sum: 3
square: 3
cube: 3
factorial: 6
fibonacci: 14You can also call the function for any executable specified in
a `compile_commands.json` data base:$ ./count-function-extents ../count-function-extents.cc
Parsing /home/brieck/Projects/libclang-experiments/count-function-extents.cc...
Obtained 1 compile commands
getCursorSpelling: 7
resolvePath: 17
functionVisitor: 24
main: 74I am sure that these programs could be easily improved. I look forward
to your changes!# Additional information
* https://clang.llvm.org/doxygen/group__CINDEX.html
* https://stackoverflow.com/questions/20280744/libclang-returns-too-much-info-about-function-declarations