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