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