bindgen/
clang.rs

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
7use crate::ir::context::BindgenContext;
8use clang_sys::*;
9use std::cmp;
10
11use std::ffi::{CStr, CString};
12use std::fmt;
13use std::fs::OpenOptions;
14use std::hash::Hash;
15use std::hash::Hasher;
16use std::os::raw::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong};
17use std::sync::OnceLock;
18use 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.
24pub(crate) struct Attribute {
25    name: &'static [u8],
26    kind: Option<CXCursorKind>,
27    token_kind: CXTokenKind,
28}
29
30impl 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)]
58pub(crate) struct Cursor {
59    x: CXCursor,
60}
61
62impl fmt::Debug for Cursor {
63    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
75impl 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.
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?
90    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?
95    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.
100    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.
108    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.
113    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.
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.
139    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    /// ```
161    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.
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.
189    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.
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                    None
221                } else {
222                    canonical.num_template_args()
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.
233    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?
246    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.
267    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?
277    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.
282    pub(crate) fn kind(&self) -> CXCursorKind {
283        self.x.kind
284    }
285
286    /// Returns true if the cursor is a definition
287    pub(crate) fn is_definition(&self) -> bool {
288        unsafe { clang_isCursorDefinition(self.x) != 0 }
289    }
290
291    /// Is the referent a template specialization?
292    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?
298    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?
306    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?
324    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?
334    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?
374    pub(crate) fn is_valid(&self) -> bool {
375        unsafe { clang_isInvalid(self.kind()) == 0 }
376    }
377
378    /// Get the source location for the referent.
379    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.
388    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.
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.
405    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.
414    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.
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.
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.
460    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.
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.
486    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.
493    pub(crate) fn visit<Visitor>(&self, mut visitor: Visitor)
494    where
495        Visitor: FnMut(Cursor) -> CXChildVisitResult,
496    {
497        let data = ptr::addr_of_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.
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.
550    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.
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?
604    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?
614    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).
631    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?
647    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?
652    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?
657    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?
673    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.
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.
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.
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.
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.
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.
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?
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 == Some(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.
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.
831    pub(crate) fn linkage(&self) -> CXLinkageKind {
832        unsafe { clang_getCursorLinkage(self.x) }
833    }
834
835    /// Get the visibility of this cursor's referent.
836    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.
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.
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.
875    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`.
883    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`?
890    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.
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`?
906    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`?
911    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?
916    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?
921    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?
926    pub(crate) fn is_virtual_base(&self) -> bool {
927        unsafe { clang_isVirtualBase(self.x) != 0 }
928    }
929
930    /// Try to evaluate this cursor.
931    pub(crate) fn evaluate(&self) -> Option<EvalResult> {
932        EvalResult::new(*self)
933    }
934
935    /// Return the result type for this cursor
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.
948    pub(crate) fn tokens(&self) -> RawTokens<'_> {
949        RawTokens::new(self)
950    }
951
952    /// Gets the tokens that correspond to that cursor as  `cexpr` tokens.
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
963    pub(crate) fn get_included_file_name(&self) -> Option<String> {
964        let file = unsafe { clang_getIncludedFile(self.x) };
965        if file.is_null() {
966            None
967        } else {
968            Some(unsafe { cxstring_into_string(clang_getFileName(file)) })
969        }
970    }
971
972    /// Is this cursor's referent a namespace that is inline?
973    pub(crate) fn is_inline_namespace(&self) -> bool {
974        unsafe { clang_Cursor_isInlineNamespace(self.x) != 0 }
975    }
976}
977
978/// A struct that owns the tokenizer result from a given cursor.
979pub(crate) struct RawTokens<'a> {
980    cursor: &'a Cursor,
981    tu: CXTranslationUnit,
982    tokens: *mut CXToken,
983    token_count: c_uint,
984}
985
986impl<'a> RawTokens<'a> {
987    fn new(cursor: &'a Cursor) -> Self {
988        let mut tokens = ptr::null_mut();
989        let mut token_count = 0;
990        let range = cursor.extent();
991        let tu = unsafe { clang_Cursor_getTranslationUnit(cursor.x) };
992        unsafe { clang_tokenize(tu, range, &mut tokens, &mut token_count) };
993        Self {
994            cursor,
995            tu,
996            tokens,
997            token_count,
998        }
999    }
1000
1001    fn as_slice(&self) -> &[CXToken] {
1002        if self.tokens.is_null() {
1003            return &[];
1004        }
1005        unsafe { slice::from_raw_parts(self.tokens, self.token_count as usize) }
1006    }
1007
1008    /// Get an iterator over these tokens.
1009    pub(crate) fn iter(&self) -> ClangTokenIterator<'_> {
1010        ClangTokenIterator {
1011            tu: self.tu,
1012            raw: self.as_slice().iter(),
1013        }
1014    }
1015}
1016
1017impl Drop for RawTokens<'_> {
1018    fn drop(&mut self) {
1019        if !self.tokens.is_null() {
1020            unsafe {
1021                clang_disposeTokens(
1022                    self.tu,
1023                    self.tokens,
1024                    self.token_count as c_uint,
1025                );
1026            }
1027        }
1028    }
1029}
1030
1031/// A raw clang token, that exposes only kind, spelling, and extent. This is a
1032/// slightly more convenient version of `CXToken` which owns the spelling
1033/// string and extent.
1034#[derive(Debug)]
1035pub(crate) struct ClangToken {
1036    spelling: CXString,
1037    /// The extent of the token. This is the same as the relevant member from
1038    /// `CXToken`.
1039    pub(crate) extent: CXSourceRange,
1040    /// The kind of the token. This is the same as the relevant member from
1041    /// `CXToken`.
1042    pub(crate) kind: CXTokenKind,
1043}
1044
1045impl ClangToken {
1046    /// Get the token spelling, without being converted to utf-8.
1047    pub(crate) fn spelling(&self) -> &[u8] {
1048        let c_str = unsafe { CStr::from_ptr(clang_getCString(self.spelling)) };
1049        c_str.to_bytes()
1050    }
1051
1052    /// Converts a `ClangToken` to a `cexpr` token if possible.
1053    pub(crate) fn as_cexpr_token(&self) -> Option<cexpr::token::Token> {
1054        use cexpr::token;
1055
1056        let kind = match self.kind {
1057            CXToken_Punctuation => token::Kind::Punctuation,
1058            CXToken_Literal => token::Kind::Literal,
1059            CXToken_Identifier => token::Kind::Identifier,
1060            CXToken_Keyword => token::Kind::Keyword,
1061            // NB: cexpr is not too happy about comments inside
1062            // expressions, so we strip them down here.
1063            CXToken_Comment => return None,
1064            _ => {
1065                warn!("Found unexpected token kind: {self:?}");
1066                return None;
1067            }
1068        };
1069
1070        Some(token::Token {
1071            kind,
1072            raw: self.spelling().to_vec().into_boxed_slice(),
1073        })
1074    }
1075}
1076
1077impl Drop for ClangToken {
1078    fn drop(&mut self) {
1079        unsafe { clang_disposeString(self.spelling) }
1080    }
1081}
1082
1083/// An iterator over a set of Tokens.
1084pub(crate) struct ClangTokenIterator<'a> {
1085    tu: CXTranslationUnit,
1086    raw: slice::Iter<'a, CXToken>,
1087}
1088
1089impl Iterator for ClangTokenIterator<'_> {
1090    type Item = ClangToken;
1091
1092    fn next(&mut self) -> Option<Self::Item> {
1093        let raw = self.raw.next()?;
1094        unsafe {
1095            let kind = clang_getTokenKind(*raw);
1096            let spelling = clang_getTokenSpelling(self.tu, *raw);
1097            let extent = clang_getTokenExtent(self.tu, *raw);
1098            Some(ClangToken {
1099                spelling,
1100                extent,
1101                kind,
1102            })
1103        }
1104    }
1105}
1106
1107/// Checks whether the name looks like an identifier, i.e. is alphanumeric
1108/// (including '_') and does not start with a digit.
1109pub(crate) fn is_valid_identifier(name: &str) -> bool {
1110    let mut chars = name.chars();
1111    let first_valid =
1112        chars.next().is_some_and(|c| c.is_alphabetic() || c == '_');
1113
1114    first_valid && chars.all(|c| c.is_alphanumeric() || c == '_')
1115}
1116
1117extern "C" fn visit_children<Visitor>(
1118    cur: CXCursor,
1119    _parent: CXCursor,
1120    data: CXClientData,
1121) -> CXChildVisitResult
1122where
1123    Visitor: FnMut(Cursor) -> CXChildVisitResult,
1124{
1125    let func: &mut Visitor = unsafe { &mut *data.cast::<Visitor>() };
1126    let child = Cursor { x: cur };
1127
1128    (*func)(child)
1129}
1130
1131impl PartialEq for Cursor {
1132    fn eq(&self, other: &Cursor) -> bool {
1133        unsafe { clang_equalCursors(self.x, other.x) == 1 }
1134    }
1135}
1136
1137impl Eq for Cursor {}
1138
1139impl Hash for Cursor {
1140    fn hash<H: Hasher>(&self, state: &mut H) {
1141        unsafe { clang_hashCursor(self.x) }.hash(state);
1142    }
1143}
1144
1145/// The type of a node in clang's AST.
1146#[derive(Clone, Copy)]
1147pub(crate) struct Type {
1148    x: CXType,
1149}
1150
1151impl PartialEq for Type {
1152    fn eq(&self, other: &Self) -> bool {
1153        unsafe { clang_equalTypes(self.x, other.x) != 0 }
1154    }
1155}
1156
1157impl Eq for Type {}
1158
1159impl fmt::Debug for Type {
1160    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1161        write!(
1162            fmt,
1163            "Type({}, kind: {}, cconv: {}, decl: {:?}, canon: {:?})",
1164            self.spelling(),
1165            type_to_str(self.kind()),
1166            self.call_conv(),
1167            self.declaration(),
1168            self.declaration().canonical()
1169        )
1170    }
1171}
1172
1173/// An error about the layout of a struct, class, or type.
1174#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1175pub(crate) enum LayoutError {
1176    /// Asked for the layout of an invalid type.
1177    Invalid,
1178    /// Asked for the layout of an incomplete type.
1179    Incomplete,
1180    /// Asked for the layout of a dependent type.
1181    Dependent,
1182    /// Asked for the layout of a type that does not have constant size.
1183    NotConstantSize,
1184    /// Asked for the layout of a field in a type that does not have such a
1185    /// field.
1186    InvalidFieldName,
1187    /// An unknown layout error.
1188    Unknown,
1189}
1190
1191impl ::std::convert::From<i32> for LayoutError {
1192    fn from(val: i32) -> Self {
1193        use self::LayoutError::*;
1194
1195        match val {
1196            CXTypeLayoutError_Invalid => Invalid,
1197            CXTypeLayoutError_Incomplete => Incomplete,
1198            CXTypeLayoutError_Dependent => Dependent,
1199            CXTypeLayoutError_NotConstantSize => NotConstantSize,
1200            CXTypeLayoutError_InvalidFieldName => InvalidFieldName,
1201            _ => Unknown,
1202        }
1203    }
1204}
1205
1206impl Type {
1207    /// Get this type's kind.
1208    pub(crate) fn kind(&self) -> CXTypeKind {
1209        self.x.kind
1210    }
1211
1212    /// Get a cursor pointing to this type's declaration.
1213    pub(crate) fn declaration(&self) -> Cursor {
1214        unsafe {
1215            Cursor {
1216                x: clang_getTypeDeclaration(self.x),
1217            }
1218        }
1219    }
1220
1221    /// Get the canonical declaration of this type, if it is available.
1222    pub(crate) fn canonical_declaration(
1223        &self,
1224        location: Option<&Cursor>,
1225    ) -> Option<CanonicalTypeDeclaration> {
1226        let mut declaration = self.declaration();
1227        if !declaration.is_valid() {
1228            if let Some(location) = location {
1229                let mut location = *location;
1230                if let Some(referenced) = location.referenced() {
1231                    location = referenced;
1232                }
1233                if location.is_template_like() {
1234                    declaration = location;
1235                }
1236            }
1237        }
1238
1239        let canonical = declaration.canonical();
1240        if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound {
1241            Some(CanonicalTypeDeclaration(*self, canonical))
1242        } else {
1243            None
1244        }
1245    }
1246
1247    /// Get a raw display name for this type.
1248    pub(crate) fn spelling(&self) -> String {
1249        let s = unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) };
1250        // Clang 5.0 introduced changes in the spelling API so it returned the
1251        // full qualified name. Let's undo that here.
1252        if s.split("::").all(is_valid_identifier) {
1253            if let Some(s) = s.split("::").last() {
1254                return s.to_owned();
1255            }
1256        }
1257
1258        s
1259    }
1260
1261    /// Is this type const qualified?
1262    pub(crate) fn is_const(&self) -> bool {
1263        unsafe { clang_isConstQualifiedType(self.x) != 0 }
1264    }
1265
1266    #[inline]
1267    fn is_non_deductible_auto_type(&self) -> bool {
1268        debug_assert_eq!(self.kind(), CXType_Auto);
1269        self.canonical_type() == *self
1270    }
1271
1272    #[inline]
1273    fn clang_size_of(&self, ctx: &BindgenContext) -> c_longlong {
1274        match self.kind() {
1275            // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
1276            CXType_RValueReference | CXType_LValueReference => {
1277                ctx.target_pointer_size() as c_longlong
1278            }
1279            // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
1280            CXType_Auto if self.is_non_deductible_auto_type() => -6,
1281            _ => unsafe { clang_Type_getSizeOf(self.x) },
1282        }
1283    }
1284
1285    #[inline]
1286    fn clang_align_of(&self, ctx: &BindgenContext) -> c_longlong {
1287        match self.kind() {
1288            // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975
1289            CXType_RValueReference | CXType_LValueReference => {
1290                ctx.target_pointer_size() as c_longlong
1291            }
1292            // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813
1293            CXType_Auto if self.is_non_deductible_auto_type() => -6,
1294            _ => unsafe { clang_Type_getAlignOf(self.x) },
1295        }
1296    }
1297
1298    /// What is the size of this type? Paper over invalid types by returning `0`
1299    /// for them.
1300    pub(crate) fn size(&self, ctx: &BindgenContext) -> usize {
1301        let val = self.clang_size_of(ctx);
1302        if val < 0 {
1303            0
1304        } else {
1305            val as usize
1306        }
1307    }
1308
1309    /// What is the size of this type?
1310    pub(crate) fn fallible_size(
1311        &self,
1312        ctx: &BindgenContext,
1313    ) -> Result<usize, LayoutError> {
1314        let val = self.clang_size_of(ctx);
1315        if val < 0 {
1316            Err(LayoutError::from(val as i32))
1317        } else {
1318            Ok(val as usize)
1319        }
1320    }
1321
1322    /// What is the alignment of this type? Paper over invalid types by
1323    /// returning `0`.
1324    pub(crate) fn align(&self, ctx: &BindgenContext) -> usize {
1325        let val = self.clang_align_of(ctx);
1326        if val < 0 {
1327            0
1328        } else {
1329            val as usize
1330        }
1331    }
1332
1333    /// What is the alignment of this type?
1334    pub(crate) fn fallible_align(
1335        &self,
1336        ctx: &BindgenContext,
1337    ) -> Result<usize, LayoutError> {
1338        let val = self.clang_align_of(ctx);
1339        if val < 0 {
1340            Err(LayoutError::from(val as i32))
1341        } else {
1342            Ok(val as usize)
1343        }
1344    }
1345
1346    /// Get the layout for this type, or an error describing why it does not
1347    /// have a valid layout.
1348    pub(crate) fn fallible_layout(
1349        &self,
1350        ctx: &BindgenContext,
1351    ) -> Result<crate::ir::layout::Layout, LayoutError> {
1352        use crate::ir::layout::Layout;
1353        let size = self.fallible_size(ctx)?;
1354        let align = self.fallible_align(ctx)?;
1355        Ok(Layout::new(size, align))
1356    }
1357
1358    /// Get the number of template arguments this type has, or `None` if it is
1359    /// not some kind of template.
1360    pub(crate) fn num_template_args(&self) -> Option<u32> {
1361        let n = unsafe { clang_Type_getNumTemplateArguments(self.x) };
1362        if n >= 0 {
1363            Some(n as u32)
1364        } else {
1365            debug_assert_eq!(n, -1);
1366            None
1367        }
1368    }
1369
1370    /// If this type is a class template specialization, return its
1371    /// template arguments. Otherwise, return None.
1372    pub(crate) fn template_args(&self) -> Option<TypeTemplateArgIterator> {
1373        self.num_template_args().map(|n| TypeTemplateArgIterator {
1374            x: self.x,
1375            length: n,
1376            index: 0,
1377        })
1378    }
1379
1380    /// Given that this type is a function prototype, return the types of its parameters.
1381    ///
1382    /// Returns None if the type is not a function prototype.
1383    pub(crate) fn args(&self) -> Option<Vec<Type>> {
1384        self.num_args().ok().map(|num| {
1385            (0..num)
1386                .map(|i| Type {
1387                    x: unsafe { clang_getArgType(self.x, i as c_uint) },
1388                })
1389                .collect()
1390        })
1391    }
1392
1393    /// Given that this type is a function prototype, return the number of arguments it takes.
1394    ///
1395    /// Returns Err if the type is not a function prototype.
1396    pub(crate) fn num_args(&self) -> Result<u32, ()> {
1397        unsafe {
1398            let w = clang_getNumArgTypes(self.x);
1399            if w == -1 {
1400                Err(())
1401            } else {
1402                Ok(w as u32)
1403            }
1404        }
1405    }
1406
1407    /// Given that this type is a pointer type, return the type that it points
1408    /// to.
1409    pub(crate) fn pointee_type(&self) -> Option<Type> {
1410        match self.kind() {
1411            CXType_Pointer |
1412            CXType_RValueReference |
1413            CXType_LValueReference |
1414            CXType_MemberPointer |
1415            CXType_BlockPointer |
1416            CXType_ObjCObjectPointer => {
1417                let ret = Type {
1418                    x: unsafe { clang_getPointeeType(self.x) },
1419                };
1420                debug_assert!(ret.is_valid());
1421                Some(ret)
1422            }
1423            _ => None,
1424        }
1425    }
1426
1427    /// Given that this type is an array, vector, or complex type, return the
1428    /// type of its elements.
1429    pub(crate) fn elem_type(&self) -> Option<Type> {
1430        let current_type = Type {
1431            x: unsafe { clang_getElementType(self.x) },
1432        };
1433        if current_type.is_valid() {
1434            Some(current_type)
1435        } else {
1436            None
1437        }
1438    }
1439
1440    /// Given that this type is an array or vector type, return its number of
1441    /// elements.
1442    pub(crate) fn num_elements(&self) -> Option<usize> {
1443        let num_elements_returned = unsafe { clang_getNumElements(self.x) };
1444        if num_elements_returned == -1 {
1445            None
1446        } else {
1447            Some(num_elements_returned as usize)
1448        }
1449    }
1450
1451    /// Get the canonical version of this type. This sees through `typedef`s and
1452    /// aliases to get the underlying, canonical type.
1453    pub(crate) fn canonical_type(&self) -> Type {
1454        unsafe {
1455            Type {
1456                x: clang_getCanonicalType(self.x),
1457            }
1458        }
1459    }
1460
1461    /// Is this type a variadic function type?
1462    pub(crate) fn is_variadic(&self) -> bool {
1463        unsafe { clang_isFunctionTypeVariadic(self.x) != 0 }
1464    }
1465
1466    /// Given that this type is a function type, get the type of its return
1467    /// value.
1468    pub(crate) fn ret_type(&self) -> Option<Type> {
1469        let rt = Type {
1470            x: unsafe { clang_getResultType(self.x) },
1471        };
1472        if rt.is_valid() {
1473            Some(rt)
1474        } else {
1475            None
1476        }
1477    }
1478
1479    /// Given that this type is a function type, get its calling convention. If
1480    /// this is not a function type, `CXCallingConv_Invalid` is returned.
1481    pub(crate) fn call_conv(&self) -> CXCallingConv {
1482        unsafe { clang_getFunctionTypeCallingConv(self.x) }
1483    }
1484
1485    /// For elaborated types (types which use `class`, `struct`, or `union` to
1486    /// disambiguate types from local bindings), get the underlying type.
1487    pub(crate) fn named(&self) -> Type {
1488        unsafe {
1489            Type {
1490                x: clang_Type_getNamedType(self.x),
1491            }
1492        }
1493    }
1494
1495    /// For atomic types, get the underlying type.
1496    pub(crate) fn atomic_value_type(&self) -> Type {
1497        unsafe {
1498            Type {
1499                x: clang_Type_getValueType(self.x),
1500            }
1501        }
1502    }
1503
1504    /// Is this a valid type?
1505    pub(crate) fn is_valid(&self) -> bool {
1506        self.kind() != CXType_Invalid
1507    }
1508
1509    /// Is this a valid and exposed type?
1510    pub(crate) fn is_valid_and_exposed(&self) -> bool {
1511        self.is_valid() && self.kind() != CXType_Unexposed
1512    }
1513
1514    /// Is this type a fully instantiated template?
1515    pub(crate) fn is_fully_instantiated_template(&self) -> bool {
1516        // Yep, the spelling of this containing type-parameter is extremely
1517        // nasty... But can happen in <type_traits>. Unfortunately I couldn't
1518        // reduce it enough :(
1519        self.template_args().is_some_and(|args| args.len() > 0) &&
1520            !matches!(
1521                self.declaration().kind(),
1522                CXCursor_ClassTemplatePartialSpecialization |
1523                    CXCursor_TypeAliasTemplateDecl |
1524                    CXCursor_TemplateTemplateParameter
1525            )
1526    }
1527
1528    /// Is this type an associated template type? Eg `T::Associated` in
1529    /// this example:
1530    ///
1531    /// ```c++
1532    /// template <typename T>
1533    /// class Foo {
1534    ///     typename T::Associated member;
1535    /// };
1536    /// ```
1537    pub(crate) fn is_associated_type(&self) -> bool {
1538        // This is terrible :(
1539        fn hacky_parse_associated_type<S: AsRef<str>>(spelling: S) -> bool {
1540            static ASSOC_TYPE_RE: OnceLock<regex::Regex> = OnceLock::new();
1541            ASSOC_TYPE_RE
1542                .get_or_init(|| {
1543                    regex::Regex::new(r"typename type\-parameter\-\d+\-\d+::.+")
1544                        .unwrap()
1545                })
1546                .is_match(spelling.as_ref())
1547        }
1548
1549        self.kind() == CXType_Unexposed &&
1550            (hacky_parse_associated_type(self.spelling()) ||
1551                hacky_parse_associated_type(
1552                    self.canonical_type().spelling(),
1553                ))
1554    }
1555}
1556
1557/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
1558/// cursor is the canonical declaration for its type. If you have a
1559/// `CanonicalTypeDeclaration` instance, you know for sure that the type and
1560/// cursor match up in a canonical declaration relationship, and it simply
1561/// cannot be otherwise.
1562#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1563pub(crate) struct CanonicalTypeDeclaration(Type, Cursor);
1564
1565impl CanonicalTypeDeclaration {
1566    /// Get the type.
1567    pub(crate) fn ty(&self) -> &Type {
1568        &self.0
1569    }
1570
1571    /// Get the type's canonical declaration cursor.
1572    pub(crate) fn cursor(&self) -> &Cursor {
1573        &self.1
1574    }
1575}
1576
1577/// An iterator for a type's template arguments.
1578pub(crate) struct TypeTemplateArgIterator {
1579    x: CXType,
1580    length: u32,
1581    index: u32,
1582}
1583
1584impl Iterator for TypeTemplateArgIterator {
1585    type Item = Type;
1586    fn next(&mut self) -> Option<Type> {
1587        if self.index < self.length {
1588            let idx = self.index as c_uint;
1589            self.index += 1;
1590            Some(Type {
1591                x: unsafe { clang_Type_getTemplateArgumentAsType(self.x, idx) },
1592            })
1593        } else {
1594            None
1595        }
1596    }
1597}
1598
1599impl ExactSizeIterator for TypeTemplateArgIterator {
1600    fn len(&self) -> usize {
1601        assert!(self.index <= self.length);
1602        (self.length - self.index) as usize
1603    }
1604}
1605
1606/// A `SourceLocation` is a file, line, column, and byte offset location for
1607/// some source text.
1608pub(crate) struct SourceLocation {
1609    x: CXSourceLocation,
1610}
1611
1612impl SourceLocation {
1613    /// Get the (file, line, column, byte offset) tuple for this source
1614    /// location.
1615    pub(crate) fn location(&self) -> (File, usize, usize, usize) {
1616        unsafe {
1617            let mut file = mem::zeroed();
1618            let mut line = 0;
1619            let mut col = 0;
1620            let mut off = 0;
1621            clang_getFileLocation(
1622                self.x, &mut file, &mut line, &mut col, &mut off,
1623            );
1624            (File { x: file }, line as usize, col as usize, off as usize)
1625        }
1626    }
1627}
1628
1629impl fmt::Display for SourceLocation {
1630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1631        let (file, line, col, _) = self.location();
1632        if let Some(name) = file.name() {
1633            write!(f, "{name}:{line}:{col}")
1634        } else {
1635            "builtin definitions".fmt(f)
1636        }
1637    }
1638}
1639
1640impl fmt::Debug for SourceLocation {
1641    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1642        write!(f, "{self}")
1643    }
1644}
1645
1646/// A comment in the source text.
1647///
1648/// Comments are sort of parsed by Clang, and have a tree structure.
1649pub(crate) struct Comment {
1650    x: CXComment,
1651}
1652
1653impl Comment {
1654    /// What kind of comment is this?
1655    pub(crate) fn kind(&self) -> CXCommentKind {
1656        unsafe { clang_Comment_getKind(self.x) }
1657    }
1658
1659    /// Get this comment's children comment
1660    pub(crate) fn get_children(&self) -> CommentChildrenIterator {
1661        CommentChildrenIterator {
1662            parent: self.x,
1663            length: unsafe { clang_Comment_getNumChildren(self.x) },
1664            index: 0,
1665        }
1666    }
1667
1668    /// Given that this comment is the start or end of an HTML tag, get its tag
1669    /// name.
1670    pub(crate) fn get_tag_name(&self) -> String {
1671        unsafe { cxstring_into_string(clang_HTMLTagComment_getTagName(self.x)) }
1672    }
1673
1674    /// Given that this comment is an HTML start tag, get its attributes.
1675    pub(crate) fn get_tag_attrs(&self) -> CommentAttributesIterator {
1676        CommentAttributesIterator {
1677            x: self.x,
1678            length: unsafe { clang_HTMLStartTag_getNumAttrs(self.x) },
1679            index: 0,
1680        }
1681    }
1682}
1683
1684/// An iterator for a comment's children
1685pub(crate) struct CommentChildrenIterator {
1686    parent: CXComment,
1687    length: c_uint,
1688    index: c_uint,
1689}
1690
1691impl Iterator for CommentChildrenIterator {
1692    type Item = Comment;
1693    fn next(&mut self) -> Option<Comment> {
1694        if self.index < self.length {
1695            let idx = self.index;
1696            self.index += 1;
1697            Some(Comment {
1698                x: unsafe { clang_Comment_getChild(self.parent, idx) },
1699            })
1700        } else {
1701            None
1702        }
1703    }
1704}
1705
1706/// An HTML start tag comment attribute
1707pub(crate) struct CommentAttribute {
1708    /// HTML start tag attribute name
1709    pub(crate) name: String,
1710    /// HTML start tag attribute value
1711    pub(crate) value: String,
1712}
1713
1714/// An iterator for a comment's attributes
1715pub(crate) struct CommentAttributesIterator {
1716    x: CXComment,
1717    length: c_uint,
1718    index: c_uint,
1719}
1720
1721impl Iterator for CommentAttributesIterator {
1722    type Item = CommentAttribute;
1723    fn next(&mut self) -> Option<CommentAttribute> {
1724        if self.index < self.length {
1725            let idx = self.index;
1726            self.index += 1;
1727            Some(CommentAttribute {
1728                name: unsafe {
1729                    cxstring_into_string(clang_HTMLStartTag_getAttrName(
1730                        self.x, idx,
1731                    ))
1732                },
1733                value: unsafe {
1734                    cxstring_into_string(clang_HTMLStartTag_getAttrValue(
1735                        self.x, idx,
1736                    ))
1737                },
1738            })
1739        } else {
1740            None
1741        }
1742    }
1743}
1744
1745/// A source file.
1746pub(crate) struct File {
1747    x: CXFile,
1748}
1749
1750impl File {
1751    /// Get the name of this source file.
1752    pub(crate) fn name(&self) -> Option<String> {
1753        if self.x.is_null() {
1754            return None;
1755        }
1756        Some(unsafe { cxstring_into_string(clang_getFileName(self.x)) })
1757    }
1758}
1759
1760fn cxstring_to_string_leaky(s: CXString) -> String {
1761    if s.data.is_null() {
1762        return String::new();
1763    }
1764    let c_str = unsafe { CStr::from_ptr(clang_getCString(s)) };
1765    c_str.to_string_lossy().into_owned()
1766}
1767
1768fn cxstring_into_string(s: CXString) -> String {
1769    let ret = cxstring_to_string_leaky(s);
1770    unsafe { clang_disposeString(s) };
1771    ret
1772}
1773
1774/// An `Index` is an environment for a set of translation units that will
1775/// typically end up linked together in one final binary.
1776pub(crate) struct Index {
1777    x: CXIndex,
1778}
1779
1780impl Index {
1781    /// Construct a new `Index`.
1782    ///
1783    /// The `pch` parameter controls whether declarations in pre-compiled
1784    /// headers are included when enumerating a translation unit's "locals".
1785    ///
1786    /// The `diag` parameter controls whether debugging diagnostics are enabled.
1787    pub(crate) fn new(pch: bool, diag: bool) -> Index {
1788        unsafe {
1789            Index {
1790                x: clang_createIndex(c_int::from(pch), c_int::from(diag)),
1791            }
1792        }
1793    }
1794}
1795
1796impl fmt::Debug for Index {
1797    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1798        write!(fmt, "Index {{ }}")
1799    }
1800}
1801
1802impl Drop for Index {
1803    fn drop(&mut self) {
1804        unsafe {
1805            clang_disposeIndex(self.x);
1806        }
1807    }
1808}
1809
1810/// A translation unit (or "compilation unit").
1811pub(crate) struct TranslationUnit {
1812    x: CXTranslationUnit,
1813}
1814
1815impl fmt::Debug for TranslationUnit {
1816    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1817        write!(fmt, "TranslationUnit {{ }}")
1818    }
1819}
1820
1821impl TranslationUnit {
1822    /// Parse a source file into a translation unit.
1823    pub(crate) fn parse(
1824        ix: &Index,
1825        file: &str,
1826        cmd_args: &[Box<str>],
1827        unsaved: &[UnsavedFile],
1828        opts: CXTranslationUnit_Flags,
1829    ) -> Option<TranslationUnit> {
1830        let fname = CString::new(file).unwrap();
1831        let _c_args: Vec<CString> = cmd_args
1832            .iter()
1833            .map(|s| CString::new(s.as_bytes()).unwrap())
1834            .collect();
1835        let c_args: Vec<*const c_char> =
1836            _c_args.iter().map(|s| s.as_ptr()).collect();
1837        let mut c_unsaved: Vec<CXUnsavedFile> =
1838            unsaved.iter().map(|f| f.x).collect();
1839        let tu = unsafe {
1840            clang_parseTranslationUnit(
1841                ix.x,
1842                fname.as_ptr(),
1843                c_args.as_ptr(),
1844                c_args.len() as c_int,
1845                c_unsaved.as_mut_ptr(),
1846                c_unsaved.len() as c_uint,
1847                opts,
1848            )
1849        };
1850        if tu.is_null() {
1851            None
1852        } else {
1853            Some(TranslationUnit { x: tu })
1854        }
1855    }
1856
1857    /// Get the Clang diagnostic information associated with this translation
1858    /// unit.
1859    pub(crate) fn diags(&self) -> Vec<Diagnostic> {
1860        unsafe {
1861            let num = clang_getNumDiagnostics(self.x) as usize;
1862            let mut diags = vec![];
1863            for i in 0..num {
1864                diags.push(Diagnostic {
1865                    x: clang_getDiagnostic(self.x, i as c_uint),
1866                });
1867            }
1868            diags
1869        }
1870    }
1871
1872    /// Get a cursor pointing to the root of this translation unit's AST.
1873    pub(crate) fn cursor(&self) -> Cursor {
1874        unsafe {
1875            Cursor {
1876                x: clang_getTranslationUnitCursor(self.x),
1877            }
1878        }
1879    }
1880
1881    /// Save a translation unit to the given file.
1882    pub(crate) fn save(&mut self, file: &str) -> Result<(), CXSaveError> {
1883        let Ok(file) = CString::new(file) else {
1884            return Err(CXSaveError_Unknown);
1885        };
1886        let ret = unsafe {
1887            clang_saveTranslationUnit(
1888                self.x,
1889                file.as_ptr(),
1890                clang_defaultSaveOptions(self.x),
1891            )
1892        };
1893        if ret != 0 {
1894            Err(ret)
1895        } else {
1896            Ok(())
1897        }
1898    }
1899
1900    /// Is this the null translation unit?
1901    pub(crate) fn is_null(&self) -> bool {
1902        self.x.is_null()
1903    }
1904}
1905
1906impl Drop for TranslationUnit {
1907    fn drop(&mut self) {
1908        unsafe {
1909            clang_disposeTranslationUnit(self.x);
1910        }
1911    }
1912}
1913
1914/// Translation unit used for macro fallback parsing
1915pub(crate) struct FallbackTranslationUnit {
1916    file_path: String,
1917    pch_path: String,
1918    idx: Box<Index>,
1919    tu: TranslationUnit,
1920}
1921
1922impl fmt::Debug for FallbackTranslationUnit {
1923    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1924        write!(fmt, "FallbackTranslationUnit {{ }}")
1925    }
1926}
1927
1928impl FallbackTranslationUnit {
1929    /// Create a new fallback translation unit
1930    pub(crate) fn new(
1931        file: String,
1932        pch_path: String,
1933        c_args: &[Box<str>],
1934    ) -> Option<Self> {
1935        // Create empty file
1936        OpenOptions::new()
1937            .write(true)
1938            .create(true)
1939            .truncate(true)
1940            .open(&file)
1941            .ok()?;
1942
1943        let f_index = Box::new(Index::new(true, false));
1944        let f_translation_unit = TranslationUnit::parse(
1945            &f_index,
1946            &file,
1947            c_args,
1948            &[],
1949            CXTranslationUnit_None,
1950        )?;
1951        Some(FallbackTranslationUnit {
1952            file_path: file,
1953            pch_path,
1954            tu: f_translation_unit,
1955            idx: f_index,
1956        })
1957    }
1958
1959    /// Get reference to underlying translation unit.
1960    pub(crate) fn translation_unit(&self) -> &TranslationUnit {
1961        &self.tu
1962    }
1963
1964    /// Reparse a translation unit.
1965    pub(crate) fn reparse(
1966        &mut self,
1967        unsaved_contents: &str,
1968    ) -> Result<(), CXErrorCode> {
1969        let unsaved = &[UnsavedFile::new(&self.file_path, unsaved_contents)];
1970        let mut c_unsaved: Vec<CXUnsavedFile> =
1971            unsaved.iter().map(|f| f.x).collect();
1972        let ret = unsafe {
1973            clang_reparseTranslationUnit(
1974                self.tu.x,
1975                unsaved.len() as c_uint,
1976                c_unsaved.as_mut_ptr(),
1977                clang_defaultReparseOptions(self.tu.x),
1978            )
1979        };
1980        if ret != 0 {
1981            Err(ret)
1982        } else {
1983            Ok(())
1984        }
1985    }
1986}
1987
1988impl Drop for FallbackTranslationUnit {
1989    fn drop(&mut self) {
1990        let _ = std::fs::remove_file(&self.file_path);
1991        let _ = std::fs::remove_file(&self.pch_path);
1992    }
1993}
1994
1995/// A diagnostic message generated while parsing a translation unit.
1996pub(crate) struct Diagnostic {
1997    x: CXDiagnostic,
1998}
1999
2000impl Diagnostic {
2001    /// Format this diagnostic message as a string, using the given option bit
2002    /// flags.
2003    pub(crate) fn format(&self) -> String {
2004        unsafe {
2005            let opts = clang_defaultDiagnosticDisplayOptions();
2006            cxstring_into_string(clang_formatDiagnostic(self.x, opts))
2007        }
2008    }
2009
2010    /// What is the severity of this diagnostic message?
2011    pub(crate) fn severity(&self) -> CXDiagnosticSeverity {
2012        unsafe { clang_getDiagnosticSeverity(self.x) }
2013    }
2014}
2015
2016impl Drop for Diagnostic {
2017    /// Destroy this diagnostic message.
2018    fn drop(&mut self) {
2019        unsafe {
2020            clang_disposeDiagnostic(self.x);
2021        }
2022    }
2023}
2024
2025/// A file which has not been saved to disk.
2026pub(crate) struct UnsavedFile {
2027    x: CXUnsavedFile,
2028    /// The name of the unsaved file. Kept here to avoid leaving dangling pointers in
2029    /// `CXUnsavedFile`.
2030    pub(crate) name: CString,
2031    contents: CString,
2032}
2033
2034impl UnsavedFile {
2035    /// Construct a new unsaved file with the given `name` and `contents`.
2036    pub(crate) fn new(name: &str, contents: &str) -> UnsavedFile {
2037        let name = CString::new(name.as_bytes()).unwrap();
2038        let contents = CString::new(contents.as_bytes()).unwrap();
2039        let x = CXUnsavedFile {
2040            Filename: name.as_ptr(),
2041            Contents: contents.as_ptr(),
2042            Length: contents.as_bytes().len() as c_ulong,
2043        };
2044        UnsavedFile { x, name, contents }
2045    }
2046}
2047
2048impl fmt::Debug for UnsavedFile {
2049    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2050        write!(
2051            fmt,
2052            "UnsavedFile(name: {:?}, contents: {:?})",
2053            self.name, self.contents
2054        )
2055    }
2056}
2057
2058/// Convert a cursor kind into a static string.
2059pub(crate) fn kind_to_str(x: CXCursorKind) -> String {
2060    unsafe { cxstring_into_string(clang_getCursorKindSpelling(x)) }
2061}
2062
2063/// Convert a type kind to a static string.
2064pub(crate) fn type_to_str(x: CXTypeKind) -> String {
2065    unsafe { cxstring_into_string(clang_getTypeKindSpelling(x)) }
2066}
2067
2068/// Dump the Clang AST to stdout for debugging purposes.
2069pub(crate) fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
2070    fn print_indent<S: AsRef<str>>(depth: isize, s: S) {
2071        for _ in 0..depth {
2072            print!("    ");
2073        }
2074        println!("{}", s.as_ref());
2075    }
2076
2077    fn print_cursor<S: AsRef<str>>(depth: isize, prefix: S, c: &Cursor) {
2078        let prefix = prefix.as_ref();
2079        print_indent(
2080            depth,
2081            format!(" {prefix}kind = {}", kind_to_str(c.kind())),
2082        );
2083        print_indent(
2084            depth,
2085            format!(" {prefix}spelling = \"{}\"", c.spelling()),
2086        );
2087        print_indent(depth, format!(" {prefix}location = {}", c.location()));
2088        print_indent(
2089            depth,
2090            format!(" {prefix}is-definition? {}", c.is_definition()),
2091        );
2092        print_indent(
2093            depth,
2094            format!(" {prefix}is-declaration? {}", c.is_declaration()),
2095        );
2096        print_indent(
2097            depth,
2098            format!(
2099                " {prefix}is-inlined-function? {}",
2100                c.is_inlined_function()
2101            ),
2102        );
2103
2104        let templ_kind = c.template_kind();
2105        if templ_kind != CXCursor_NoDeclFound {
2106            print_indent(
2107                depth,
2108                format!(" {prefix}template-kind = {}", kind_to_str(templ_kind)),
2109            );
2110        }
2111        if let Some(usr) = c.usr() {
2112            print_indent(depth, format!(" {prefix}usr = \"{usr}\""));
2113        }
2114        if let Ok(num) = c.num_args() {
2115            print_indent(depth, format!(" {prefix}number-of-args = {num}"));
2116        }
2117        if let Some(num) = c.num_template_args() {
2118            print_indent(
2119                depth,
2120                format!(" {prefix}number-of-template-args = {num}"),
2121            );
2122        }
2123
2124        if c.is_bit_field() {
2125            let width = match c.bit_width() {
2126                Some(w) => w.to_string(),
2127                None => "<unevaluable>".to_string(),
2128            };
2129            print_indent(depth, format!(" {prefix}bit-width = {width}"));
2130        }
2131
2132        if let Some(ty) = c.enum_type() {
2133            print_indent(
2134                depth,
2135                format!(" {prefix}enum-type = {}", type_to_str(ty.kind())),
2136            );
2137        }
2138        if let Some(val) = c.enum_val_signed() {
2139            print_indent(depth, format!(" {prefix}enum-val = {val}"));
2140        }
2141        if let Some(ty) = c.typedef_type() {
2142            print_indent(
2143                depth,
2144                format!(" {prefix}typedef-type = {}", type_to_str(ty.kind())),
2145            );
2146        }
2147        if let Some(ty) = c.ret_type() {
2148            print_indent(
2149                depth,
2150                format!(" {prefix}ret-type = {}", type_to_str(ty.kind())),
2151            );
2152        }
2153
2154        if let Some(refd) = c.referenced() {
2155            if refd != *c {
2156                println!();
2157                print_cursor(
2158                    depth,
2159                    String::from(prefix) + "referenced.",
2160                    &refd,
2161                );
2162            }
2163        }
2164
2165        let canonical = c.canonical();
2166        if canonical != *c {
2167            println!();
2168            print_cursor(
2169                depth,
2170                String::from(prefix) + "canonical.",
2171                &canonical,
2172            );
2173        }
2174
2175        if let Some(specialized) = c.specialized() {
2176            if specialized != *c {
2177                println!();
2178                print_cursor(
2179                    depth,
2180                    String::from(prefix) + "specialized.",
2181                    &specialized,
2182                );
2183            }
2184        }
2185
2186        if let Some(parent) = c.fallible_semantic_parent() {
2187            println!();
2188            print_cursor(
2189                depth,
2190                String::from(prefix) + "semantic-parent.",
2191                &parent,
2192            );
2193        }
2194    }
2195
2196    fn print_type<S: AsRef<str>>(depth: isize, prefix: S, ty: &Type) {
2197        let prefix = prefix.as_ref();
2198
2199        let kind = ty.kind();
2200        print_indent(depth, format!(" {prefix}kind = {}", type_to_str(kind)));
2201        if kind == CXType_Invalid {
2202            return;
2203        }
2204
2205        print_indent(depth, format!(" {prefix}cconv = {}", ty.call_conv()));
2206
2207        print_indent(
2208            depth,
2209            format!(" {prefix}spelling = \"{}\"", ty.spelling()),
2210        );
2211        let num_template_args =
2212            unsafe { clang_Type_getNumTemplateArguments(ty.x) };
2213        if num_template_args >= 0 {
2214            print_indent(
2215                depth,
2216                format!(
2217                    " {prefix}number-of-template-args = {num_template_args}"
2218                ),
2219            );
2220        }
2221        if let Some(num) = ty.num_elements() {
2222            print_indent(depth, format!(" {prefix}number-of-elements = {num}"));
2223        }
2224        print_indent(
2225            depth,
2226            format!(" {prefix}is-variadic? {}", ty.is_variadic()),
2227        );
2228
2229        let canonical = ty.canonical_type();
2230        if canonical != *ty {
2231            println!();
2232            print_type(depth, String::from(prefix) + "canonical.", &canonical);
2233        }
2234
2235        if let Some(pointee) = ty.pointee_type() {
2236            if pointee != *ty {
2237                println!();
2238                print_type(depth, String::from(prefix) + "pointee.", &pointee);
2239            }
2240        }
2241
2242        if let Some(elem) = ty.elem_type() {
2243            if elem != *ty {
2244                println!();
2245                print_type(depth, String::from(prefix) + "elements.", &elem);
2246            }
2247        }
2248
2249        if let Some(ret) = ty.ret_type() {
2250            if ret != *ty {
2251                println!();
2252                print_type(depth, String::from(prefix) + "return.", &ret);
2253            }
2254        }
2255
2256        let named = ty.named();
2257        if named != *ty && named.is_valid() {
2258            println!();
2259            print_type(depth, String::from(prefix) + "named.", &named);
2260        }
2261    }
2262
2263    print_indent(depth, "(");
2264    print_cursor(depth, "", c);
2265
2266    println!();
2267    let ty = c.cur_type();
2268    print_type(depth, "type.", &ty);
2269
2270    let declaration = ty.declaration();
2271    if declaration != *c && declaration.kind() != CXCursor_NoDeclFound {
2272        println!();
2273        print_cursor(depth, "type.declaration.", &declaration);
2274    }
2275
2276    // Recurse.
2277    let mut found_children = false;
2278    c.visit(|s| {
2279        if !found_children {
2280            println!();
2281            found_children = true;
2282        }
2283        ast_dump(&s, depth + 1)
2284    });
2285
2286    print_indent(depth, ")");
2287
2288    CXChildVisit_Continue
2289}
2290
2291/// Try to extract the clang version to a string
2292pub(crate) fn extract_clang_version() -> String {
2293    unsafe { cxstring_into_string(clang_getClangVersion()) }
2294}
2295
2296/// A wrapper for the result of evaluating an expression.
2297#[derive(Debug)]
2298pub(crate) struct EvalResult {
2299    x: CXEvalResult,
2300    ty: Type,
2301}
2302
2303impl EvalResult {
2304    /// Evaluate `cursor` and return the result.
2305    pub(crate) fn new(cursor: Cursor) -> Option<Self> {
2306        // Work around https://bugs.llvm.org/show_bug.cgi?id=42532, see:
2307        //  * https://github.com/rust-lang/rust-bindgen/issues/283
2308        //  * https://github.com/rust-lang/rust-bindgen/issues/1590
2309        {
2310            let mut found_cant_eval = false;
2311            cursor.visit(|c| {
2312                if c.kind() == CXCursor_TypeRef &&
2313                    c.cur_type().canonical_type().kind() == CXType_Unexposed
2314                {
2315                    found_cant_eval = true;
2316                    return CXChildVisit_Break;
2317                }
2318
2319                CXChildVisit_Recurse
2320            });
2321
2322            if found_cant_eval {
2323                return None;
2324            }
2325        }
2326        Some(EvalResult {
2327            x: unsafe { clang_Cursor_Evaluate(cursor.x) },
2328            ty: cursor.cur_type().canonical_type(),
2329        })
2330    }
2331
2332    fn kind(&self) -> CXEvalResultKind {
2333        unsafe { clang_EvalResult_getKind(self.x) }
2334    }
2335
2336    /// Try to get back the result as a double.
2337    pub(crate) fn as_double(&self) -> Option<f64> {
2338        match self.kind() {
2339            CXEval_Float => {
2340                Some(unsafe { clang_EvalResult_getAsDouble(self.x) })
2341            }
2342            _ => None,
2343        }
2344    }
2345
2346    /// Try to get back the result as an integer.
2347    pub(crate) fn as_int(&self) -> Option<i64> {
2348        if self.kind() != CXEval_Int {
2349            return None;
2350        }
2351
2352        if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
2353            let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
2354            if value > i64::MAX as c_ulonglong {
2355                return None;
2356            }
2357
2358            return Some(value as i64);
2359        }
2360
2361        let value = unsafe { clang_EvalResult_getAsLongLong(self.x) };
2362        if value > i64::MAX as c_longlong {
2363            return None;
2364        }
2365        if value < i64::MIN as c_longlong {
2366            return None;
2367        }
2368        #[allow(clippy::unnecessary_cast)]
2369        Some(value as i64)
2370    }
2371
2372    /// Evaluates the expression as a literal string, that may or may not be
2373    /// valid utf-8.
2374    pub(crate) fn as_literal_string(&self) -> Option<Vec<u8>> {
2375        if self.kind() != CXEval_StrLiteral {
2376            return None;
2377        }
2378
2379        let char_ty = self.ty.pointee_type().or_else(|| self.ty.elem_type())?;
2380        match char_ty.kind() {
2381            CXType_Char_S | CXType_SChar | CXType_Char_U | CXType_UChar => {
2382                let ret = unsafe {
2383                    CStr::from_ptr(clang_EvalResult_getAsStr(self.x))
2384                };
2385                Some(ret.to_bytes().to_vec())
2386            }
2387            // FIXME: Support generating these.
2388            CXType_Char16 => None,
2389            CXType_Char32 => None,
2390            CXType_WChar => None,
2391            _ => None,
2392        }
2393    }
2394}
2395
2396impl Drop for EvalResult {
2397    fn drop(&mut self) {
2398        unsafe { clang_EvalResult_dispose(self.x) };
2399    }
2400}
2401/// ABI kinds as defined in
2402/// <https://github.com/llvm/llvm-project/blob/ddf1de20a3f7db3bca1ef6ba7e6cbb90aac5fd2d/clang/include/clang/Basic/TargetCXXABI.def>
2403#[derive(Debug, Eq, PartialEq, Copy, Clone)]
2404pub(crate) enum ABIKind {
2405    /// All the regular targets like Linux, Mac, WASM, etc. implement the Itanium ABI
2406    GenericItanium,
2407    /// The ABI used when compiling for the MSVC target
2408    Microsoft,
2409}
2410
2411/// Target information obtained from libclang.
2412#[derive(Debug)]
2413pub(crate) struct TargetInfo {
2414    /// The target triple.
2415    pub(crate) triple: String,
2416    /// The width of the pointer _in bits_.
2417    pub(crate) pointer_width: usize,
2418    /// The ABI of the target
2419    pub(crate) abi: ABIKind,
2420}
2421
2422impl TargetInfo {
2423    /// Tries to obtain target information from libclang.
2424    pub(crate) fn new(tu: &TranslationUnit) -> Self {
2425        let triple;
2426        let pointer_width;
2427        unsafe {
2428            let ti = clang_getTranslationUnitTargetInfo(tu.x);
2429            triple = cxstring_into_string(clang_TargetInfo_getTriple(ti));
2430            pointer_width = clang_TargetInfo_getPointerWidth(ti);
2431            clang_TargetInfo_dispose(ti);
2432        }
2433        assert!(pointer_width > 0);
2434        assert_eq!(pointer_width % 8, 0);
2435
2436        let abi = if triple.contains("msvc") {
2437            ABIKind::Microsoft
2438        } else {
2439            ABIKind::GenericItanium
2440        };
2441
2442        TargetInfo {
2443            triple,
2444            pointer_width: pointer_width as usize,
2445            abi,
2446        }
2447    }
2448}