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