446 lines · plain
1.. role:: raw-html(raw)2 :format: html3 4Libclang tutorial5=================6The C Interface to Clang provides a relatively small API that exposes facilities for parsing source code into an abstract syntax tree (AST), loading already-parsed ASTs, traversing the AST, associating physical source locations with elements within the AST, and other facilities that support Clang-based development tools.7This C interface to Clang will never provide all of the information representation stored in Clang's C++ AST, nor should it: the intent is to maintain an API that is :ref:`relatively stable <Stability>` from one release to the next, providing only the basic functionality needed to support development tools.8The entire C interface of libclang is available in the file `Index.h`_9 10Essential types overview11-------------------------12 13All types of libclang are prefixed with ``CX``14 15CXIndex16~~~~~~~17An Index that consists of a set of translation units that would typically be linked together into an executable or library.18 19CXTranslationUnit20~~~~~~~~~~~~~~~~~21A single translation unit, which resides in an index.22 23CXCursor24~~~~~~~~25A cursor representing a pointer to some element in the abstract syntax tree of a translation unit.26 27 28Code example29""""""""""""30 31.. code-block:: cpp32 33 // file.cpp34 struct foo{35 int bar;36 int* bar_pointer;37 };38 39.. code-block:: cpp40 41 // main.cpp42 #include <clang-c/Index.h>43 #include <iostream>44 45 int main(){46 CXIndex index = clang_createIndex(0, 0); //Create index47 CXTranslationUnit unit = clang_parseTranslationUnit(48 index,49 "file.cpp", nullptr, 0,50 nullptr, 0,51 CXTranslationUnit_None); //Parse "file.cpp"52 53 54 if (unit == nullptr){55 std::cerr << "Unable to parse translation unit. Quitting.\n";56 return 0;57 }58 CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit59 }60 61.. code-block:: cmake62 63 # CMakeLists.txt64 cmake_minimum_required(VERSION 3.20)65 project(my_clang_tool VERSION 0.1.0)66 67 # This will find the default system installation of Clang; if you want to68 # use a different build of clang, pass -DClang_DIR=/foobar/lib/cmake/clang69 # to the CMake configure command, where /foobar is the build directory where70 # you built Clang.71 find_package(Clang CONFIG REQUIRED)72 73 add_executable(my_clang_tool main.cpp)74 target_include_directories(my_clang_tool PRIVATE ${CLANG_INCLUDE_DIRS})75 target_link_libraries(my_clang_tool PRIVATE libclang)76 77Visiting elements of an AST78~~~~~~~~~~~~~~~~~~~~~~~~~~~79The elements of an AST can be recursively visited with pre-order traversal with ``clang_visitChildren``.80 81.. code-block:: cpp82 83 clang_visitChildren(84 cursor, //Root cursor85 [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){86 87 CXString current_display_name = clang_getCursorDisplayName(current_cursor);88 //Allocate a CXString representing the name of the current cursor89 90 std::cout << "Visiting element " << clang_getCString(current_display_name) << "\n";91 //Print the char* value of current_display_name92 93 clang_disposeString(current_display_name);94 //Since clang_getCursorDisplayName allocates a new CXString, it must be freed. This applies95 //to all functions returning a CXString96 97 return CXChildVisit_Recurse;98 99 100 }, //CXCursorVisitor: a function pointer101 nullptr //client_data102 );103 104The return value of ``CXCursorVisitor``, the callable argument of ``clang_visitChildren``, can return one of the three:105 106#. ``CXChildVisit_Break``: Terminates the cursor traversal107 108#. ``CXChildVisit_Continue``: Continues the cursor traversal with the next sibling of the cursor just visited, without visiting its children.109 110#. ``CXChildVisit_Recurse``: Recursively traverse the children of this cursor, using the same visitor and client data111 112The expected output of that program is113 114.. code-block::115 116 Visiting element foo117 Visiting element bar118 Visiting element bar_pointer119 120 121Extracting information from a Cursor122~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~123.. The following functions take a ``CXCursor`` as an argument and return associated information.124 125 126 127Extracting the Cursor kind128""""""""""""""""""""""""""129 130``CXCursorKind clang_getCursorKind(CXCursor)`` Describes the kind of entity that a cursor refers to. Example values:131 132- ``CXCursor_StructDecl``: A C or C++ struct.133- ``CXCursor_FieldDecl``: A field in a struct, union, or C++ class.134- ``CXCursor_CallExpr``: An expression that calls a function.135 136 137Extracting the Cursor type138""""""""""""""""""""""""""139``CXType clang_getCursorType(CXCursor)``: Retrieve the type of a CXCursor (if any).140 141A ``CXType`` represents a complete C++ type, including qualifiers and pointers. It has a member field ``CXTypeKind kind`` and additional opaque data.142 143Example values for ``CXTypeKind kind``144 145- ``CXType_Invalid``: Represents an invalid type (e.g., where no type is available)146- ``CXType_Pointer``: A pointer to another type147- ``CXType_Int``: Regular ``int``148- ``CXType_Elaborated``: Represents a type that was referred to using an elaborated type keyword e.g. struct S, or via a qualified name, e.g., N::M::type, or both.149 150Any ``CXTypeKind`` can be converted to a ``CXString`` using ``clang_getTypeKindSpelling(CXTypeKind)``.151 152A ``CXType`` holds additional necessary opaque type info, such as:153 154- Which struct was referred to?155- What type is the pointer pointing to?156- Qualifiers (e.g. ``const``, ``volatile``)?157 158Qualifiers of a ``CXType`` can be queried with:159 160- ``clang_isConstQualifiedType(CXType)`` to check for ``const``161- ``clang_isRestrictQualifiedType(CXType)`` to check for ``restrict``162- ``clang_isVolatileQualifiedType(CXType)`` to check for ``volatile``163 164Code example165""""""""""""166.. code-block:: cpp167 168 //structs.cpp169 struct A{170 int value;171 };172 struct B{173 int value;174 A struct_value;175 };176 177.. code-block:: cpp178 179 #include <clang-c/Index.h>180 #include <iostream>181 182 int main(){183 CXIndex index = clang_createIndex(0, 0); //Create index184 CXTranslationUnit unit = clang_parseTranslationUnit(185 index,186 "structs.cpp", nullptr, 0,187 nullptr, 0,188 CXTranslationUnit_None); //Parse "structs.cpp"189 190 if (unit == nullptr){191 std::cerr << "Unable to parse translation unit. Quitting.\n";192 return 0;193 }194 CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit195 196 clang_visitChildren(197 cursor,198 [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){199 CXType cursor_type = clang_getCursorType(current_cursor);200 201 CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);202 std::cout << "Type Kind: " << clang_getCString(type_kind_spelling);203 clang_disposeString(type_kind_spelling);204 205 if(cursor_type.kind == CXType_Pointer || // If cursor_type is a pointer206 cursor_type.kind == CXType_LValueReference || // or an LValue Reference (&)207 cursor_type.kind == CXType_RValueReference){ // or an RValue Reference (&&),208 CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type209 210 CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type); // Spell out the entire211 std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type212 clang_disposeString(pointed_to_type_spelling);213 }214 else if(cursor_type.kind == CXType_Record){215 CXString type_spelling = clang_getTypeSpelling(cursor_type);216 std::cout << ", namely " << clang_getCString(type_spelling);217 clang_disposeString(type_spelling);218 }219 std::cout << "\n";220 return CXChildVisit_Recurse;221 },222 nullptr223 );224 225The expected output of program is:226 227.. code-block::228 229 Type Kind: Record, namely A230 Type Kind: Int231 Type Kind: Record, namely B232 Type Kind: Int233 Type Kind: Record, namely A234 Type Kind: Record, namely A235 236 237Reiterating the difference between ``CXType`` and ``CXTypeKind``: For an example238 239.. code-block:: cpp240 241 const char* __restrict__ variable;242 243- Type Kind will be: ``CXType_Pointer`` spelled ``"Pointer"``244- Type will be a complex ``CXType`` structure, spelled ``"const char* __restrict__``245 246Retrieving source locations247"""""""""""""""""""""""""""248 249``CXSourceRange clang_getCursorExtent(CXCursor)`` returns a ``CXSourceRange``, representing a half-open range in the source code.250 251Use ``clang_getRangeStart(CXSourceRange)`` and ``clang_getRangeEnd(CXSourceRange)`` to retrieve the starting and end ``CXSourceLocation`` from a source range, respectively.252 253Given a ``CXSourceLocation``, use ``clang_getExpansionLocation`` to retrieve file, line and column of a source location.254 255Code example256""""""""""""257.. code-block:: cpp258 259 // Again, file.cpp260 struct foo{261 int bar;262 int* bar_pointer;263 };264.. code-block:: cpp265 266 clang_visitChildren(267 cursor,268 [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){269 270 CXType cursor_type = clang_getCursorType(current_cursor);271 CXString cursor_spelling = clang_getCursorSpelling(current_cursor);272 CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);273 std::cout << "Cursor " << clang_getCString(cursor_spelling);274 275 CXFile file;276 unsigned start_line, start_column, start_offset;277 unsigned end_line, end_column, end_offset;278 279 clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);280 clang_getExpansionLocation(clang_getRangeEnd (cursor_range), &file, &end_line , &end_column , &end_offset);281 std::cout << " spanning lines " << start_line << " to " << end_line;282 clang_disposeString(cursor_spelling);283 284 std::cout << "\n";285 return CXChildVisit_Recurse;286 },287 nullptr288 );289 290The expected output of this program is:291 292.. code-block::293 294 Cursor foo spanning lines 2 to 5295 Cursor bar spanning lines 3 to 3296 Cursor bar_pointer spanning lines 4 to 4297 298Complete example code299~~~~~~~~~~~~~~~~~~~~~300 301.. code-block:: cpp302 303 // main.cpp304 #include <clang-c/Index.h>305 #include <iostream>306 307 int main(){308 CXIndex index = clang_createIndex(0, 0); //Create index309 CXTranslationUnit unit = clang_parseTranslationUnit(310 index,311 "file.cpp", nullptr, 0,312 nullptr, 0,313 CXTranslationUnit_None); //Parse "file.cpp"314 315 if (unit == nullptr){316 std::cerr << "Unable to parse translation unit. Quitting.\n";317 return 0;318 }319 CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit320 321 322 clang_visitChildren(323 cursor,324 [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){325 CXType cursor_type = clang_getCursorType(current_cursor);326 327 CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);328 std::cout << "TypeKind: " << clang_getCString(type_kind_spelling);329 clang_disposeString(type_kind_spelling);330 331 if(cursor_type.kind == CXType_Pointer || // If cursor_type is a pointer332 cursor_type.kind == CXType_LValueReference || // or an LValue Reference (&)333 cursor_type.kind == CXType_RValueReference){ // or an RValue Reference (&&),334 CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type335 336 CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type); // Spell out the entire337 std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type338 clang_disposeString(pointed_to_type_spelling);339 }340 else if(cursor_type.kind == CXType_Record){341 CXString type_spelling = clang_getTypeSpelling(cursor_type);342 std::cout << ", namely " << clang_getCString(type_spelling);343 clang_disposeString(type_spelling);344 }345 std::cout << "\n";346 return CXChildVisit_Recurse;347 },348 nullptr349 );350 351 352 clang_visitChildren(353 cursor,354 [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){355 356 CXType cursor_type = clang_getCursorType(current_cursor);357 CXString cursor_spelling = clang_getCursorSpelling(current_cursor);358 CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);359 std::cout << "Cursor " << clang_getCString(cursor_spelling);360 361 CXFile file;362 unsigned start_line, start_column, start_offset;363 unsigned end_line, end_column, end_offset;364 365 clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);366 clang_getExpansionLocation(clang_getRangeEnd (cursor_range), &file, &end_line , &end_column , &end_offset);367 std::cout << " spanning lines " << start_line << " to " << end_line;368 clang_disposeString(cursor_spelling);369 370 std::cout << "\n";371 return CXChildVisit_Recurse;372 },373 nullptr374 );375 }376 377.. code-block:: cmake378 379 # CMakeLists.txt380 cmake_minimum_required(VERSION 3.20)381 project(my_clang_tool VERSION 0.1.0)382 383 # This will find the default system installation of Clang; if you want to384 # use a different build of clang, pass -DClang_DIR=/foobar/lib/cmake/clang385 # to the CMake configure command, where /foobar is the build directory where386 # you built Clang.387 find_package(Clang CONFIG REQUIRED)388 389 add_executable(my_clang_tool main.cpp)390 target_include_directories(my_clang_tool PRIVATE ${CLANG_INCLUDE_DIRS})391 target_link_libraries(my_clang_tool PRIVATE libclang)392 393.. _Index.h: https://github.com/llvm/llvm-project/blob/main/clang/include/clang-c/Index.h394 395.. _Stability:396 397ABI and API Stability398---------------------399 400The C interfaces in libclang are intended to be relatively stable. This allows401a programmer to use libclang without having to worry as much about Clang402upgrades breaking existing code. However, the library is not unchanging. For403example, the library will gain new interfaces over time as needs arise,404existing APIs may be deprecated for eventual removal, etc. Also, the underlying405implementation of the facilities by Clang may change behavior as bugs are406fixed, features get implemented, etc.407 408The library should be ABI and API stable over time, but ABI- and API-breaking409changes can happen in the following (non-exhaustive) situations:410 411* Adding new enumerator to an enumeration (can be ABI-breaking in C++).412* Removing an explicitly deprecated API after a suitably long deprecation413 period.414* Using implementation details, such as names or comments that say something415 is "private", "reserved", "internal", etc.416* Bug fixes and changes to Clang's internal implementation happen routinely and417 will change the behavior of callers.418* Rarely, bug fixes to libclang itself.419 420The library has version macros (``CINDEX_VERSION_MAJOR``,421``CINDEX_VERSION_MINOR``, and ``CINDEX_VERSION``) which can be used to test for422specific library versions at compile time. The ``CINDEX_VERSION_MAJOR`` macro423is only incremented if there are major source- or ABI-breaking changes. Except424for removing an explicitly deprecated API, the changes listed above are not425considered major source- or ABI-breaking changes. Historically, the value this426macro expands to has not changed, but may be incremented in the future should427the need arise. The ``CINDEX_VERSION_MINOR`` macro is incremented as new APIs428are added. The ``CINDEX_VERSION`` macro expands to a value based on the major429and minor version macros.430 431In an effort to allow the library to be modified as new needs arise, the432following situations are explicitly unsupported:433 434* Loading different library versions into the same executable and passing435 objects between the libraries; despite general ABI stability, different436 versions of the library may use different implementation details that are not437 compatible across library versions.438* For the same reason as above, serializing objects from one version of the439 library and deserializing with a different version is also not supported.440 441Note: because libclang is a wrapper around the compiler frontend, it is not a442`security-sensitive component`_ of the LLVM Project. Consider using a sandbox443or some other mitigation approach if processing untrusted input.444 445.. _security-sensitive component: https://llvm.org/docs/Security.html#what-is-considered-a-security-issue446