brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.0 KiB · 6c62bcb Raw
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