xref: /llvm-project/clang/docs/LibClang.rst (revision 12d72e4fdee91b3f1e314759d6aa33d25fb38f86)
1.. role:: raw-html(raw)
2    :format: html
3
4Libclang tutorial
5=================
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 relatively stable 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 overview
11-------------------------
12
13All types of libclang are prefixed with ``CX``
14
15CXIndex
16~~~~~~~
17An Index that consists of a set of translation units that would typically be linked together into an executable or library.
18
19CXTranslationUnit
20~~~~~~~~~~~~~~~~~
21A single translation unit, which resides in an index.
22
23CXCursor
24~~~~~~~~
25A cursor representing a pointer to some element in the abstract syntax tree of a translation unit.
26
27
28Code example
29""""""""""""
30
31.. code-block:: cpp
32
33  // file.cpp
34  struct foo{
35    int bar;
36    int* bar_pointer;
37  };
38
39.. code-block:: cpp
40
41  #include <clang-c/Index.h>
42  #include <iostream>
43
44  int main(){
45    CXIndex index = clang_createIndex(0, 0); //Create index
46    CXTranslationUnit unit = clang_parseTranslationUnit(
47      index,
48      "file.cpp", nullptr, 0,
49      nullptr, 0,
50      CXTranslationUnit_None); //Parse "file.cpp"
51
52
53    if (unit == nullptr){
54      std::cerr << "Unable to parse translation unit. Quitting.\n";
55      return 0;
56    }
57    CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
58  }
59
60Visiting elements of an AST
61~~~~~~~~~~~~~~~~~~~~~~~~~~~
62The elements of an AST can be recursively visited with pre-order traversal with ``clang_visitChildren``.
63
64.. code-block:: cpp
65
66  clang_visitChildren(
67    cursor, //Root cursor
68    [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
69
70      CXString current_display_name = clang_getCursorDisplayName(current_cursor);
71      //Allocate a CXString representing the name of the current cursor
72
73      std::cout << "Visiting element " << clang_getCString(current_display_name) << "\n";
74      //Print the char* value of current_display_name
75
76      clang_disposeString(current_display_name);
77      //Since clang_getCursorDisplayName allocates a new CXString, it must be freed. This applies
78      //to all functions returning a CXString
79
80      return CXChildVisit_Recurse;
81
82
83    }, //CXCursorVisitor: a function pointer
84    nullptr //client_data
85    );
86
87The return value of ``CXCursorVisitor``, the callable argument of ``clang_visitChildren``, can return one of the three:
88
89#. ``CXChildVisit_Break``: Terminates the cursor traversal
90
91#. ``CXChildVisit_Continue``: Continues the cursor traversal with the next sibling of the cursor just visited, without visiting its children.
92
93#. ``CXChildVisit_Recurse``: Recursively traverse the children of this cursor, using the same visitor and client data
94
95The expected output of that program is
96
97.. code-block::
98
99  Visiting element foo
100  Visiting element bar
101  Visiting element bar_pointer
102
103
104Extracting information from a Cursor
105~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106.. The following functions take a ``CXCursor`` as an argument and return associated information.
107
108
109
110Extracting the Cursor kind
111""""""""""""""""""""""""""
112
113``CXCursorKind clang_getCursorKind(CXCursor)`` Describes the kind of entity that a cursor refers to. Example values:
114
115- ``CXCursor_StructDecl``: A C or C++ struct.
116- ``CXCursor_FieldDecl``: A field in a struct, union, or C++ class.
117- ``CXCursor_CallExpr``: An expression that calls a function.
118
119
120Extracting the Cursor type
121""""""""""""""""""""""""""
122``CXType clang_getCursorType(CXCursor)``: Retrieve the type of a CXCursor (if any).
123
124A ``CXType`` represents a complete C++ type, including qualifiers and pointers. It has a member field ``CXTypeKind kind`` and additional opaque data.
125
126Example values for ``CXTypeKind kind``
127
128- ``CXType_Invalid``: Represents an invalid type (e.g., where no type is available)
129- ``CXType_Pointer``: A pointer to another type
130- ``CXType_Int``: Regular ``int``
131- ``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.
132
133Any ``CXTypeKind`` can be converted to a ``CXString`` using ``clang_getTypeKindSpelling(CXTypeKind)``.
134
135A ``CXType`` holds additional necessary opaque type info, such as:
136
137- Which struct was referred to?
138- What type is the pointer pointing to?
139- Qualifiers (e.g. ``const``, ``volatile``)?
140
141Qualifiers of a ``CXType`` can be queried with:
142
143- ``clang_isConstQualifiedType(CXType)`` to check for ``const``
144- ``clang_isRestrictQualifiedType(CXType)`` to check for ``restrict``
145- ``clang_isVolatileQualifiedType(CXType)`` to check for ``volatile``
146
147Code example
148""""""""""""
149.. code-block:: cpp
150
151  //structs.cpp
152  struct A{
153    int value;
154  };
155  struct B{
156    int value;
157    A struct_value;
158  };
159
160.. code-block:: cpp
161
162  #include <clang-c/Index.h>
163  #include <iostream>
164
165  int main(){
166    CXIndex index = clang_createIndex(0, 0); //Create index
167    CXTranslationUnit unit = clang_parseTranslationUnit(
168      index,
169      "structs.cpp", nullptr, 0,
170      nullptr, 0,
171      CXTranslationUnit_None); //Parse "structs.cpp"
172
173    if (unit == nullptr){
174      std::cerr << "Unable to parse translation unit. Quitting.\n";
175      return 0;
176    }
177    CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
178
179    clang_visitChildren(
180    cursor,
181    [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
182      CXType cursor_type = clang_getCursorType(current_cursor);
183
184      CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);
185      std::cout << "Type Kind: " << clang_getCString(type_kind_spelling);
186      clang_disposeString(type_kind_spelling);
187
188      if(cursor_type.kind == CXType_Pointer ||                     // If cursor_type is a pointer
189        cursor_type.kind == CXType_LValueReference ||              // or an LValue Reference (&)
190        cursor_type.kind == CXType_RValueReference){               // or an RValue Reference (&&),
191        CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type
192
193        CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type);     // Spell out the entire
194        std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type
195        clang_disposeString(pointed_to_type_spelling);
196      }
197      else if(cursor_type.kind == CXType_Record){
198        CXString type_spelling = clang_getTypeSpelling(cursor_type);
199        std::cout <<  ", namely " << clang_getCString(type_spelling);
200        clang_disposeString(type_spelling);
201      }
202      std::cout << "\n";
203      return CXChildVisit_Recurse;
204    },
205    nullptr
206    );
207
208The expected output of program is:
209
210.. code-block::
211
212  Type Kind: Record, namely A
213  Type Kind: Int
214  Type Kind: Record, namely B
215  Type Kind: Int
216  Type Kind: Record, namely A
217  Type Kind: Record, namely A
218
219
220Reiterating the difference between ``CXType`` and ``CXTypeKind``: For an example
221
222.. code-block:: cpp
223
224   const char* __restrict__ variable;
225
226- Type Kind will be: ``CXType_Pointer`` spelled ``"Pointer"``
227- Type will be a complex ``CXType`` structure, spelled ``"const char* __restrict__``
228
229Retrieving source locations
230"""""""""""""""""""""""""""
231
232``CXSourceRange clang_getCursorExtent(CXCursor)`` returns a ``CXSourceRange``, representing a half-open range in the source code.
233
234Use ``clang_getRangeStart(CXSourceRange)`` and ``clang_getRangeEnd(CXSourceRange)`` to retrieve the starting and end ``CXSourceLocation`` from a source range, respectively.
235
236Given a ``CXSourceLocation``, use ``clang_getExpansionLocation`` to retrieve file, line and column of a source location.
237
238Code example
239""""""""""""
240.. code-block:: cpp
241
242  // Again, file.cpp
243  struct foo{
244    int bar;
245    int* bar_pointer;
246  };
247.. code-block:: cpp
248
249  clang_visitChildren(
250    cursor,
251    [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
252
253      CXType cursor_type = clang_getCursorType(current_cursor);
254      CXString cursor_spelling = clang_getCursorSpelling(current_cursor);
255      CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);
256      std::cout << "Cursor " << clang_getCString(cursor_spelling);
257
258      CXFile file;
259      unsigned start_line, start_column, start_offset;
260      unsigned end_line, end_column, end_offset;
261
262      clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);
263      clang_getExpansionLocation(clang_getRangeEnd  (cursor_range), &file, &end_line  , &end_column  , &end_offset);
264      std::cout << " spanning lines " << start_line << " to " << end_line;
265      clang_disposeString(cursor_spelling);
266
267      std::cout << "\n";
268      return CXChildVisit_Recurse;
269    },
270    nullptr
271  );
272
273The expected output of this program is:
274
275.. code-block::
276
277  Cursor foo spanning lines 2 to 5
278  Cursor bar spanning lines 3 to 3
279  Cursor bar_pointer spanning lines 4 to 4
280
281Complete example code
282~~~~~~~~~~~~~~~~~~~~~
283
284.. code-block:: cpp
285
286  #include <clang-c/Index.h>
287  #include <iostream>
288
289  int main(){
290    CXIndex index = clang_createIndex(0, 0); //Create index
291    CXTranslationUnit unit = clang_parseTranslationUnit(
292      index,
293      "file.cpp", nullptr, 0,
294      nullptr, 0,
295      CXTranslationUnit_None); //Parse "file.cpp"
296
297    if (unit == nullptr){
298      std::cerr << "Unable to parse translation unit. Quitting.\n";
299      return 0;
300    }
301    CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
302
303
304    clang_visitChildren(
305    cursor,
306    [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
307      CXType cursor_type = clang_getCursorType(current_cursor);
308
309      CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);
310      std::cout << "TypeKind: " << clang_getCString(type_kind_spelling);
311      clang_disposeString(type_kind_spelling);
312
313      if(cursor_type.kind == CXType_Pointer ||                     // If cursor_type is a pointer
314        cursor_type.kind == CXType_LValueReference ||              // or an LValue Reference (&)
315        cursor_type.kind == CXType_RValueReference){               // or an RValue Reference (&&),
316        CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type
317
318        CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type);     // Spell out the entire
319        std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type
320        clang_disposeString(pointed_to_type_spelling);
321      }
322      else if(cursor_type.kind == CXType_Record){
323        CXString type_spelling = clang_getTypeSpelling(cursor_type);
324        std::cout <<  ", namely " << clang_getCString(type_spelling);
325        clang_disposeString(type_spelling);
326      }
327      std::cout << "\n";
328      return CXChildVisit_Recurse;
329    },
330    nullptr
331    );
332
333
334    clang_visitChildren(
335    cursor,
336    [](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
337
338      CXType cursor_type = clang_getCursorType(current_cursor);
339      CXString cursor_spelling = clang_getCursorSpelling(current_cursor);
340      CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);
341      std::cout << "Cursor " << clang_getCString(cursor_spelling);
342
343      CXFile file;
344      unsigned start_line, start_column, start_offset;
345      unsigned end_line, end_column, end_offset;
346
347      clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);
348      clang_getExpansionLocation(clang_getRangeEnd  (cursor_range), &file, &end_line  , &end_column  , &end_offset);
349      std::cout << " spanning lines " << start_line << " to " << end_line;
350      clang_disposeString(cursor_spelling);
351
352      std::cout << "\n";
353      return CXChildVisit_Recurse;
354    },
355    nullptr
356    );
357  }
358
359
360.. _Index.h: https://github.com/llvm/llvm-project/blob/main/clang/include/clang-c/Index.h
361