• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! A higher level Clang API built on top of the generated bindings in the
2 //! `clang_sys` module.
3 
4 #![allow(non_upper_case_globals, dead_code)]
5 
6 use crate::ir::context::BindgenContext;
7 use clang_sys::*;
8 use std::ffi::{CStr, CString};
9 use std::fmt;
10 use std::hash::Hash;
11 use std::hash::Hasher;
12 use std::os::raw::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong};
13 use std::{mem, ptr, slice};
14 
15 /// Type representing a clang attribute.
16 ///
17 /// Values of this type can be used to check for different attributes using the `has_attrs`
18 /// function.
19 pub struct Attribute {
20     name: &'static [u8],
21     kind: Option<CXCursorKind>,
22     token_kind: CXTokenKind,
23 }
24 
25 impl Attribute {
26     /// A `warn_unused_result` attribute.
27     pub const MUST_USE: Self = Self {
28         name: b"warn_unused_result",
29         // FIXME(emilio): clang-sys doesn't expose `CXCursor_WarnUnusedResultAttr` (from clang 9).
30         kind: Some(440),
31         token_kind: CXToken_Identifier,
32     };
33 
34     /// A `_Noreturn` attribute.
35     pub const NO_RETURN: Self = Self {
36         name: b"_Noreturn",
37         kind: None,
38         token_kind: CXToken_Keyword,
39     };
40 
41     /// A `[[noreturn]]` attribute.
42     pub const NO_RETURN_CPP: Self = Self {
43         name: b"noreturn",
44         kind: None,
45         token_kind: CXToken_Identifier,
46     };
47 }
48 
49 /// A cursor into the Clang AST, pointing to an AST node.
50 ///
51 /// We call the AST node pointed to by the cursor the cursor's "referent".
52 #[derive(Copy, Clone)]
53 pub struct Cursor {
54     x: CXCursor,
55 }
56 
57 impl fmt::Debug for Cursor {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result58     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
59         write!(
60             fmt,
61             "Cursor({} kind: {}, loc: {}, usr: {:?})",
62             self.spelling(),
63             kind_to_str(self.kind()),
64             self.location(),
65             self.usr()
66         )
67     }
68 }
69 
70 impl Cursor {
71     /// Get the Unified Symbol Resolution for this cursor's referent, if
72     /// available.
73     ///
74     /// The USR can be used to compare entities across translation units.
usr(&self) -> Option<String>75     pub fn usr(&self) -> Option<String> {
76         let s = unsafe { cxstring_into_string(clang_getCursorUSR(self.x)) };
77         if s.is_empty() {
78             None
79         } else {
80             Some(s)
81         }
82     }
83 
84     /// Is this cursor's referent a declaration?
is_declaration(&self) -> bool85     pub fn is_declaration(&self) -> bool {
86         unsafe { clang_isDeclaration(self.kind()) != 0 }
87     }
88 
89     /// Is this cursor's referent an anonymous record or so?
is_anonymous(&self) -> bool90     pub fn is_anonymous(&self) -> bool {
91         unsafe { clang_Cursor_isAnonymous(self.x) != 0 }
92     }
93 
94     /// Get this cursor's referent's spelling.
spelling(&self) -> String95     pub fn spelling(&self) -> String {
96         unsafe { cxstring_into_string(clang_getCursorSpelling(self.x)) }
97     }
98 
99     /// Get this cursor's referent's display name.
100     ///
101     /// This is not necessarily a valid identifier. It includes extra
102     /// information, such as parameters for a function, etc.
display_name(&self) -> String103     pub fn display_name(&self) -> String {
104         unsafe { cxstring_into_string(clang_getCursorDisplayName(self.x)) }
105     }
106 
107     /// Get the mangled name of this cursor's referent.
mangling(&self) -> String108     pub fn mangling(&self) -> String {
109         unsafe { cxstring_into_string(clang_Cursor_getMangling(self.x)) }
110     }
111 
112     /// Gets the C++ manglings for this cursor, or an error if the manglings
113     /// are not available.
cxx_manglings(&self) -> Result<Vec<String>, ()>114     pub fn cxx_manglings(&self) -> Result<Vec<String>, ()> {
115         use clang_sys::*;
116         unsafe {
117             let manglings = clang_Cursor_getCXXManglings(self.x);
118             if manglings.is_null() {
119                 return Err(());
120             }
121             let count = (*manglings).Count as usize;
122 
123             let mut result = Vec::with_capacity(count);
124             for i in 0..count {
125                 let string_ptr = (*manglings).Strings.add(i);
126                 result.push(cxstring_to_string_leaky(*string_ptr));
127             }
128             clang_disposeStringSet(manglings);
129             Ok(result)
130         }
131     }
132 
133     /// Returns whether the cursor refers to a built-in definition.
is_builtin(&self) -> bool134     pub fn is_builtin(&self) -> bool {
135         let (file, _, _, _) = self.location().location();
136         file.name().is_none()
137     }
138 
139     /// Get the `Cursor` for this cursor's referent's lexical parent.
140     ///
141     /// The lexical parent is the parent of the definition. The semantic parent
142     /// is the parent of the declaration. Generally, the lexical parent doesn't
143     /// have any effect on semantics, while the semantic parent does.
144     ///
145     /// In the following snippet, the `Foo` class would be the semantic parent
146     /// of the out-of-line `method` definition, while the lexical parent is the
147     /// translation unit.
148     ///
149     /// ```c++
150     /// class Foo {
151     ///     void method();
152     /// };
153     ///
154     /// void Foo::method() { /* ... */ }
155     /// ```
lexical_parent(&self) -> Cursor156     pub fn lexical_parent(&self) -> Cursor {
157         unsafe {
158             Cursor {
159                 x: clang_getCursorLexicalParent(self.x),
160             }
161         }
162     }
163 
164     /// Get the referent's semantic parent, if one is available.
165     ///
166     /// See documentation for `lexical_parent` for details on semantic vs
167     /// lexical parents.
fallible_semantic_parent(&self) -> Option<Cursor>168     pub fn fallible_semantic_parent(&self) -> Option<Cursor> {
169         let sp = unsafe {
170             Cursor {
171                 x: clang_getCursorSemanticParent(self.x),
172             }
173         };
174         if sp == *self || !sp.is_valid() {
175             return None;
176         }
177         Some(sp)
178     }
179 
180     /// Get the referent's semantic parent.
181     ///
182     /// See documentation for `lexical_parent` for details on semantic vs
183     /// lexical parents.
semantic_parent(&self) -> Cursor184     pub fn semantic_parent(&self) -> Cursor {
185         self.fallible_semantic_parent().unwrap()
186     }
187 
188     /// Return the number of template arguments used by this cursor's referent,
189     /// if the referent is either a template instantiation. Returns `None`
190     /// otherwise.
191     ///
192     /// NOTE: This may not return `Some` for partial template specializations,
193     /// see #193 and #194.
num_template_args(&self) -> Option<u32>194     pub fn num_template_args(&self) -> Option<u32> {
195         // XXX: `clang_Type_getNumTemplateArguments` is sort of reliable, while
196         // `clang_Cursor_getNumTemplateArguments` is totally unreliable.
197         // Therefore, try former first, and only fallback to the latter if we
198         // have to.
199         self.cur_type()
200             .num_template_args()
201             .or_else(|| {
202                 let n: c_int =
203                     unsafe { clang_Cursor_getNumTemplateArguments(self.x) };
204 
205                 if n >= 0 {
206                     Some(n as u32)
207                 } else {
208                     debug_assert_eq!(n, -1);
209                     None
210                 }
211             })
212             .or_else(|| {
213                 let canonical = self.canonical();
214                 if canonical != *self {
215                     canonical.num_template_args()
216                 } else {
217                     None
218                 }
219             })
220     }
221 
222     /// Get a cursor pointing to this referent's containing translation unit.
223     ///
224     /// Note that we shouldn't create a `TranslationUnit` struct here, because
225     /// bindgen assumes there will only be one of them alive at a time, and
226     /// disposes it on drop. That can change if this would be required, but I
227     /// think we can survive fine without it.
translation_unit(&self) -> Cursor228     pub fn translation_unit(&self) -> Cursor {
229         assert!(self.is_valid());
230         unsafe {
231             let tu = clang_Cursor_getTranslationUnit(self.x);
232             let cursor = Cursor {
233                 x: clang_getTranslationUnitCursor(tu),
234             };
235             assert!(cursor.is_valid());
236             cursor
237         }
238     }
239 
240     /// Is the referent a top level construct?
is_toplevel(&self) -> bool241     pub fn is_toplevel(&self) -> bool {
242         let mut semantic_parent = self.fallible_semantic_parent();
243 
244         while semantic_parent.is_some() &&
245             (semantic_parent.unwrap().kind() == CXCursor_Namespace ||
246                 semantic_parent.unwrap().kind() ==
247                     CXCursor_NamespaceAlias ||
248                 semantic_parent.unwrap().kind() == CXCursor_NamespaceRef)
249         {
250             semantic_parent =
251                 semantic_parent.unwrap().fallible_semantic_parent();
252         }
253 
254         let tu = self.translation_unit();
255         // Yes, this can happen with, e.g., macro definitions.
256         semantic_parent == tu.fallible_semantic_parent()
257     }
258 
259     /// There are a few kinds of types that we need to treat specially, mainly
260     /// not tracking the type declaration but the location of the cursor, given
261     /// clang doesn't expose a proper declaration for these types.
is_template_like(&self) -> bool262     pub fn is_template_like(&self) -> bool {
263         matches!(
264             self.kind(),
265             CXCursor_ClassTemplate |
266                 CXCursor_ClassTemplatePartialSpecialization |
267                 CXCursor_TypeAliasTemplateDecl
268         )
269     }
270 
271     /// Is this Cursor pointing to a function-like macro definition?
is_macro_function_like(&self) -> bool272     pub fn is_macro_function_like(&self) -> bool {
273         unsafe { clang_Cursor_isMacroFunctionLike(self.x) != 0 }
274     }
275 
276     /// Get the kind of referent this cursor is pointing to.
kind(&self) -> CXCursorKind277     pub fn kind(&self) -> CXCursorKind {
278         self.x.kind
279     }
280 
281     /// Returns true if the cursor is a definition
is_definition(&self) -> bool282     pub fn is_definition(&self) -> bool {
283         unsafe { clang_isCursorDefinition(self.x) != 0 }
284     }
285 
286     /// Is the referent a template specialization?
is_template_specialization(&self) -> bool287     pub fn is_template_specialization(&self) -> bool {
288         self.specialized().is_some()
289     }
290 
291     /// Is the referent a fully specialized template specialization without any
292     /// remaining free template arguments?
is_fully_specialized_template(&self) -> bool293     pub fn is_fully_specialized_template(&self) -> bool {
294         self.is_template_specialization() &&
295             self.kind() != CXCursor_ClassTemplatePartialSpecialization &&
296             self.num_template_args().unwrap_or(0) > 0
297     }
298 
299     /// Is the referent a template specialization that still has remaining free
300     /// template arguments?
is_in_non_fully_specialized_template(&self) -> bool301     pub fn is_in_non_fully_specialized_template(&self) -> bool {
302         if self.is_toplevel() {
303             return false;
304         }
305 
306         let parent = self.semantic_parent();
307         if parent.is_fully_specialized_template() {
308             return false;
309         }
310 
311         if !parent.is_template_like() {
312             return parent.is_in_non_fully_specialized_template();
313         }
314 
315         true
316     }
317 
318     /// Is the referent any kind of template parameter?
is_template_parameter(&self) -> bool319     pub fn is_template_parameter(&self) -> bool {
320         matches!(
321             self.kind(),
322             CXCursor_TemplateTemplateParameter |
323                 CXCursor_TemplateTypeParameter |
324                 CXCursor_NonTypeTemplateParameter
325         )
326     }
327 
328     /// Does the referent's type or value depend on a template parameter?
is_dependent_on_template_parameter(&self) -> bool329     pub fn is_dependent_on_template_parameter(&self) -> bool {
330         fn visitor(
331             found_template_parameter: &mut bool,
332             cur: Cursor,
333         ) -> CXChildVisitResult {
334             // If we found a template parameter, it is dependent.
335             if cur.is_template_parameter() {
336                 *found_template_parameter = true;
337                 return CXChildVisit_Break;
338             }
339 
340             // Get the referent and traverse it as well.
341             if let Some(referenced) = cur.referenced() {
342                 if referenced.is_template_parameter() {
343                     *found_template_parameter = true;
344                     return CXChildVisit_Break;
345                 }
346 
347                 referenced
348                     .visit(|next| visitor(found_template_parameter, next));
349                 if *found_template_parameter {
350                     return CXChildVisit_Break;
351                 }
352             }
353 
354             // Continue traversing the AST at the original cursor.
355             CXChildVisit_Recurse
356         }
357 
358         if self.is_template_parameter() {
359             return true;
360         }
361 
362         let mut found_template_parameter = false;
363         self.visit(|next| visitor(&mut found_template_parameter, next));
364 
365         found_template_parameter
366     }
367 
368     /// Is this cursor pointing a valid referent?
is_valid(&self) -> bool369     pub fn is_valid(&self) -> bool {
370         unsafe { clang_isInvalid(self.kind()) == 0 }
371     }
372 
373     /// Get the source location for the referent.
location(&self) -> SourceLocation374     pub fn location(&self) -> SourceLocation {
375         unsafe {
376             SourceLocation {
377                 x: clang_getCursorLocation(self.x),
378             }
379         }
380     }
381 
382     /// Get the source location range for the referent.
extent(&self) -> CXSourceRange383     pub fn extent(&self) -> CXSourceRange {
384         unsafe { clang_getCursorExtent(self.x) }
385     }
386 
387     /// Get the raw declaration comment for this referent, if one exists.
raw_comment(&self) -> Option<String>388     pub fn raw_comment(&self) -> Option<String> {
389         let s = unsafe {
390             cxstring_into_string(clang_Cursor_getRawCommentText(self.x))
391         };
392         if s.is_empty() {
393             None
394         } else {
395             Some(s)
396         }
397     }
398 
399     /// Get the referent's parsed comment.
comment(&self) -> Comment400     pub fn comment(&self) -> Comment {
401         unsafe {
402             Comment {
403                 x: clang_Cursor_getParsedComment(self.x),
404             }
405         }
406     }
407 
408     /// Get the referent's type.
cur_type(&self) -> Type409     pub fn cur_type(&self) -> Type {
410         unsafe {
411             Type {
412                 x: clang_getCursorType(self.x),
413             }
414         }
415     }
416 
417     /// Given that this cursor's referent is a reference to another type, or is
418     /// a declaration, get the cursor pointing to the referenced type or type of
419     /// the declared thing.
definition(&self) -> Option<Cursor>420     pub fn definition(&self) -> Option<Cursor> {
421         unsafe {
422             let ret = Cursor {
423                 x: clang_getCursorDefinition(self.x),
424             };
425 
426             if ret.is_valid() && ret.kind() != CXCursor_NoDeclFound {
427                 Some(ret)
428             } else {
429                 None
430             }
431         }
432     }
433 
434     /// Given that this cursor's referent is reference type, get the cursor
435     /// pointing to the referenced type.
referenced(&self) -> Option<Cursor>436     pub fn referenced(&self) -> Option<Cursor> {
437         unsafe {
438             let ret = Cursor {
439                 x: clang_getCursorReferenced(self.x),
440             };
441 
442             if ret.is_valid() {
443                 Some(ret)
444             } else {
445                 None
446             }
447         }
448     }
449 
450     /// Get the canonical cursor for this referent.
451     ///
452     /// Many types can be declared multiple times before finally being properly
453     /// defined. This method allows us to get the canonical cursor for the
454     /// referent type.
canonical(&self) -> Cursor455     pub fn canonical(&self) -> Cursor {
456         unsafe {
457             Cursor {
458                 x: clang_getCanonicalCursor(self.x),
459             }
460         }
461     }
462 
463     /// Given that this cursor points to either a template specialization or a
464     /// template instantiation, get a cursor pointing to the template definition
465     /// that is being specialized.
specialized(&self) -> Option<Cursor>466     pub fn specialized(&self) -> Option<Cursor> {
467         unsafe {
468             let ret = Cursor {
469                 x: clang_getSpecializedCursorTemplate(self.x),
470             };
471             if ret.is_valid() {
472                 Some(ret)
473             } else {
474                 None
475             }
476         }
477     }
478 
479     /// Assuming that this cursor's referent is a template declaration, get the
480     /// kind of cursor that would be generated for its specializations.
template_kind(&self) -> CXCursorKind481     pub fn template_kind(&self) -> CXCursorKind {
482         unsafe { clang_getTemplateCursorKind(self.x) }
483     }
484 
485     /// Traverse this cursor's referent and its children.
486     ///
487     /// Call the given function on each AST node traversed.
visit<Visitor>(&self, mut visitor: Visitor) where Visitor: FnMut(Cursor) -> CXChildVisitResult,488     pub fn visit<Visitor>(&self, mut visitor: Visitor)
489     where
490         Visitor: FnMut(Cursor) -> CXChildVisitResult,
491     {
492         let data = &mut visitor as *mut Visitor;
493         unsafe {
494             clang_visitChildren(self.x, visit_children::<Visitor>, data.cast());
495         }
496     }
497 
498     /// Collect all of this cursor's children into a vec and return them.
collect_children(&self) -> Vec<Cursor>499     pub fn collect_children(&self) -> Vec<Cursor> {
500         let mut children = vec![];
501         self.visit(|c| {
502             children.push(c);
503             CXChildVisit_Continue
504         });
505         children
506     }
507 
508     /// Does this cursor have any children?
has_children(&self) -> bool509     pub fn has_children(&self) -> bool {
510         let mut has_children = false;
511         self.visit(|_| {
512             has_children = true;
513             CXChildVisit_Break
514         });
515         has_children
516     }
517 
518     /// Does this cursor have at least `n` children?
has_at_least_num_children(&self, n: usize) -> bool519     pub fn has_at_least_num_children(&self, n: usize) -> bool {
520         assert!(n > 0);
521         let mut num_left = n;
522         self.visit(|_| {
523             num_left -= 1;
524             if num_left == 0 {
525                 CXChildVisit_Break
526             } else {
527                 CXChildVisit_Continue
528             }
529         });
530         num_left == 0
531     }
532 
533     /// Returns whether the given location contains a cursor with the given
534     /// kind in the first level of nesting underneath (doesn't look
535     /// recursively).
contains_cursor(&self, kind: CXCursorKind) -> bool536     pub fn contains_cursor(&self, kind: CXCursorKind) -> bool {
537         let mut found = false;
538 
539         self.visit(|c| {
540             if c.kind() == kind {
541                 found = true;
542                 CXChildVisit_Break
543             } else {
544                 CXChildVisit_Continue
545             }
546         });
547 
548         found
549     }
550 
551     /// Is the referent an inlined function?
is_inlined_function(&self) -> bool552     pub fn is_inlined_function(&self) -> bool {
553         unsafe { clang_Cursor_isFunctionInlined(self.x) != 0 }
554     }
555 
556     /// Is the referent a defaulted function?
is_defaulted_function(&self) -> bool557     pub fn is_defaulted_function(&self) -> bool {
558         unsafe { clang_CXXMethod_isDefaulted(self.x) != 0 }
559     }
560 
561     /// Is the referent a deleted function?
is_deleted_function(&self) -> bool562     pub fn is_deleted_function(&self) -> bool {
563         // Unfortunately, libclang doesn't yet have an API for checking if a
564         // member function is deleted, but the following should be a good
565         // enough approximation.
566         // Deleted functions are implicitly inline according to paragraph 4 of
567         // [dcl.fct.def.delete] in the C++ standard. Normal inline functions
568         // have a definition in the same translation unit, so if this is an
569         // inline function without a definition, and it's not a defaulted
570         // function, we can reasonably safely conclude that it's a deleted
571         // function.
572         self.is_inlined_function() &&
573             self.definition().is_none() &&
574             !self.is_defaulted_function()
575     }
576 
577     /// Is the referent a bit field declaration?
is_bit_field(&self) -> bool578     pub fn is_bit_field(&self) -> bool {
579         unsafe { clang_Cursor_isBitField(self.x) != 0 }
580     }
581 
582     /// Get a cursor to the bit field's width expression, or `None` if it's not
583     /// a bit field.
bit_width_expr(&self) -> Option<Cursor>584     pub fn bit_width_expr(&self) -> Option<Cursor> {
585         if !self.is_bit_field() {
586             return None;
587         }
588 
589         let mut result = None;
590         self.visit(|cur| {
591             // The first child may or may not be a TypeRef, depending on whether
592             // the field's type is builtin. Skip it.
593             if cur.kind() == CXCursor_TypeRef {
594                 return CXChildVisit_Continue;
595             }
596 
597             // The next expression or literal is the bit width.
598             result = Some(cur);
599 
600             CXChildVisit_Break
601         });
602 
603         result
604     }
605 
606     /// Get the width of this cursor's referent bit field, or `None` if the
607     /// referent is not a bit field or if the width could not be evaluated.
bit_width(&self) -> Option<u32>608     pub fn bit_width(&self) -> Option<u32> {
609         // It is not safe to check the bit width without ensuring it doesn't
610         // depend on a template parameter. See
611         // https://github.com/rust-lang/rust-bindgen/issues/2239
612         if self.bit_width_expr()?.is_dependent_on_template_parameter() {
613             return None;
614         }
615 
616         unsafe {
617             let w = clang_getFieldDeclBitWidth(self.x);
618             if w == -1 {
619                 None
620             } else {
621                 Some(w as u32)
622             }
623         }
624     }
625 
626     /// Get the integer representation type used to hold this cursor's referent
627     /// enum type.
enum_type(&self) -> Option<Type>628     pub fn enum_type(&self) -> Option<Type> {
629         unsafe {
630             let t = Type {
631                 x: clang_getEnumDeclIntegerType(self.x),
632             };
633             if t.is_valid() {
634                 Some(t)
635             } else {
636                 None
637             }
638         }
639     }
640 
641     /// Get the boolean constant value for this cursor's enum variant referent.
642     ///
643     /// Returns None if the cursor's referent is not an enum variant.
enum_val_boolean(&self) -> Option<bool>644     pub fn enum_val_boolean(&self) -> Option<bool> {
645         unsafe {
646             if self.kind() == CXCursor_EnumConstantDecl {
647                 Some(clang_getEnumConstantDeclValue(self.x) != 0)
648             } else {
649                 None
650             }
651         }
652     }
653 
654     /// Get the signed constant value for this cursor's enum variant referent.
655     ///
656     /// Returns None if the cursor's referent is not an enum variant.
enum_val_signed(&self) -> Option<i64>657     pub fn enum_val_signed(&self) -> Option<i64> {
658         unsafe {
659             if self.kind() == CXCursor_EnumConstantDecl {
660                 #[allow(clippy::unnecessary_cast)]
661                 Some(clang_getEnumConstantDeclValue(self.x) as i64)
662             } else {
663                 None
664             }
665         }
666     }
667 
668     /// Get the unsigned constant value for this cursor's enum variant referent.
669     ///
670     /// Returns None if the cursor's referent is not an enum variant.
enum_val_unsigned(&self) -> Option<u64>671     pub fn enum_val_unsigned(&self) -> Option<u64> {
672         unsafe {
673             if self.kind() == CXCursor_EnumConstantDecl {
674                 #[allow(clippy::unnecessary_cast)]
675                 Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64)
676             } else {
677                 None
678             }
679         }
680     }
681 
682     /// Does this cursor have the given attributes?
has_attrs<const N: usize>( &self, attrs: &[Attribute; N], ) -> [bool; N]683     pub fn has_attrs<const N: usize>(
684         &self,
685         attrs: &[Attribute; N],
686     ) -> [bool; N] {
687         let mut found_attrs = [false; N];
688         let mut found_count = 0;
689 
690         self.visit(|cur| {
691             let kind = cur.kind();
692             for (idx, attr) in attrs.iter().enumerate() {
693                 let found_attr = &mut found_attrs[idx];
694                 if !*found_attr {
695                     // `attr.name` and` attr.token_kind` are checked against unexposed attributes only.
696                     if attr.kind.map_or(false, |k| k == kind) ||
697                         (kind == CXCursor_UnexposedAttr &&
698                             cur.tokens().iter().any(|t| {
699                                 t.kind == attr.token_kind &&
700                                     t.spelling() == attr.name
701                             }))
702                     {
703                         *found_attr = true;
704                         found_count += 1;
705 
706                         if found_count == N {
707                             return CXChildVisit_Break;
708                         }
709                     }
710                 }
711             }
712 
713             CXChildVisit_Continue
714         });
715 
716         found_attrs
717     }
718 
719     /// Given that this cursor's referent is a `typedef`, get the `Type` that is
720     /// being aliased.
typedef_type(&self) -> Option<Type>721     pub fn typedef_type(&self) -> Option<Type> {
722         let inner = Type {
723             x: unsafe { clang_getTypedefDeclUnderlyingType(self.x) },
724         };
725 
726         if inner.is_valid() {
727             Some(inner)
728         } else {
729             None
730         }
731     }
732 
733     /// Get the linkage kind for this cursor's referent.
734     ///
735     /// This only applies to functions and variables.
linkage(&self) -> CXLinkageKind736     pub fn linkage(&self) -> CXLinkageKind {
737         unsafe { clang_getCursorLinkage(self.x) }
738     }
739 
740     /// Get the visibility of this cursor's referent.
visibility(&self) -> CXVisibilityKind741     pub fn visibility(&self) -> CXVisibilityKind {
742         unsafe { clang_getCursorVisibility(self.x) }
743     }
744 
745     /// Given that this cursor's referent is a function, return cursors to its
746     /// parameters.
747     ///
748     /// Returns None if the cursor's referent is not a function/method call or
749     /// declaration.
args(&self) -> Option<Vec<Cursor>>750     pub fn args(&self) -> Option<Vec<Cursor>> {
751         // match self.kind() {
752         // CXCursor_FunctionDecl |
753         // CXCursor_CXXMethod => {
754         self.num_args().ok().map(|num| {
755             (0..num)
756                 .map(|i| Cursor {
757                     x: unsafe { clang_Cursor_getArgument(self.x, i as c_uint) },
758                 })
759                 .collect()
760         })
761     }
762 
763     /// Given that this cursor's referent is a function/method call or
764     /// declaration, return the number of arguments it takes.
765     ///
766     /// Returns Err if the cursor's referent is not a function/method call or
767     /// declaration.
num_args(&self) -> Result<u32, ()>768     pub fn num_args(&self) -> Result<u32, ()> {
769         unsafe {
770             let w = clang_Cursor_getNumArguments(self.x);
771             if w == -1 {
772                 Err(())
773             } else {
774                 Ok(w as u32)
775             }
776         }
777     }
778 
779     /// Get the access specifier for this cursor's referent.
access_specifier(&self) -> CX_CXXAccessSpecifier780     pub fn access_specifier(&self) -> CX_CXXAccessSpecifier {
781         unsafe { clang_getCXXAccessSpecifier(self.x) }
782     }
783 
784     /// Is the cursor's referrent publically accessible in C++?
785     ///
786     /// Returns true if self.access_specifier() is `CX_CXXPublic` or
787     /// `CX_CXXInvalidAccessSpecifier`.
public_accessible(&self) -> bool788     pub fn public_accessible(&self) -> bool {
789         let access = self.access_specifier();
790         access == CX_CXXPublic || access == CX_CXXInvalidAccessSpecifier
791     }
792 
793     /// Is this cursor's referent a field declaration that is marked as
794     /// `mutable`?
is_mutable_field(&self) -> bool795     pub fn is_mutable_field(&self) -> bool {
796         unsafe { clang_CXXField_isMutable(self.x) != 0 }
797     }
798 
799     /// Get the offset of the field represented by the Cursor.
offset_of_field(&self) -> Result<usize, LayoutError>800     pub fn offset_of_field(&self) -> Result<usize, LayoutError> {
801         let offset = unsafe { clang_Cursor_getOffsetOfField(self.x) };
802 
803         if offset < 0 {
804             Err(LayoutError::from(offset as i32))
805         } else {
806             Ok(offset as usize)
807         }
808     }
809 
810     /// Is this cursor's referent a member function that is declared `static`?
method_is_static(&self) -> bool811     pub fn method_is_static(&self) -> bool {
812         unsafe { clang_CXXMethod_isStatic(self.x) != 0 }
813     }
814 
815     /// Is this cursor's referent a member function that is declared `const`?
method_is_const(&self) -> bool816     pub fn method_is_const(&self) -> bool {
817         unsafe { clang_CXXMethod_isConst(self.x) != 0 }
818     }
819 
820     /// Is this cursor's referent a member function that is virtual?
method_is_virtual(&self) -> bool821     pub fn method_is_virtual(&self) -> bool {
822         unsafe { clang_CXXMethod_isVirtual(self.x) != 0 }
823     }
824 
825     /// Is this cursor's referent a member function that is pure virtual?
method_is_pure_virtual(&self) -> bool826     pub fn method_is_pure_virtual(&self) -> bool {
827         unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 }
828     }
829 
830     /// Is this cursor's referent a struct or class with virtual members?
is_virtual_base(&self) -> bool831     pub fn is_virtual_base(&self) -> bool {
832         unsafe { clang_isVirtualBase(self.x) != 0 }
833     }
834 
835     /// Try to evaluate this cursor.
evaluate(&self) -> Option<EvalResult>836     pub fn evaluate(&self) -> Option<EvalResult> {
837         EvalResult::new(*self)
838     }
839 
840     /// Return the result type for this cursor
ret_type(&self) -> Option<Type>841     pub fn ret_type(&self) -> Option<Type> {
842         let rt = Type {
843             x: unsafe { clang_getCursorResultType(self.x) },
844         };
845         if rt.is_valid() {
846             Some(rt)
847         } else {
848             None
849         }
850     }
851 
852     /// Gets the tokens that correspond to that cursor.
tokens(&self) -> RawTokens853     pub fn tokens(&self) -> RawTokens {
854         RawTokens::new(self)
855     }
856 
857     /// Gets the tokens that correspond to that cursor as  `cexpr` tokens.
cexpr_tokens(self) -> Vec<cexpr::token::Token>858     pub fn cexpr_tokens(self) -> Vec<cexpr::token::Token> {
859         self.tokens()
860             .iter()
861             .filter_map(|token| token.as_cexpr_token())
862             .collect()
863     }
864 
865     /// Obtain the real path name of a cursor of InclusionDirective kind.
866     ///
867     /// Returns None if the cursor does not include a file, otherwise the file's full name
get_included_file_name(&self) -> Option<String>868     pub fn get_included_file_name(&self) -> Option<String> {
869         let file = unsafe { clang_sys::clang_getIncludedFile(self.x) };
870         if file.is_null() {
871             None
872         } else {
873             Some(unsafe {
874                 cxstring_into_string(clang_sys::clang_getFileName(file))
875             })
876         }
877     }
878 }
879 
880 /// A struct that owns the tokenizer result from a given cursor.
881 pub struct RawTokens<'a> {
882     cursor: &'a Cursor,
883     tu: CXTranslationUnit,
884     tokens: *mut CXToken,
885     token_count: c_uint,
886 }
887 
888 impl<'a> RawTokens<'a> {
new(cursor: &'a Cursor) -> Self889     fn new(cursor: &'a Cursor) -> Self {
890         let mut tokens = ptr::null_mut();
891         let mut token_count = 0;
892         let range = cursor.extent();
893         let tu = unsafe { clang_Cursor_getTranslationUnit(cursor.x) };
894         unsafe { clang_tokenize(tu, range, &mut tokens, &mut token_count) };
895         Self {
896             cursor,
897             tu,
898             tokens,
899             token_count,
900         }
901     }
902 
as_slice(&self) -> &[CXToken]903     fn as_slice(&self) -> &[CXToken] {
904         if self.tokens.is_null() {
905             return &[];
906         }
907         unsafe { slice::from_raw_parts(self.tokens, self.token_count as usize) }
908     }
909 
910     /// Get an iterator over these tokens.
iter(&self) -> ClangTokenIterator911     pub fn iter(&self) -> ClangTokenIterator {
912         ClangTokenIterator {
913             tu: self.tu,
914             raw: self.as_slice().iter(),
915         }
916     }
917 }
918 
919 impl<'a> Drop for RawTokens<'a> {
drop(&mut self)920     fn drop(&mut self) {
921         if !self.tokens.is_null() {
922             unsafe {
923                 clang_disposeTokens(
924                     self.tu,
925                     self.tokens,
926                     self.token_count as c_uint,
927                 );
928             }
929         }
930     }
931 }
932 
933 /// A raw clang token, that exposes only kind, spelling, and extent. This is a
934 /// slightly more convenient version of `CXToken` which owns the spelling
935 /// string and extent.
936 #[derive(Debug)]
937 pub struct ClangToken {
938     spelling: CXString,
939     /// The extent of the token. This is the same as the relevant member from
940     /// `CXToken`.
941     pub extent: CXSourceRange,
942     /// The kind of the token. This is the same as the relevant member from
943     /// `CXToken`.
944     pub kind: CXTokenKind,
945 }
946 
947 impl ClangToken {
948     /// Get the token spelling, without being converted to utf-8.
spelling(&self) -> &[u8]949     pub fn spelling(&self) -> &[u8] {
950         let c_str = unsafe {
951             CStr::from_ptr(clang_getCString(self.spelling) as *const _)
952         };
953         c_str.to_bytes()
954     }
955 
956     /// Converts a ClangToken to a `cexpr` token if possible.
as_cexpr_token(&self) -> Option<cexpr::token::Token>957     pub fn as_cexpr_token(&self) -> Option<cexpr::token::Token> {
958         use cexpr::token;
959 
960         let kind = match self.kind {
961             CXToken_Punctuation => token::Kind::Punctuation,
962             CXToken_Literal => token::Kind::Literal,
963             CXToken_Identifier => token::Kind::Identifier,
964             CXToken_Keyword => token::Kind::Keyword,
965             // NB: cexpr is not too happy about comments inside
966             // expressions, so we strip them down here.
967             CXToken_Comment => return None,
968             _ => {
969                 warn!("Found unexpected token kind: {:?}", self);
970                 return None;
971             }
972         };
973 
974         Some(token::Token {
975             kind,
976             raw: self.spelling().to_vec().into_boxed_slice(),
977         })
978     }
979 }
980 
981 impl Drop for ClangToken {
drop(&mut self)982     fn drop(&mut self) {
983         unsafe { clang_disposeString(self.spelling) }
984     }
985 }
986 
987 /// An iterator over a set of Tokens.
988 pub struct ClangTokenIterator<'a> {
989     tu: CXTranslationUnit,
990     raw: slice::Iter<'a, CXToken>,
991 }
992 
993 impl<'a> Iterator for ClangTokenIterator<'a> {
994     type Item = ClangToken;
995 
next(&mut self) -> Option<Self::Item>996     fn next(&mut self) -> Option<Self::Item> {
997         let raw = self.raw.next()?;
998         unsafe {
999             let kind = clang_getTokenKind(*raw);
1000             let spelling = clang_getTokenSpelling(self.tu, *raw);
1001             let extent = clang_getTokenExtent(self.tu, *raw);
1002             Some(ClangToken {
1003                 kind,
1004                 extent,
1005                 spelling,
1006             })
1007         }
1008     }
1009 }
1010 
1011 /// Checks whether the name looks like an identifier, i.e. is alphanumeric
1012 /// (including '_') and does not start with a digit.
is_valid_identifier(name: &str) -> bool1013 pub fn is_valid_identifier(name: &str) -> bool {
1014     let mut chars = name.chars();
1015     let first_valid = chars
1016         .next()
1017         .map(|c| c.is_alphabetic() || c == '_')
1018         .unwrap_or(false);
1019 
1020     first_valid && chars.all(|c| c.is_alphanumeric() || c == '_')
1021 }
1022 
visit_children<Visitor>( cur: CXCursor, _parent: CXCursor, data: CXClientData, ) -> CXChildVisitResult where Visitor: FnMut(Cursor) -> CXChildVisitResult,1023 extern "C" fn visit_children<Visitor>(
1024     cur: CXCursor,
1025     _parent: CXCursor,
1026     data: CXClientData,
1027 ) -> CXChildVisitResult
1028 where
1029     Visitor: FnMut(Cursor) -> CXChildVisitResult,
1030 {
1031     let func: &mut Visitor = unsafe { &mut *(data as *mut Visitor) };
1032     let child = Cursor { x: cur };
1033 
1034     (*func)(child)
1035 }
1036 
1037 impl PartialEq for Cursor {
eq(&self, other: &Cursor) -> bool1038     fn eq(&self, other: &Cursor) -> bool {
1039         unsafe { clang_equalCursors(self.x, other.x) == 1 }
1040     }
1041 }
1042 
1043 impl Eq for Cursor {}
1044 
1045 impl Hash for Cursor {
hash<H: Hasher>(&self, state: &mut H)1046     fn hash<H: Hasher>(&self, state: &mut H) {
1047         unsafe { clang_hashCursor(self.x) }.hash(state)
1048     }
1049 }
1050 
1051 /// The type of a node in clang's AST.
1052 #[derive(Clone, Copy)]
1053 pub struct Type {
1054     x: CXType,
1055 }
1056 
1057 impl PartialEq for Type {
eq(&self, other: &Self) -> bool1058     fn eq(&self, other: &Self) -> bool {
1059         unsafe { clang_equalTypes(self.x, other.x) != 0 }
1060     }
1061 }
1062 
1063 impl Eq for Type {}
1064 
1065 impl fmt::Debug for Type {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1066     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1067         write!(
1068             fmt,
1069             "Type({}, kind: {}, cconv: {}, decl: {:?}, canon: {:?})",
1070             self.spelling(),
1071             type_to_str(self.kind()),
1072             self.call_conv(),
1073             self.declaration(),
1074             self.declaration().canonical()
1075         )
1076     }
1077 }
1078 
1079 /// An error about the layout of a struct, class, or type.
1080 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1081 pub enum LayoutError {
1082     /// Asked for the layout of an invalid type.
1083     Invalid,
1084     /// Asked for the layout of an incomplete type.
1085     Incomplete,
1086     /// Asked for the layout of a dependent type.
1087     Dependent,
1088     /// Asked for the layout of a type that does not have constant size.
1089     NotConstantSize,
1090     /// Asked for the layout of a field in a type that does not have such a
1091     /// field.
1092     InvalidFieldName,
1093     /// An unknown layout error.
1094     Unknown,
1095 }
1096 
1097 impl ::std::convert::From<i32> for LayoutError {
from(val: i32) -> Self1098     fn from(val: i32) -> Self {
1099         use self::LayoutError::*;
1100 
1101         match val {
1102             CXTypeLayoutError_Invalid => Invalid,
1103             CXTypeLayoutError_Incomplete => Incomplete,
1104             CXTypeLayoutError_Dependent => Dependent,
1105             CXTypeLayoutError_NotConstantSize => NotConstantSize,
1106             CXTypeLayoutError_InvalidFieldName => InvalidFieldName,
1107             _ => Unknown,
1108         }
1109     }
1110 }
1111 
1112 impl Type {
1113     /// Get this type's kind.
kind(&self) -> CXTypeKind1114     pub fn kind(&self) -> CXTypeKind {
1115         self.x.kind
1116     }
1117 
1118     /// Get a cursor pointing to this type's declaration.
declaration(&self) -> Cursor1119     pub fn declaration(&self) -> Cursor {
1120         unsafe {
1121             Cursor {
1122                 x: clang_getTypeDeclaration(self.x),
1123             }
1124         }
1125     }
1126 
1127     /// Get the canonical declaration of this type, if it is available.
canonical_declaration( &self, location: Option<&Cursor>, ) -> Option<CanonicalTypeDeclaration>1128     pub fn canonical_declaration(
1129         &self,
1130         location: Option<&Cursor>,
1131     ) -> Option<CanonicalTypeDeclaration> {
1132         let mut declaration = self.declaration();
1133         if !declaration.is_valid() {
1134             if let Some(location) = location {
1135                 let mut location = *location;
1136                 if let Some(referenced) = location.referenced() {
1137                     location = referenced;
1138                 }
1139                 if location.is_template_like() {
1140                     declaration = location;
1141                 }
1142             }
1143         }
1144 
1145         let canonical = declaration.canonical();
1146         if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound {
1147             Some(CanonicalTypeDeclaration(*self, canonical))
1148         } else {
1149             None
1150         }
1151     }
1152 
1153     /// Get a raw display name for this type.
spelling(&self) -> String1154     pub fn spelling(&self) -> String {
1155         let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) };
1156         // Clang 5.0 introduced changes in the spelling API so it returned the
1157         // full qualified name. Let's undo that here.
1158         if s.split("::").all(is_valid_identifier) {
1159             if let Some(s) = s.split("::").last() {
1160                 return s.to_owned();
1161             }
1162         }
1163 
1164         s
1165     }
1166 
1167     /// Is this type const qualified?
is_const(&self) -> bool1168     pub fn is_const(&self) -> bool {
1169         unsafe { clang_isConstQualifiedType(self.x) != 0 }
1170     }
1171 
1172     #[inline]
is_non_deductible_auto_type(&self) -> bool1173     fn is_non_deductible_auto_type(&self) -> bool {
1174         debug_assert_eq!(self.kind(), CXType_Auto);
1175         self.canonical_type() == *self
1176     }
1177 
1178     #[inline]
clang_size_of(&self, ctx: &BindgenContext) -> c_longlong1179     fn clang_size_of(&self, ctx: &BindgenContext) -> c_longlong {
1180         match self.kind() {
1181             // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
1182             CXType_RValueReference | CXType_LValueReference => {
1183                 ctx.target_pointer_size() as c_longlong
1184             }
1185             // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
1186             CXType_Auto if self.is_non_deductible_auto_type() => -6,
1187             _ => unsafe { clang_Type_getSizeOf(self.x) },
1188         }
1189     }
1190 
1191     #[inline]
clang_align_of(&self, ctx: &BindgenContext) -> c_longlong1192     fn clang_align_of(&self, ctx: &BindgenContext) -> c_longlong {
1193         match self.kind() {
1194             // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
1195             CXType_RValueReference | CXType_LValueReference => {
1196                 ctx.target_pointer_size() as c_longlong
1197             }
1198             // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
1199             CXType_Auto if self.is_non_deductible_auto_type() => -6,
1200             _ => unsafe { clang_Type_getAlignOf(self.x) },
1201         }
1202     }
1203 
1204     /// What is the size of this type? Paper over invalid types by returning `0`
1205     /// for them.
size(&self, ctx: &BindgenContext) -> usize1206     pub fn size(&self, ctx: &BindgenContext) -> usize {
1207         let val = self.clang_size_of(ctx);
1208         if val < 0 {
1209             0
1210         } else {
1211             val as usize
1212         }
1213     }
1214 
1215     /// What is the size of this type?
fallible_size( &self, ctx: &BindgenContext, ) -> Result<usize, LayoutError>1216     pub fn fallible_size(
1217         &self,
1218         ctx: &BindgenContext,
1219     ) -> Result<usize, LayoutError> {
1220         let val = self.clang_size_of(ctx);
1221         if val < 0 {
1222             Err(LayoutError::from(val as i32))
1223         } else {
1224             Ok(val as usize)
1225         }
1226     }
1227 
1228     /// What is the alignment of this type? Paper over invalid types by
1229     /// returning `0`.
align(&self, ctx: &BindgenContext) -> usize1230     pub fn align(&self, ctx: &BindgenContext) -> usize {
1231         let val = self.clang_align_of(ctx);
1232         if val < 0 {
1233             0
1234         } else {
1235             val as usize
1236         }
1237     }
1238 
1239     /// What is the alignment of this type?
fallible_align( &self, ctx: &BindgenContext, ) -> Result<usize, LayoutError>1240     pub fn fallible_align(
1241         &self,
1242         ctx: &BindgenContext,
1243     ) -> Result<usize, LayoutError> {
1244         let val = self.clang_align_of(ctx);
1245         if val < 0 {
1246             Err(LayoutError::from(val as i32))
1247         } else {
1248             Ok(val as usize)
1249         }
1250     }
1251 
1252     /// Get the layout for this type, or an error describing why it does not
1253     /// have a valid layout.
fallible_layout( &self, ctx: &BindgenContext, ) -> Result<crate::ir::layout::Layout, LayoutError>1254     pub fn fallible_layout(
1255         &self,
1256         ctx: &BindgenContext,
1257     ) -> Result<crate::ir::layout::Layout, LayoutError> {
1258         use crate::ir::layout::Layout;
1259         let size = self.fallible_size(ctx)?;
1260         let align = self.fallible_align(ctx)?;
1261         Ok(Layout::new(size, align))
1262     }
1263 
1264     /// Get the number of template arguments this type has, or `None` if it is
1265     /// not some kind of template.
num_template_args(&self) -> Option<u32>1266     pub fn num_template_args(&self) -> Option<u32> {
1267         let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
1268         if n >= 0 {
1269             Some(n as u32)
1270         } else {
1271             debug_assert_eq!(n, -1);
1272             None
1273         }
1274     }
1275 
1276     /// If this type is a class template specialization, return its
1277     /// template arguments. Otherwise, return None.
template_args(&self) -> Option<TypeTemplateArgIterator>1278     pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
1279         self.num_template_args().map(|n| TypeTemplateArgIterator {
1280             x: self.x,
1281             length: n,
1282             index: 0,
1283         })
1284     }
1285 
1286     /// Given that this type is a function prototype, return the types of its parameters.
1287     ///
1288     /// Returns None if the type is not a function prototype.
args(&self) -> Option<Vec<Type>>1289     pub fn args(&self) -> Option<Vec<Type>> {
1290         self.num_args().ok().map(|num| {
1291             (0..num)
1292                 .map(|i| Type {
1293                     x: unsafe { clang_getArgType(self.x, i as c_uint) },
1294                 })
1295                 .collect()
1296         })
1297     }
1298 
1299     /// Given that this type is a function prototype, return the number of arguments it takes.
1300     ///
1301     /// Returns Err if the type is not a function prototype.
num_args(&self) -> Result<u32, ()>1302     pub fn num_args(&self) -> Result<u32, ()> {
1303         unsafe {
1304             let w = clang_getNumArgTypes(self.x);
1305             if w == -1 {
1306                 Err(())
1307             } else {
1308                 Ok(w as u32)
1309             }
1310         }
1311     }
1312 
1313     /// Given that this type is a pointer type, return the type that it points
1314     /// to.
pointee_type(&self) -> Option<Type>1315     pub fn pointee_type(&self) -> Option<Type> {
1316         match self.kind() {
1317             CXType_Pointer |
1318             CXType_RValueReference |
1319             CXType_LValueReference |
1320             CXType_MemberPointer |
1321             CXType_BlockPointer |
1322             CXType_ObjCObjectPointer => {
1323                 let ret = Type {
1324                     x: unsafe { clang_getPointeeType(self.x) },
1325                 };
1326                 debug_assert!(ret.is_valid());
1327                 Some(ret)
1328             }
1329             _ => None,
1330         }
1331     }
1332 
1333     /// Given that this type is an array, vector, or complex type, return the
1334     /// type of its elements.
elem_type(&self) -> Option<Type>1335     pub fn elem_type(&self) -> Option<Type> {
1336         let current_type = Type {
1337             x: unsafe { clang_getElementType(self.x) },
1338         };
1339         if current_type.is_valid() {
1340             Some(current_type)
1341         } else {
1342             None
1343         }
1344     }
1345 
1346     /// Given that this type is an array or vector type, return its number of
1347     /// elements.
num_elements(&self) -> Option<usize>1348     pub fn num_elements(&self) -> Option<usize> {
1349         let num_elements_returned = unsafe { clang_getNumElements(self.x) };
1350         if num_elements_returned != -1 {
1351             Some(num_elements_returned as usize)
1352         } else {
1353             None
1354         }
1355     }
1356 
1357     /// Get the canonical version of this type. This sees through `typedef`s and
1358     /// aliases to get the underlying, canonical type.
canonical_type(&self) -> Type1359     pub fn canonical_type(&self) -> Type {
1360         unsafe {
1361             Type {
1362                 x: clang_getCanonicalType(self.x),
1363             }
1364         }
1365     }
1366 
1367     /// Is this type a variadic function type?
is_variadic(&self) -> bool1368     pub fn is_variadic(&self) -> bool {
1369         unsafe { clang_isFunctionTypeVariadic(self.x) != 0 }
1370     }
1371 
1372     /// Given that this type is a function type, get the type of its return
1373     /// value.
ret_type(&self) -> Option<Type>1374     pub fn ret_type(&self) -> Option<Type> {
1375         let rt = Type {
1376             x: unsafe { clang_getResultType(self.x) },
1377         };
1378         if rt.is_valid() {
1379             Some(rt)
1380         } else {
1381             None
1382         }
1383     }
1384 
1385     /// Given that this type is a function type, get its calling convention. If
1386     /// this is not a function type, `CXCallingConv_Invalid` is returned.
call_conv(&self) -> CXCallingConv1387     pub fn call_conv(&self) -> CXCallingConv {
1388         unsafe { clang_getFunctionTypeCallingConv(self.x) }
1389     }
1390 
1391     /// For elaborated types (types which use `class`, `struct`, or `union` to
1392     /// disambiguate types from local bindings), get the underlying type.
named(&self) -> Type1393     pub fn named(&self) -> Type {
1394         unsafe {
1395             Type {
1396                 x: clang_Type_getNamedType(self.x),
1397             }
1398         }
1399     }
1400 
1401     /// Is this a valid type?
is_valid(&self) -> bool1402     pub fn is_valid(&self) -> bool {
1403         self.kind() != CXType_Invalid
1404     }
1405 
1406     /// Is this a valid and exposed type?
is_valid_and_exposed(&self) -> bool1407     pub fn is_valid_and_exposed(&self) -> bool {
1408         self.is_valid() && self.kind() != CXType_Unexposed
1409     }
1410 
1411     /// Is this type a fully instantiated template?
is_fully_instantiated_template(&self) -> bool1412     pub fn is_fully_instantiated_template(&self) -> bool {
1413         // Yep, the spelling of this containing type-parameter is extremely
1414         // nasty... But can happen in <type_traits>. Unfortunately I couldn't
1415         // reduce it enough :(
1416         self.template_args().map_or(false, |args| args.len() > 0) &&
1417             !matches!(
1418                 self.declaration().kind(),
1419                 CXCursor_ClassTemplatePartialSpecialization |
1420                     CXCursor_TypeAliasTemplateDecl |
1421                     CXCursor_TemplateTemplateParameter
1422             )
1423     }
1424 
1425     /// Is this type an associated template type? Eg `T::Associated` in
1426     /// this example:
1427     ///
1428     /// ```c++
1429     /// template <typename T>
1430     /// class Foo {
1431     ///     typename T::Associated member;
1432     /// };
1433     /// ```
is_associated_type(&self) -> bool1434     pub fn is_associated_type(&self) -> bool {
1435         // This is terrible :(
1436         fn hacky_parse_associated_type<S: AsRef<str>>(spelling: S) -> bool {
1437             lazy_static! {
1438                 static ref ASSOC_TYPE_RE: regex::Regex = regex::Regex::new(
1439                     r"typename type\-parameter\-\d+\-\d+::.+"
1440                 )
1441                 .unwrap();
1442             }
1443             ASSOC_TYPE_RE.is_match(spelling.as_ref())
1444         }
1445 
1446         self.kind() == CXType_Unexposed &&
1447             (hacky_parse_associated_type(self.spelling()) ||
1448                 hacky_parse_associated_type(
1449                     self.canonical_type().spelling(),
1450                 ))
1451     }
1452 }
1453 
1454 /// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
1455 /// cursor is the canonical declaration for its type. If you have a
1456 /// `CanonicalTypeDeclaration` instance, you know for sure that the type and
1457 /// cursor match up in a canonical declaration relationship, and it simply
1458 /// cannot be otherwise.
1459 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1460 pub struct CanonicalTypeDeclaration(Type, Cursor);
1461 
1462 impl CanonicalTypeDeclaration {
1463     /// Get the type.
ty(&self) -> &Type1464     pub fn ty(&self) -> &Type {
1465         &self.0
1466     }
1467 
1468     /// Get the type's canonical declaration cursor.
cursor(&self) -> &Cursor1469     pub fn cursor(&self) -> &Cursor {
1470         &self.1
1471     }
1472 }
1473 
1474 /// An iterator for a type's template arguments.
1475 pub struct TypeTemplateArgIterator {
1476     x: CXType,
1477     length: u32,
1478     index: u32,
1479 }
1480 
1481 impl Iterator for TypeTemplateArgIterator {
1482     type Item = Type;
next(&mut self) -> Option<Type>1483     fn next(&mut self) -> Option<Type> {
1484         if self.index < self.length {
1485             let idx = self.index as c_uint;
1486             self.index += 1;
1487             Some(Type {
1488                 x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) },
1489             })
1490         } else {
1491             None
1492         }
1493     }
1494 }
1495 
1496 impl ExactSizeIterator for TypeTemplateArgIterator {
len(&self) -> usize1497     fn len(&self) -> usize {
1498         assert!(self.index <= self.length);
1499         (self.length - self.index) as usize
1500     }
1501 }
1502 
1503 /// A `SourceLocation` is a file, line, column, and byte offset location for
1504 /// some source text.
1505 pub struct SourceLocation {
1506     x: CXSourceLocation,
1507 }
1508 
1509 impl SourceLocation {
1510     /// Get the (file, line, column, byte offset) tuple for this source
1511     /// location.
location(&self) -> (File, usize, usize, usize)1512     pub fn location(&self) -> (File, usize, usize, usize) {
1513         unsafe {
1514             let mut file = mem::zeroed();
1515             let mut line = 0;
1516             let mut col = 0;
1517             let mut off = 0;
1518             clang_getSpellingLocation(
1519                 self.x, &mut file, &mut line, &mut col, &mut off,
1520             );
1521             (File { x: file }, line as usize, col as usize, off as usize)
1522         }
1523     }
1524 }
1525 
1526 impl fmt::Display for SourceLocation {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1527     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1528         let (file, line, col, _) = self.location();
1529         if let Some(name) = file.name() {
1530             write!(f, "{}:{}:{}", name, line, col)
1531         } else {
1532             "builtin definitions".fmt(f)
1533         }
1534     }
1535 }
1536 
1537 impl fmt::Debug for SourceLocation {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1538     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1539         write!(f, "{}", self)
1540     }
1541 }
1542 
1543 /// A comment in the source text.
1544 ///
1545 /// Comments are sort of parsed by Clang, and have a tree structure.
1546 pub struct Comment {
1547     x: CXComment,
1548 }
1549 
1550 impl Comment {
1551     /// What kind of comment is this?
kind(&self) -> CXCommentKind1552     pub fn kind(&self) -> CXCommentKind {
1553         unsafe { clang_Comment_getKind(self.x) }
1554     }
1555 
1556     /// Get this comment's children comment
get_children(&self) -> CommentChildrenIterator1557     pub fn get_children(&self) -> CommentChildrenIterator {
1558         CommentChildrenIterator {
1559             parent: self.x,
1560             length: unsafe { clang_Comment_getNumChildren(self.x) },
1561             index: 0,
1562         }
1563     }
1564 
1565     /// Given that this comment is the start or end of an HTML tag, get its tag
1566     /// name.
get_tag_name(&self) -> String1567     pub fn get_tag_name(&self) -> String {
1568         unsafe { cxstring_into_string(clang_HTMLTagComment_getTagName(self.x)) }
1569     }
1570 
1571     /// Given that this comment is an HTML start tag, get its attributes.
get_tag_attrs(&self) -> CommentAttributesIterator1572     pub fn get_tag_attrs(&self) -> CommentAttributesIterator {
1573         CommentAttributesIterator {
1574             x: self.x,
1575             length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) },
1576             index: 0,
1577         }
1578     }
1579 }
1580 
1581 /// An iterator for a comment's children
1582 pub struct CommentChildrenIterator {
1583     parent: CXComment,
1584     length: c_uint,
1585     index: c_uint,
1586 }
1587 
1588 impl Iterator for CommentChildrenIterator {
1589     type Item = Comment;
next(&mut self) -> Option<Comment>1590     fn next(&mut self) -> Option<Comment> {
1591         if self.index < self.length {
1592             let idx = self.index;
1593             self.index += 1;
1594             Some(Comment {
1595                 x: unsafe { clang_Comment_getChild(self.parent, idx) },
1596             })
1597         } else {
1598             None
1599         }
1600     }
1601 }
1602 
1603 /// An HTML start tag comment attribute
1604 pub struct CommentAttribute {
1605     /// HTML start tag attribute name
1606     pub name: String,
1607     /// HTML start tag attribute value
1608     pub value: String,
1609 }
1610 
1611 /// An iterator for a comment's attributes
1612 pub struct CommentAttributesIterator {
1613     x: CXComment,
1614     length: c_uint,
1615     index: c_uint,
1616 }
1617 
1618 impl Iterator for CommentAttributesIterator {
1619     type Item = CommentAttribute;
next(&mut self) -> Option<CommentAttribute>1620     fn next(&mut self) -> Option<CommentAttribute> {
1621         if self.index < self.length {
1622             let idx = self.index;
1623             self.index += 1;
1624             Some(CommentAttribute {
1625                 name: unsafe {
1626                     cxstring_into_string(clang_HTMLStartTag_getAttrName(
1627                         self.x, idx,
1628                     ))
1629                 },
1630                 value: unsafe {
1631                     cxstring_into_string(clang_HTMLStartTag_getAttrValue(
1632                         self.x, idx,
1633                     ))
1634                 },
1635             })
1636         } else {
1637             None
1638         }
1639     }
1640 }
1641 
1642 /// A source file.
1643 pub struct File {
1644     x: CXFile,
1645 }
1646 
1647 impl File {
1648     /// Get the name of this source file.
name(&self) -> Option<String>1649     pub fn name(&self) -> Option<String> {
1650         if self.x.is_null() {
1651             return None;
1652         }
1653         Some(unsafe { cxstring_into_string(clang_getFileName(self.x)) })
1654     }
1655 }
1656 
cxstring_to_string_leaky(s: CXString) -> String1657 fn cxstring_to_string_leaky(s: CXString) -> String {
1658     if s.data.is_null() {
1659         return "".to_owned();
1660     }
1661     let c_str = unsafe { CStr::from_ptr(clang_getCString(s) as *const _) };
1662     c_str.to_string_lossy().into_owned()
1663 }
1664 
cxstring_into_string(s: CXString) -> String1665 fn cxstring_into_string(s: CXString) -> String {
1666     let ret = cxstring_to_string_leaky(s);
1667     unsafe { clang_disposeString(s) };
1668     ret
1669 }
1670 
1671 /// An `Index` is an environment for a set of translation units that will
1672 /// typically end up linked together in one final binary.
1673 pub struct Index {
1674     x: CXIndex,
1675 }
1676 
1677 impl Index {
1678     /// Construct a new `Index`.
1679     ///
1680     /// The `pch` parameter controls whether declarations in pre-compiled
1681     /// headers are included when enumerating a translation unit's "locals".
1682     ///
1683     /// The `diag` parameter controls whether debugging diagnostics are enabled.
new(pch: bool, diag: bool) -> Index1684     pub fn new(pch: bool, diag: bool) -> Index {
1685         unsafe {
1686             Index {
1687                 x: clang_createIndex(pch as c_int, diag as c_int),
1688             }
1689         }
1690     }
1691 }
1692 
1693 impl fmt::Debug for Index {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1694     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1695         write!(fmt, "Index {{ }}")
1696     }
1697 }
1698 
1699 impl Drop for Index {
drop(&mut self)1700     fn drop(&mut self) {
1701         unsafe {
1702             clang_disposeIndex(self.x);
1703         }
1704     }
1705 }
1706 
1707 /// A translation unit (or "compilation unit").
1708 pub struct TranslationUnit {
1709     x: CXTranslationUnit,
1710 }
1711 
1712 impl fmt::Debug for TranslationUnit {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1713     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1714         write!(fmt, "TranslationUnit {{ }}")
1715     }
1716 }
1717 
1718 impl TranslationUnit {
1719     /// Parse a source file into a translation unit.
parse( ix: &Index, file: &str, cmd_args: &[String], unsaved: &[UnsavedFile], opts: CXTranslationUnit_Flags, ) -> Option<TranslationUnit>1720     pub fn parse(
1721         ix: &Index,
1722         file: &str,
1723         cmd_args: &[String],
1724         unsaved: &[UnsavedFile],
1725         opts: CXTranslationUnit_Flags,
1726     ) -> Option<TranslationUnit> {
1727         let fname = CString::new(file).unwrap();
1728         let _c_args: Vec<CString> = cmd_args
1729             .iter()
1730             .map(|s| CString::new(s.clone()).unwrap())
1731             .collect();
1732         let c_args: Vec<*const c_char> =
1733             _c_args.iter().map(|s| s.as_ptr()).collect();
1734         let mut c_unsaved: Vec<CXUnsavedFile> =
1735             unsaved.iter().map(|f| f.x).collect();
1736         let tu = unsafe {
1737             clang_parseTranslationUnit(
1738                 ix.x,
1739                 fname.as_ptr(),
1740                 c_args.as_ptr(),
1741                 c_args.len() as c_int,
1742                 c_unsaved.as_mut_ptr(),
1743                 c_unsaved.len() as c_uint,
1744                 opts,
1745             )
1746         };
1747         if tu.is_null() {
1748             None
1749         } else {
1750             Some(TranslationUnit { x: tu })
1751         }
1752     }
1753 
1754     /// Get the Clang diagnostic information associated with this translation
1755     /// unit.
diags(&self) -> Vec<Diagnostic>1756     pub fn diags(&self) -> Vec<Diagnostic> {
1757         unsafe {
1758             let num = clang_getNumDiagnostics(self.x) as usize;
1759             let mut diags = vec![];
1760             for i in 0..num {
1761                 diags.push(Diagnostic {
1762                     x: clang_getDiagnostic(self.x, i as c_uint),
1763                 });
1764             }
1765             diags
1766         }
1767     }
1768 
1769     /// Get a cursor pointing to the root of this translation unit's AST.
cursor(&self) -> Cursor1770     pub fn cursor(&self) -> Cursor {
1771         unsafe {
1772             Cursor {
1773                 x: clang_getTranslationUnitCursor(self.x),
1774             }
1775         }
1776     }
1777 
1778     /// Is this the null translation unit?
is_null(&self) -> bool1779     pub fn is_null(&self) -> bool {
1780         self.x.is_null()
1781     }
1782 }
1783 
1784 impl Drop for TranslationUnit {
drop(&mut self)1785     fn drop(&mut self) {
1786         unsafe {
1787             clang_disposeTranslationUnit(self.x);
1788         }
1789     }
1790 }
1791 
1792 /// A diagnostic message generated while parsing a translation unit.
1793 pub struct Diagnostic {
1794     x: CXDiagnostic,
1795 }
1796 
1797 impl Diagnostic {
1798     /// Format this diagnostic message as a string, using the given option bit
1799     /// flags.
format(&self) -> String1800     pub fn format(&self) -> String {
1801         unsafe {
1802             let opts = clang_defaultDiagnosticDisplayOptions();
1803             cxstring_into_string(clang_formatDiagnostic(self.x, opts))
1804         }
1805     }
1806 
1807     /// What is the severity of this diagnostic message?
severity(&self) -> CXDiagnosticSeverity1808     pub fn severity(&self) -> CXDiagnosticSeverity {
1809         unsafe { clang_getDiagnosticSeverity(self.x) }
1810     }
1811 }
1812 
1813 impl Drop for Diagnostic {
1814     /// Destroy this diagnostic message.
drop(&mut self)1815     fn drop(&mut self) {
1816         unsafe {
1817             clang_disposeDiagnostic(self.x);
1818         }
1819     }
1820 }
1821 
1822 /// A file which has not been saved to disk.
1823 pub struct UnsavedFile {
1824     x: CXUnsavedFile,
1825     /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
1826     /// `CXUnsavedFile`.
1827     pub name: CString,
1828     contents: CString,
1829 }
1830 
1831 impl UnsavedFile {
1832     /// Construct a new unsaved file with the given `name` and `contents`.
new(name: String, contents: String) -> UnsavedFile1833     pub fn new(name: String, contents: String) -> UnsavedFile {
1834         let name = CString::new(name).unwrap();
1835         let contents = CString::new(contents).unwrap();
1836         let x = CXUnsavedFile {
1837             Filename: name.as_ptr(),
1838             Contents: contents.as_ptr(),
1839             Length: contents.as_bytes().len() as c_ulong,
1840         };
1841         UnsavedFile { x, name, contents }
1842     }
1843 }
1844 
1845 impl fmt::Debug for UnsavedFile {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1846     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1847         write!(
1848             fmt,
1849             "UnsavedFile(name: {:?}, contents: {:?})",
1850             self.name, self.contents
1851         )
1852     }
1853 }
1854 
1855 /// Convert a cursor kind into a static string.
kind_to_str(x: CXCursorKind) -> String1856 pub fn kind_to_str(x: CXCursorKind) -> String {
1857     unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
1858 }
1859 
1860 /// Convert a type kind to a static string.
type_to_str(x: CXTypeKind) -> String1861 pub fn type_to_str(x: CXTypeKind) -> String {
1862     unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) }
1863 }
1864 
1865 /// Dump the Clang AST to stdout for debugging purposes.
ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult1866 pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
1867     fn print_indent<S: AsRef<str>>(depth: isize, s: S) {
1868         for _ in 0..depth {
1869             print!("    ");
1870         }
1871         println!("{}", s.as_ref());
1872     }
1873 
1874     fn print_cursor<S: AsRef<str>>(depth: isize, prefix: S, c: &Cursor) {
1875         let prefix = prefix.as_ref();
1876         print_indent(
1877             depth,
1878             format!(" {}kind = {}", prefix, kind_to_str(c.kind())),
1879         );
1880         print_indent(
1881             depth,
1882             format!(" {}spelling = \"{}\"", prefix, c.spelling()),
1883         );
1884         print_indent(depth, format!(" {}location = {}", prefix, c.location()));
1885         print_indent(
1886             depth,
1887             format!(" {}is-definition? {}", prefix, c.is_definition()),
1888         );
1889         print_indent(
1890             depth,
1891             format!(" {}is-declaration? {}", prefix, c.is_declaration()),
1892         );
1893         print_indent(
1894             depth,
1895             format!(
1896                 " {}is-inlined-function? {}",
1897                 prefix,
1898                 c.is_inlined_function()
1899             ),
1900         );
1901 
1902         let templ_kind = c.template_kind();
1903         if templ_kind != CXCursor_NoDeclFound {
1904             print_indent(
1905                 depth,
1906                 format!(
1907                     " {}template-kind = {}",
1908                     prefix,
1909                     kind_to_str(templ_kind)
1910                 ),
1911             );
1912         }
1913         if let Some(usr) = c.usr() {
1914             print_indent(depth, format!(" {}usr = \"{}\"", prefix, usr));
1915         }
1916         if let Ok(num) = c.num_args() {
1917             print_indent(depth, format!(" {}number-of-args = {}", prefix, num));
1918         }
1919         if let Some(num) = c.num_template_args() {
1920             print_indent(
1921                 depth,
1922                 format!(" {}number-of-template-args = {}", prefix, num),
1923             );
1924         }
1925 
1926         if c.is_bit_field() {
1927             let width = match c.bit_width() {
1928                 Some(w) => w.to_string(),
1929                 None => "<unevaluable>".to_string(),
1930             };
1931             print_indent(depth, format!(" {}bit-width = {}", prefix, width));
1932         }
1933 
1934         if let Some(ty) = c.enum_type() {
1935             print_indent(
1936                 depth,
1937                 format!(" {}enum-type = {}", prefix, type_to_str(ty.kind())),
1938             );
1939         }
1940         if let Some(val) = c.enum_val_signed() {
1941             print_indent(depth, format!(" {}enum-val = {}", prefix, val));
1942         }
1943         if let Some(ty) = c.typedef_type() {
1944             print_indent(
1945                 depth,
1946                 format!(" {}typedef-type = {}", prefix, type_to_str(ty.kind())),
1947             );
1948         }
1949         if let Some(ty) = c.ret_type() {
1950             print_indent(
1951                 depth,
1952                 format!(" {}ret-type = {}", prefix, type_to_str(ty.kind())),
1953             );
1954         }
1955 
1956         if let Some(refd) = c.referenced() {
1957             if refd != *c {
1958                 println!();
1959                 print_cursor(
1960                     depth,
1961                     String::from(prefix) + "referenced.",
1962                     &refd,
1963                 );
1964             }
1965         }
1966 
1967         let canonical = c.canonical();
1968         if canonical != *c {
1969             println!();
1970             print_cursor(
1971                 depth,
1972                 String::from(prefix) + "canonical.",
1973                 &canonical,
1974             );
1975         }
1976 
1977         if let Some(specialized) = c.specialized() {
1978             if specialized != *c {
1979                 println!();
1980                 print_cursor(
1981                     depth,
1982                     String::from(prefix) + "specialized.",
1983                     &specialized,
1984                 );
1985             }
1986         }
1987 
1988         if let Some(parent) = c.fallible_semantic_parent() {
1989             println!();
1990             print_cursor(
1991                 depth,
1992                 String::from(prefix) + "semantic-parent.",
1993                 &parent,
1994             );
1995         }
1996     }
1997 
1998     fn print_type<S: AsRef<str>>(depth: isize, prefix: S, ty: &Type) {
1999         let prefix = prefix.as_ref();
2000 
2001         let kind = ty.kind();
2002         print_indent(depth, format!(" {}kind = {}", prefix, type_to_str(kind)));
2003         if kind == CXType_Invalid {
2004             return;
2005         }
2006 
2007         print_indent(depth, format!(" {}cconv = {}", prefix, ty.call_conv()));
2008 
2009         print_indent(
2010             depth,
2011             format!(" {}spelling = \"{}\"", prefix, ty.spelling()),
2012         );
2013         let num_template_args =
2014             unsafe { clang_Type_getNumTemplateArguments(ty.x) };
2015         if num_template_args >= 0 {
2016             print_indent(
2017                 depth,
2018                 format!(
2019                     " {}number-of-template-args = {}",
2020                     prefix, num_template_args
2021                 ),
2022             );
2023         }
2024         if let Some(num) = ty.num_elements() {
2025             print_indent(
2026                 depth,
2027                 format!(" {}number-of-elements = {}", prefix, num),
2028             );
2029         }
2030         print_indent(
2031             depth,
2032             format!(" {}is-variadic? {}", prefix, ty.is_variadic()),
2033         );
2034 
2035         let canonical = ty.canonical_type();
2036         if canonical != *ty {
2037             println!();
2038             print_type(depth, String::from(prefix) + "canonical.", &canonical);
2039         }
2040 
2041         if let Some(pointee) = ty.pointee_type() {
2042             if pointee != *ty {
2043                 println!();
2044                 print_type(depth, String::from(prefix) + "pointee.", &pointee);
2045             }
2046         }
2047 
2048         if let Some(elem) = ty.elem_type() {
2049             if elem != *ty {
2050                 println!();
2051                 print_type(depth, String::from(prefix) + "elements.", &elem);
2052             }
2053         }
2054 
2055         if let Some(ret) = ty.ret_type() {
2056             if ret != *ty {
2057                 println!();
2058                 print_type(depth, String::from(prefix) + "return.", &ret);
2059             }
2060         }
2061 
2062         let named = ty.named();
2063         if named != *ty && named.is_valid() {
2064             println!();
2065             print_type(depth, String::from(prefix) + "named.", &named);
2066         }
2067     }
2068 
2069     print_indent(depth, "(");
2070     print_cursor(depth, "", c);
2071 
2072     println!();
2073     let ty = c.cur_type();
2074     print_type(depth, "type.", &ty);
2075 
2076     let declaration = ty.declaration();
2077     if declaration != *c && declaration.kind() != CXCursor_NoDeclFound {
2078         println!();
2079         print_cursor(depth, "type.declaration.", &declaration);
2080     }
2081 
2082     // Recurse.
2083     let mut found_children = false;
2084     c.visit(|s| {
2085         if !found_children {
2086             println!();
2087             found_children = true;
2088         }
2089         ast_dump(&s, depth + 1)
2090     });
2091 
2092     print_indent(depth, ")");
2093 
2094     CXChildVisit_Continue
2095 }
2096 
2097 /// Try to extract the clang version to a string
extract_clang_version() -> String2098 pub fn extract_clang_version() -> String {
2099     unsafe { cxstring_into_string(clang_getClangVersion()) }
2100 }
2101 
2102 /// A wrapper for the result of evaluating an expression.
2103 #[derive(Debug)]
2104 pub struct EvalResult {
2105     x: CXEvalResult,
2106 }
2107 
2108 impl EvalResult {
2109     /// Evaluate `cursor` and return the result.
new(cursor: Cursor) -> Option<Self>2110     pub fn new(cursor: Cursor) -> Option<Self> {
2111         // Work around https://bugs.llvm.org/show_bug.cgi?id=42532, see:
2112         //  * https://github.com/rust-lang/rust-bindgen/issues/283
2113         //  * https://github.com/rust-lang/rust-bindgen/issues/1590
2114         {
2115             let mut found_cant_eval = false;
2116             cursor.visit(|c| {
2117                 if c.kind() == CXCursor_TypeRef &&
2118                     c.cur_type().canonical_type().kind() == CXType_Unexposed
2119                 {
2120                     found_cant_eval = true;
2121                     return CXChildVisit_Break;
2122                 }
2123 
2124                 CXChildVisit_Recurse
2125             });
2126 
2127             if found_cant_eval {
2128                 return None;
2129             }
2130         }
2131         Some(EvalResult {
2132             x: unsafe { clang_Cursor_Evaluate(cursor.x) },
2133         })
2134     }
2135 
kind(&self) -> CXEvalResultKind2136     fn kind(&self) -> CXEvalResultKind {
2137         unsafe { clang_EvalResult_getKind(self.x) }
2138     }
2139 
2140     /// Try to get back the result as a double.
as_double(&self) -> Option<f64>2141     pub fn as_double(&self) -> Option<f64> {
2142         match self.kind() {
2143             CXEval_Float => {
2144                 Some(unsafe { clang_EvalResult_getAsDouble(self.x) })
2145             }
2146             _ => None,
2147         }
2148     }
2149 
2150     /// Try to get back the result as an integer.
as_int(&self) -> Option<i64>2151     pub fn as_int(&self) -> Option<i64> {
2152         if self.kind() != CXEval_Int {
2153             return None;
2154         }
2155 
2156         if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
2157             let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
2158             if value > i64::max_value() as c_ulonglong {
2159                 return None;
2160             }
2161 
2162             return Some(value as i64);
2163         }
2164 
2165         let value = unsafe { clang_EvalResult_getAsLongLong(self.x) };
2166         if value > i64::max_value() as c_longlong {
2167             return None;
2168         }
2169         if value < i64::min_value() as c_longlong {
2170             return None;
2171         }
2172         #[allow(clippy::unnecessary_cast)]
2173         Some(value as i64)
2174     }
2175 
2176     /// Evaluates the expression as a literal string, that may or may not be
2177     /// valid utf-8.
as_literal_string(&self) -> Option<Vec<u8>>2178     pub fn as_literal_string(&self) -> Option<Vec<u8>> {
2179         match self.kind() {
2180             CXEval_StrLiteral => {
2181                 let ret = unsafe {
2182                     CStr::from_ptr(clang_EvalResult_getAsStr(self.x))
2183                 };
2184                 Some(ret.to_bytes().to_vec())
2185             }
2186             _ => None,
2187         }
2188     }
2189 }
2190 
2191 impl Drop for EvalResult {
drop(&mut self)2192     fn drop(&mut self) {
2193         unsafe { clang_EvalResult_dispose(self.x) };
2194     }
2195 }
2196 
2197 /// Target information obtained from libclang.
2198 #[derive(Debug)]
2199 pub struct TargetInfo {
2200     /// The target triple.
2201     pub triple: String,
2202     /// The width of the pointer _in bits_.
2203     pub pointer_width: usize,
2204 }
2205 
2206 impl TargetInfo {
2207     /// Tries to obtain target information from libclang.
new(tu: &TranslationUnit) -> Self2208     pub fn new(tu: &TranslationUnit) -> Self {
2209         let triple;
2210         let pointer_width;
2211         unsafe {
2212             let ti = clang_getTranslationUnitTargetInfo(tu.x);
2213             triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
2214             pointer_width = clang_TargetInfo_getPointerWidth(ti);
2215             clang_TargetInfo_dispose(ti);
2216         }
2217         assert!(pointer_width > 0);
2218         assert_eq!(pointer_width % 8, 0);
2219         TargetInfo {
2220             triple,
2221             pointer_width: pointer_width as usize,
2222         }
2223     }
2224 }
2225