bindgen/ir/
context.rs

1//! Common context that is passed around during parsing and codegen.
2
3use super::super::time::Timer;
4use super::analysis::{
5    analyze, as_cannot_derive_set, CannotDerive, DeriveTrait,
6    HasDestructorAnalysis, HasFloat, HasTypeParameterInArray,
7    HasVtableAnalysis, HasVtableResult, SizednessAnalysis, SizednessResult,
8    UsedTemplateParameters,
9};
10use super::derive::{
11    CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
12    CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
13};
14use super::function::Function;
15use super::int::IntKind;
16use super::item::{IsOpaque, Item, ItemAncestors, ItemSet};
17use super::item_kind::ItemKind;
18use super::module::{Module, ModuleKind};
19use super::template::{TemplateInstantiation, TemplateParameters};
20use super::traversal::{self, Edge, ItemTraversal};
21use super::ty::{FloatKind, Type, TypeKind};
22use crate::clang::{self, ABIKind, Cursor};
23use crate::codegen::CodegenError;
24use crate::BindgenOptions;
25use crate::{Entry, HashMap, HashSet};
26
27use proc_macro2::{Ident, Span, TokenStream};
28use quote::ToTokens;
29use std::borrow::Cow;
30use std::cell::{Cell, RefCell};
31use std::collections::{BTreeSet, HashMap as StdHashMap};
32use std::fs::OpenOptions;
33use std::io::Write;
34use std::mem;
35use std::path::Path;
36
37/// An identifier for some kind of IR item.
38#[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
39pub(crate) struct ItemId(usize);
40
41/// Declare a newtype around `ItemId` with conversion methods.
42macro_rules! item_id_newtype {
43    (
44        $( #[$attr:meta] )*
45        pub(crate) struct $name:ident(ItemId)
46        where
47            $( #[$checked_attr:meta] )*
48            checked = $checked:ident with $check_method:ident,
49            $( #[$expected_attr:meta] )*
50            expected = $expected:ident,
51            $( #[$unchecked_attr:meta] )*
52            unchecked = $unchecked:ident;
53    ) => {
54        $( #[$attr] )*
55        #[derive(Debug, Copy, Clone, Eq, PartialOrd, Ord, Hash)]
56        pub(crate) struct $name(ItemId);
57
58        impl $name {
59            /// Create an `ItemResolver` from this ID.
60            #[allow(dead_code)]
61            pub(crate) fn into_resolver(self) -> ItemResolver {
62                let id: ItemId = self.into();
63                id.into()
64            }
65        }
66
67        impl<T> ::std::cmp::PartialEq<T> for $name
68        where
69            T: Copy + Into<ItemId>
70        {
71            fn eq(&self, rhs: &T) -> bool {
72                let rhs: ItemId = (*rhs).into();
73                self.0 == rhs
74            }
75        }
76
77        impl From<$name> for ItemId {
78            fn from(id: $name) -> ItemId {
79                id.0
80            }
81        }
82
83        impl<'a> From<&'a $name> for ItemId {
84            fn from(id: &'a $name) -> ItemId {
85                id.0
86            }
87        }
88
89        #[allow(dead_code)]
90        impl ItemId {
91            $( #[$checked_attr] )*
92            pub(crate) fn $checked(&self, ctx: &BindgenContext) -> Option<$name> {
93                if ctx.resolve_item(*self).kind().$check_method() {
94                    Some($name(*self))
95                } else {
96                    None
97                }
98            }
99
100            $( #[$expected_attr] )*
101            pub(crate) fn $expected(&self, ctx: &BindgenContext) -> $name {
102                self.$checked(ctx)
103                    .expect(concat!(
104                        stringify!($expected),
105                        " called with ItemId that points to the wrong ItemKind"
106                    ))
107            }
108
109            $( #[$unchecked_attr] )*
110            pub(crate) fn $unchecked(&self) -> $name {
111                $name(*self)
112            }
113        }
114    }
115}
116
117item_id_newtype! {
118    /// An identifier for an `Item` whose `ItemKind` is known to be
119    /// `ItemKind::Type`.
120    pub(crate) struct TypeId(ItemId)
121    where
122        /// Convert this `ItemId` into a `TypeId` if its associated item is a type,
123        /// otherwise return `None`.
124        checked = as_type_id with is_type,
125
126        /// Convert this `ItemId` into a `TypeId`.
127        ///
128        /// If this `ItemId` does not point to a type, then panic.
129        expected = expect_type_id,
130
131        /// Convert this `ItemId` into a `TypeId` without actually checking whether
132        /// this ID actually points to a `Type`.
133        unchecked = as_type_id_unchecked;
134}
135
136item_id_newtype! {
137    /// An identifier for an `Item` whose `ItemKind` is known to be
138    /// `ItemKind::Module`.
139    pub(crate) struct ModuleId(ItemId)
140    where
141        /// Convert this `ItemId` into a `ModuleId` if its associated item is a
142        /// module, otherwise return `None`.
143        checked = as_module_id with is_module,
144
145        /// Convert this `ItemId` into a `ModuleId`.
146        ///
147        /// If this `ItemId` does not point to a module, then panic.
148        expected = expect_module_id,
149
150        /// Convert this `ItemId` into a `ModuleId` without actually checking
151        /// whether this ID actually points to a `Module`.
152        unchecked = as_module_id_unchecked;
153}
154
155item_id_newtype! {
156    /// An identifier for an `Item` whose `ItemKind` is known to be
157    /// `ItemKind::Var`.
158    pub(crate) struct VarId(ItemId)
159    where
160        /// Convert this `ItemId` into a `VarId` if its associated item is a var,
161        /// otherwise return `None`.
162        checked = as_var_id with is_var,
163
164        /// Convert this `ItemId` into a `VarId`.
165        ///
166        /// If this `ItemId` does not point to a var, then panic.
167        expected = expect_var_id,
168
169        /// Convert this `ItemId` into a `VarId` without actually checking whether
170        /// this ID actually points to a `Var`.
171        unchecked = as_var_id_unchecked;
172}
173
174item_id_newtype! {
175    /// An identifier for an `Item` whose `ItemKind` is known to be
176    /// `ItemKind::Function`.
177    pub(crate) struct FunctionId(ItemId)
178    where
179        /// Convert this `ItemId` into a `FunctionId` if its associated item is a function,
180        /// otherwise return `None`.
181        checked = as_function_id with is_function,
182
183        /// Convert this `ItemId` into a `FunctionId`.
184        ///
185        /// If this `ItemId` does not point to a function, then panic.
186        expected = expect_function_id,
187
188        /// Convert this `ItemId` into a `FunctionId` without actually checking whether
189        /// this ID actually points to a `Function`.
190        unchecked = as_function_id_unchecked;
191}
192
193impl From<ItemId> for usize {
194    fn from(id: ItemId) -> usize {
195        id.0
196    }
197}
198
199impl ItemId {
200    /// Get a numeric representation of this ID.
201    pub(crate) fn as_usize(&self) -> usize {
202        (*self).into()
203    }
204}
205
206impl<T> ::std::cmp::PartialEq<T> for ItemId
207where
208    T: Copy + Into<ItemId>,
209{
210    fn eq(&self, rhs: &T) -> bool {
211        let rhs: ItemId = (*rhs).into();
212        self.0 == rhs.0
213    }
214}
215
216impl<T> CanDeriveDebug for T
217where
218    T: Copy + Into<ItemId>,
219{
220    fn can_derive_debug(&self, ctx: &BindgenContext) -> bool {
221        ctx.options().derive_debug && ctx.lookup_can_derive_debug(*self)
222    }
223}
224
225impl<T> CanDeriveDefault for T
226where
227    T: Copy + Into<ItemId>,
228{
229    fn can_derive_default(&self, ctx: &BindgenContext) -> bool {
230        ctx.options().derive_default && ctx.lookup_can_derive_default(*self)
231    }
232}
233
234impl<T> CanDeriveCopy for T
235where
236    T: Copy + Into<ItemId>,
237{
238    fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
239        ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self)
240    }
241}
242
243impl<T> CanDeriveHash for T
244where
245    T: Copy + Into<ItemId>,
246{
247    fn can_derive_hash(&self, ctx: &BindgenContext) -> bool {
248        ctx.options().derive_hash && ctx.lookup_can_derive_hash(*self)
249    }
250}
251
252impl<T> CanDerivePartialOrd for T
253where
254    T: Copy + Into<ItemId>,
255{
256    fn can_derive_partialord(&self, ctx: &BindgenContext) -> bool {
257        ctx.options().derive_partialord &&
258            ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
259                CanDerive::Yes
260    }
261}
262
263impl<T> CanDerivePartialEq for T
264where
265    T: Copy + Into<ItemId>,
266{
267    fn can_derive_partialeq(&self, ctx: &BindgenContext) -> bool {
268        ctx.options().derive_partialeq &&
269            ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
270                CanDerive::Yes
271    }
272}
273
274impl<T> CanDeriveEq for T
275where
276    T: Copy + Into<ItemId>,
277{
278    fn can_derive_eq(&self, ctx: &BindgenContext) -> bool {
279        ctx.options().derive_eq &&
280            ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
281                CanDerive::Yes &&
282            !ctx.lookup_has_float(*self)
283    }
284}
285
286impl<T> CanDeriveOrd for T
287where
288    T: Copy + Into<ItemId>,
289{
290    fn can_derive_ord(&self, ctx: &BindgenContext) -> bool {
291        ctx.options().derive_ord &&
292            ctx.lookup_can_derive_partialeq_or_partialord(*self) ==
293                CanDerive::Yes &&
294            !ctx.lookup_has_float(*self)
295    }
296}
297
298/// A key used to index a resolved type, so we only process it once.
299///
300/// This is almost always a USR string (an unique identifier generated by
301/// clang), but it can also be the canonical declaration if the type is unnamed,
302/// in which case clang may generate the same USR for multiple nested unnamed
303/// types.
304#[derive(Eq, PartialEq, Hash, Debug)]
305enum TypeKey {
306    Usr(String),
307    Declaration(Cursor),
308}
309
310/// A context used during parsing and generation of structs.
311#[derive(Debug)]
312pub(crate) struct BindgenContext {
313    /// The map of all the items parsed so far, keyed off `ItemId`.
314    items: Vec<Option<Item>>,
315
316    /// Clang USR to type map. This is needed to be able to associate types with
317    /// item ids during parsing.
318    types: HashMap<TypeKey, TypeId>,
319
320    /// Maps from a cursor to the item ID of the named template type parameter
321    /// for that cursor.
322    type_params: HashMap<Cursor, TypeId>,
323
324    /// A cursor to module map. Similar reason than above.
325    modules: HashMap<Cursor, ModuleId>,
326
327    /// The root module, this is guaranteed to be an item of kind Module.
328    root_module: ModuleId,
329
330    /// Current module being traversed.
331    current_module: ModuleId,
332
333    /// A `HashMap` keyed on a type definition, and whose value is the parent ID
334    /// of the declaration.
335    ///
336    /// This is used to handle the cases where the semantic and the lexical
337    /// parents of the cursor differ, like when a nested class is defined
338    /// outside of the parent class.
339    semantic_parents: HashMap<Cursor, ItemId>,
340
341    /// A stack with the current type declarations and types we're parsing. This
342    /// is needed to avoid infinite recursion when parsing a type like:
343    ///
344    /// struct c { struct c* next; };
345    ///
346    /// This means effectively, that a type has a potential ID before knowing if
347    /// it's a correct type. But that's not important in practice.
348    ///
349    /// We could also use the `types` `HashMap`, but my intention with it is that
350    /// only valid types and declarations end up there, and this could
351    /// potentially break that assumption.
352    currently_parsed_types: Vec<PartialType>,
353
354    /// A map with all the already parsed macro names. This is done to avoid
355    /// hard errors while parsing duplicated macros, as well to allow macro
356    /// expression parsing.
357    ///
358    /// This needs to be an `std::HashMap` because the `cexpr` API requires it.
359    parsed_macros: StdHashMap<Vec<u8>, cexpr::expr::EvalResult>,
360
361    /// A map with all include locations.
362    ///
363    /// This is needed so that items are created in the order they are defined in.
364    ///
365    /// The key is the included file, the value is a pair of the source file and
366    /// the position of the `#include` directive in the source file.
367    includes: StdHashMap<String, (String, usize)>,
368
369    /// A set of all the included filenames.
370    deps: BTreeSet<Box<str>>,
371
372    /// The active replacements collected from replaces="xxx" annotations.
373    replacements: HashMap<Vec<String>, ItemId>,
374
375    collected_typerefs: bool,
376
377    in_codegen: bool,
378
379    /// The translation unit for parsing.
380    translation_unit: clang::TranslationUnit,
381
382    /// The translation unit for macro fallback parsing.
383    fallback_tu: Option<clang::FallbackTranslationUnit>,
384
385    /// Target information that can be useful for some stuff.
386    target_info: clang::TargetInfo,
387
388    /// The options given by the user via cli or other medium.
389    options: BindgenOptions,
390
391    /// Whether an opaque array was generated
392    generated_opaque_array: Cell<bool>,
393
394    /// Whether a bindgen complex was generated
395    generated_bindgen_complex: Cell<bool>,
396
397    /// Whether a bindgen float16 was generated
398    generated_bindgen_float16: Cell<bool>,
399
400    /// The set of `ItemId`s that are allowlisted. This the very first thing
401    /// computed after parsing our IR, and before running any of our analyses.
402    allowlisted: Option<ItemSet>,
403
404    /// Cache for calls to `ParseCallbacks::blocklisted_type_implements_trait`
405    blocklisted_types_implement_traits:
406        RefCell<HashMap<DeriveTrait, HashMap<ItemId, CanDerive>>>,
407
408    /// The set of `ItemId`s that are allowlisted for code generation _and_ that
409    /// we should generate accounting for the codegen options.
410    ///
411    /// It's computed right after computing the allowlisted items.
412    codegen_items: Option<ItemSet>,
413
414    /// Map from an item's ID to the set of template parameter items that it
415    /// uses. See `ir::named` for more details. Always `Some` during the codegen
416    /// phase.
417    used_template_parameters: Option<HashMap<ItemId, ItemSet>>,
418
419    /// The set of `TypeKind::Comp` items found during parsing that need their
420    /// bitfield allocation units computed. Drained in `compute_bitfield_units`.
421    need_bitfield_allocation: Vec<ItemId>,
422
423    /// The set of enums that are defined by a pair of `enum` and `typedef`,
424    /// which is legal in C (but not C++).
425    ///
426    /// ```c++
427    /// // in either order
428    /// enum Enum { Variants... };
429    /// typedef int16_t Enum;
430    /// ```
431    ///
432    /// The stored `ItemId` is that of the `TypeKind::Enum`, not of the
433    /// `TypeKind::Alias`.
434    ///
435    /// This is populated when we enter codegen by `compute_enum_typedef_combos`
436    /// and is always `None` before that and `Some` after.
437    enum_typedef_combos: Option<HashSet<ItemId>>,
438
439    /// The set of (`ItemId`s of) types that can't derive debug.
440    ///
441    /// This is populated when we enter codegen by `compute_cannot_derive_debug`
442    /// and is always `None` before that and `Some` after.
443    cannot_derive_debug: Option<HashSet<ItemId>>,
444
445    /// The set of (`ItemId`s of) types that can't derive default.
446    ///
447    /// This is populated when we enter codegen by `compute_cannot_derive_default`
448    /// and is always `None` before that and `Some` after.
449    cannot_derive_default: Option<HashSet<ItemId>>,
450
451    /// The set of (`ItemId`s of) types that can't derive copy.
452    ///
453    /// This is populated when we enter codegen by `compute_cannot_derive_copy`
454    /// and is always `None` before that and `Some` after.
455    cannot_derive_copy: Option<HashSet<ItemId>>,
456
457    /// The set of (`ItemId`s of) types that can't derive hash.
458    ///
459    /// This is populated when we enter codegen by `compute_can_derive_hash`
460    /// and is always `None` before that and `Some` after.
461    cannot_derive_hash: Option<HashSet<ItemId>>,
462
463    /// The map why specified `ItemId`s of) types that can't derive hash.
464    ///
465    /// This is populated when we enter codegen by
466    /// `compute_cannot_derive_partialord_partialeq_or_eq` and is always `None`
467    /// before that and `Some` after.
468    cannot_derive_partialeq_or_partialord: Option<HashMap<ItemId, CanDerive>>,
469
470    /// The sizedness of types.
471    ///
472    /// This is populated by `compute_sizedness` and is always `None` before
473    /// that function is invoked and `Some` afterwards.
474    sizedness: Option<HashMap<TypeId, SizednessResult>>,
475
476    /// The set of (`ItemId's of`) types that has vtable.
477    ///
478    /// Populated when we enter codegen by `compute_has_vtable`; always `None`
479    /// before that and `Some` after.
480    have_vtable: Option<HashMap<ItemId, HasVtableResult>>,
481
482    /// The set of (`ItemId's of`) types that has destructor.
483    ///
484    /// Populated when we enter codegen by `compute_has_destructor`; always `None`
485    /// before that and `Some` after.
486    have_destructor: Option<HashSet<ItemId>>,
487
488    /// The set of (`ItemId's of`) types that has array.
489    ///
490    /// Populated when we enter codegen by `compute_has_type_param_in_array`; always `None`
491    /// before that and `Some` after.
492    has_type_param_in_array: Option<HashSet<ItemId>>,
493
494    /// The set of (`ItemId's of`) types that has float.
495    ///
496    /// Populated when we enter codegen by `compute_has_float`; always `None`
497    /// before that and `Some` after.
498    has_float: Option<HashSet<ItemId>>,
499}
500
501/// A traversal of allowlisted items.
502struct AllowlistedItemsTraversal<'ctx> {
503    ctx: &'ctx BindgenContext,
504    traversal: ItemTraversal<'ctx, ItemSet, Vec<ItemId>>,
505}
506
507impl Iterator for AllowlistedItemsTraversal<'_> {
508    type Item = ItemId;
509
510    fn next(&mut self) -> Option<ItemId> {
511        loop {
512            let id = self.traversal.next()?;
513
514            if self.ctx.resolve_item(id).is_blocklisted(self.ctx) {
515                continue;
516            }
517
518            return Some(id);
519        }
520    }
521}
522
523impl<'ctx> AllowlistedItemsTraversal<'ctx> {
524    /// Construct a new allowlisted items traversal.
525    pub(crate) fn new<R>(
526        ctx: &'ctx BindgenContext,
527        roots: R,
528        predicate: for<'a> fn(&'a BindgenContext, Edge) -> bool,
529    ) -> Self
530    where
531        R: IntoIterator<Item = ItemId>,
532    {
533        AllowlistedItemsTraversal {
534            ctx,
535            traversal: ItemTraversal::new(ctx, roots, predicate),
536        }
537    }
538}
539
540impl BindgenContext {
541    /// Construct the context for the given `options`.
542    pub(crate) fn new(
543        options: BindgenOptions,
544        input_unsaved_files: &[clang::UnsavedFile],
545    ) -> Self {
546        // TODO(emilio): Use the CXTargetInfo here when available.
547        //
548        // see: https://reviews.llvm.org/D32389
549        let index = clang::Index::new(false, true);
550
551        let parse_options =
552            clang_sys::CXTranslationUnit_DetailedPreprocessingRecord;
553
554        let translation_unit = {
555            let _t =
556                Timer::new("translation_unit").with_output(options.time_phases);
557
558            clang::TranslationUnit::parse(
559                &index,
560                "",
561                &options.clang_args,
562                input_unsaved_files,
563                parse_options,
564            ).expect("libclang error; possible causes include:
565- Invalid flag syntax
566- Unrecognized flags
567- Invalid flag arguments
568- File I/O errors
569- Host vs. target architecture mismatch
570If you encounter an error missing from this list, please file an issue or a PR!")
571        };
572
573        let target_info = clang::TargetInfo::new(&translation_unit);
574        let root_module = Self::build_root_module(ItemId(0));
575        let root_module_id = root_module.id().as_module_id_unchecked();
576
577        // depfiles need to include the explicitly listed headers too
578        let deps = options.input_headers.iter().cloned().collect();
579
580        BindgenContext {
581            items: vec![Some(root_module)],
582            includes: Default::default(),
583            deps,
584            types: Default::default(),
585            type_params: Default::default(),
586            modules: Default::default(),
587            root_module: root_module_id,
588            current_module: root_module_id,
589            semantic_parents: Default::default(),
590            currently_parsed_types: vec![],
591            parsed_macros: Default::default(),
592            replacements: Default::default(),
593            collected_typerefs: false,
594            in_codegen: false,
595            translation_unit,
596            fallback_tu: None,
597            target_info,
598            options,
599            generated_bindgen_complex: Cell::new(false),
600            generated_bindgen_float16: Cell::new(false),
601            generated_opaque_array: Cell::new(false),
602            allowlisted: None,
603            blocklisted_types_implement_traits: Default::default(),
604            codegen_items: None,
605            used_template_parameters: None,
606            need_bitfield_allocation: Default::default(),
607            enum_typedef_combos: None,
608            cannot_derive_debug: None,
609            cannot_derive_default: None,
610            cannot_derive_copy: None,
611            cannot_derive_hash: None,
612            cannot_derive_partialeq_or_partialord: None,
613            sizedness: None,
614            have_vtable: None,
615            have_destructor: None,
616            has_type_param_in_array: None,
617            has_float: None,
618        }
619    }
620
621    /// Returns `true` if the target architecture is wasm32
622    pub(crate) fn is_target_wasm32(&self) -> bool {
623        self.target_info.triple.starts_with("wasm32-")
624    }
625
626    /// Creates a timer for the current bindgen phase. If `time_phases` is `true`,
627    /// the timer will print to stderr when it is dropped, otherwise it will do
628    /// nothing.
629    pub(crate) fn timer<'a>(&self, name: &'a str) -> Timer<'a> {
630        Timer::new(name).with_output(self.options.time_phases)
631    }
632
633    /// Returns the pointer width to use for the target for the current
634    /// translation.
635    pub(crate) fn target_pointer_size(&self) -> usize {
636        self.target_info.pointer_width / 8
637    }
638
639    /// Returns the ABI, which is mostly useful for determining the mangling kind.
640    pub(crate) fn abi_kind(&self) -> ABIKind {
641        self.target_info.abi
642    }
643
644    /// Get the stack of partially parsed types that we are in the middle of
645    /// parsing.
646    pub(crate) fn currently_parsed_types(&self) -> &[PartialType] {
647        &self.currently_parsed_types[..]
648    }
649
650    /// Begin parsing the given partial type, and push it onto the
651    /// `currently_parsed_types` stack so that we won't infinite recurse if we
652    /// run into a reference to it while parsing it.
653    pub(crate) fn begin_parsing(&mut self, partial_ty: PartialType) {
654        self.currently_parsed_types.push(partial_ty);
655    }
656
657    /// Finish parsing the current partial type, pop it off the
658    /// `currently_parsed_types` stack, and return it.
659    pub(crate) fn finish_parsing(&mut self) -> PartialType {
660        self.currently_parsed_types.pop().expect(
661            "should have been parsing a type, if we finished parsing a type",
662        )
663    }
664
665    /// Add the location of the `#include` directive for the `included_file`.
666    pub(crate) fn add_include(
667        &mut self,
668        source_file: String,
669        included_file: String,
670        offset: usize,
671    ) {
672        self.includes
673            .entry(included_file)
674            .or_insert((source_file, offset));
675    }
676
677    /// Get the location of the first `#include` directive for the `included_file`.
678    pub(crate) fn included_file_location(
679        &self,
680        included_file: &str,
681    ) -> Option<(String, usize)> {
682        self.includes.get(included_file).cloned()
683    }
684
685    /// Add an included file.
686    pub(crate) fn add_dep(&mut self, dep: Box<str>) {
687        self.deps.insert(dep);
688    }
689
690    /// Get any included files.
691    pub(crate) fn deps(&self) -> &BTreeSet<Box<str>> {
692        &self.deps
693    }
694
695    /// Define a new item.
696    ///
697    /// This inserts it into the internal items set, and its type into the
698    /// internal types set.
699    pub(crate) fn add_item(
700        &mut self,
701        item: Item,
702        declaration: Option<Cursor>,
703        location: Option<Cursor>,
704    ) {
705        debug!("BindgenContext::add_item({item:?}, declaration: {declaration:?}, loc: {location:?}");
706        debug_assert!(
707            declaration.is_some() ||
708                !item.kind().is_type() ||
709                item.kind().expect_type().is_builtin_or_type_param() ||
710                item.kind().expect_type().is_opaque(self, &item) ||
711                item.kind().expect_type().is_unresolved_ref(),
712            "Adding a type without declaration?"
713        );
714
715        let id = item.id();
716        let is_type = item.kind().is_type();
717        let is_unnamed = is_type && item.expect_type().name().is_none();
718        let is_template_instantiation =
719            is_type && item.expect_type().is_template_instantiation();
720
721        if item.id() != self.root_module {
722            self.add_item_to_module(&item);
723        }
724
725        if is_type && item.expect_type().is_comp() {
726            self.need_bitfield_allocation.push(id);
727        }
728
729        let old_item = mem::replace(&mut self.items[id.0], Some(item));
730        assert!(
731            old_item.is_none(),
732            "should not have already associated an item with the given id"
733        );
734
735        // Unnamed items can have an USR, but they can't be referenced from
736        // other sites explicitly and the USR can match if the unnamed items are
737        // nested, so don't bother tracking them.
738        if !is_type || is_template_instantiation {
739            return;
740        }
741        if let Some(mut declaration) = declaration {
742            if !declaration.is_valid() {
743                if let Some(location) = location {
744                    if location.is_template_like() {
745                        declaration = location;
746                    }
747                }
748            }
749            declaration = declaration.canonical();
750            if !declaration.is_valid() {
751                // This could happen, for example, with types like `int*` or
752                // similar.
753                //
754                // Fortunately, we don't care about those types being
755                // duplicated, so we can just ignore them.
756                debug!(
757                    "Invalid declaration {declaration:?} found for type {:?}",
758                    self.resolve_item_fallible(id)
759                        .unwrap()
760                        .kind()
761                        .expect_type()
762                );
763                return;
764            }
765
766            let key = if is_unnamed {
767                TypeKey::Declaration(declaration)
768            } else if let Some(usr) = declaration.usr() {
769                TypeKey::Usr(usr)
770            } else {
771                warn!("Valid declaration with no USR: {declaration:?}, {location:?}");
772                TypeKey::Declaration(declaration)
773            };
774
775            let old = self.types.insert(key, id.as_type_id_unchecked());
776            debug_assert_eq!(old, None);
777        }
778    }
779
780    /// Ensure that every item (other than the root module) is in a module's
781    /// children list. This is to make sure that every allowlisted item get's
782    /// codegen'd, even if its parent is not allowlisted. See issue #769 for
783    /// details.
784    fn add_item_to_module(&mut self, item: &Item) {
785        assert!(item.id() != self.root_module);
786        assert!(self.resolve_item_fallible(item.id()).is_none());
787
788        if let Some(ref mut parent) = self.items[item.parent_id().0] {
789            if let Some(module) = parent.as_module_mut() {
790                debug!(
791                    "add_item_to_module: adding {:?} as child of parent module {:?}",
792                    item.id(),
793                    item.parent_id()
794                );
795
796                module.children_mut().insert(item.id());
797                return;
798            }
799        }
800
801        debug!(
802            "add_item_to_module: adding {:?} as child of current module {:?}",
803            item.id(),
804            self.current_module
805        );
806
807        self.items[(self.current_module.0).0]
808            .as_mut()
809            .expect("Should always have an item for self.current_module")
810            .as_module_mut()
811            .expect("self.current_module should always be a module")
812            .children_mut()
813            .insert(item.id());
814    }
815
816    /// Add a new named template type parameter to this context's item set.
817    pub(crate) fn add_type_param(&mut self, item: Item, definition: Cursor) {
818        debug!("BindgenContext::add_type_param: item = {item:?}; definition = {definition:?}");
819
820        assert!(
821            item.expect_type().is_type_param(),
822            "Should directly be a named type, not a resolved reference or anything"
823        );
824        assert_eq!(
825            definition.kind(),
826            clang_sys::CXCursor_TemplateTypeParameter
827        );
828
829        self.add_item_to_module(&item);
830
831        let id = item.id();
832        let old_item = mem::replace(&mut self.items[id.0], Some(item));
833        assert!(
834            old_item.is_none(),
835            "should not have already associated an item with the given id"
836        );
837
838        let old_named_ty = self
839            .type_params
840            .insert(definition, id.as_type_id_unchecked());
841        assert!(
842            old_named_ty.is_none(),
843            "should not have already associated a named type with this id"
844        );
845    }
846
847    /// Get the named type defined at the given cursor location, if we've
848    /// already added one.
849    pub(crate) fn get_type_param(&self, definition: &Cursor) -> Option<TypeId> {
850        assert_eq!(
851            definition.kind(),
852            clang_sys::CXCursor_TemplateTypeParameter
853        );
854        self.type_params.get(definition).copied()
855    }
856
857    // TODO: Move all this syntax crap to other part of the code.
858
859    /// Mangles a name so it doesn't conflict with any keyword.
860    #[rustfmt::skip]
861    pub(crate) fn rust_mangle<'a>(&self, name: &'a str) -> Cow<'a, str> {
862        if name.contains('@') ||
863            name.contains('?') ||
864            name.contains('$') ||
865            matches!(
866                name,
867                "abstract" | "alignof" | "as" | "async" | "await" | "become" |
868                    "box" | "break" | "const" | "continue" | "crate" | "do" |
869                    "dyn" | "else" | "enum" | "extern" | "false" | "final" |
870                    "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" |
871                    "macro" | "match" | "mod" | "move" | "mut" | "offsetof" |
872                    "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
873                    "return" | "Self" | "self" | "sizeof" | "static" |
874                    "struct" | "super" | "trait" | "true" | "try" | "type" | "typeof" |
875                    "unsafe" | "unsized" | "use" | "virtual" | "where" |
876                    "while" | "yield" | "str" | "bool" | "f32" | "f64" |
877                    "usize" | "isize" | "u128" | "i128" | "u64" | "i64" |
878                    "u32" | "i32" | "u16" | "i16" | "u8" | "i8" | "_"
879            )
880        {
881            let mut s = name.to_owned();
882            s = s.replace('@', "_");
883            s = s.replace('?', "_");
884            s = s.replace('$', "_");
885            s.push('_');
886            return Cow::Owned(s);
887        }
888        Cow::Borrowed(name)
889    }
890
891    /// Returns a mangled name as a rust identifier.
892    pub(crate) fn rust_ident<S>(&self, name: S) -> Ident
893    where
894        S: AsRef<str>,
895    {
896        self.rust_ident_raw(self.rust_mangle(name.as_ref()))
897    }
898
899    /// Returns a mangled name as a rust identifier.
900    pub(crate) fn rust_ident_raw<T>(&self, name: T) -> Ident
901    where
902        T: AsRef<str>,
903    {
904        Ident::new(name.as_ref(), Span::call_site())
905    }
906
907    /// Iterate over all items that have been defined.
908    pub(crate) fn items(&self) -> impl Iterator<Item = (ItemId, &Item)> {
909        self.items.iter().enumerate().filter_map(|(index, item)| {
910            let item = item.as_ref()?;
911            Some((ItemId(index), item))
912        })
913    }
914
915    /// Have we collected all unresolved type references yet?
916    pub(crate) fn collected_typerefs(&self) -> bool {
917        self.collected_typerefs
918    }
919
920    /// Gather all the unresolved type references.
921    fn collect_typerefs(
922        &mut self,
923    ) -> Vec<(ItemId, clang::Type, Cursor, Option<ItemId>)> {
924        debug_assert!(!self.collected_typerefs);
925        self.collected_typerefs = true;
926        let mut typerefs = vec![];
927
928        for (id, item) in self.items() {
929            let kind = item.kind();
930            let Some(ty) = kind.as_type() else { continue };
931
932            if let TypeKind::UnresolvedTypeRef(ref ty, loc, parent_id) =
933                *ty.kind()
934            {
935                typerefs.push((id, *ty, loc, parent_id));
936            };
937        }
938        typerefs
939    }
940
941    /// Collect all of our unresolved type references and resolve them.
942    fn resolve_typerefs(&mut self) {
943        let _t = self.timer("resolve_typerefs");
944
945        let typerefs = self.collect_typerefs();
946
947        for (id, ty, loc, parent_id) in typerefs {
948            let _resolved =
949                {
950                    let resolved = Item::from_ty(&ty, loc, parent_id, self)
951                    .unwrap_or_else(|_| {
952                        warn!("Could not resolve type reference, falling back \
953                               to opaque blob");
954                        Item::new_opaque_type(self.next_item_id(), &ty, self)
955                    });
956
957                    let item = self.items[id.0].as_mut().unwrap();
958                    *item.kind_mut().as_type_mut().unwrap().kind_mut() =
959                        TypeKind::ResolvedTypeRef(resolved);
960                    resolved
961                };
962
963            // Something in the STL is trolling me. I don't need this assertion
964            // right now, but worth investigating properly once this lands.
965            //
966            // debug_assert!(self.items.get(&resolved).is_some(), "How?");
967            //
968            // if let Some(parent_id) = parent_id {
969            //     assert_eq!(self.items[&resolved].parent_id(), parent_id);
970            // }
971        }
972    }
973
974    /// Temporarily loan `Item` with the given `ItemId`. This provides means to
975    /// mutably borrow `Item` while having a reference to `BindgenContext`.
976    ///
977    /// `Item` with the given `ItemId` is removed from the context, given
978    /// closure is executed and then `Item` is placed back.
979    ///
980    /// # Panics
981    ///
982    /// Panics if attempt to resolve given `ItemId` inside the given
983    /// closure is made.
984    fn with_loaned_item<F, T>(&mut self, id: ItemId, f: F) -> T
985    where
986        F: (FnOnce(&BindgenContext, &mut Item) -> T),
987    {
988        let mut item = self.items[id.0].take().unwrap();
989
990        let result = f(self, &mut item);
991
992        let existing = mem::replace(&mut self.items[id.0], Some(item));
993        assert!(existing.is_none());
994
995        result
996    }
997
998    /// Compute the bitfield allocation units for all `TypeKind::Comp` items we
999    /// parsed.
1000    fn compute_bitfield_units(&mut self) {
1001        let _t = self.timer("compute_bitfield_units");
1002
1003        assert!(self.collected_typerefs());
1004
1005        let need_bitfield_allocation =
1006            mem::take(&mut self.need_bitfield_allocation);
1007        for id in need_bitfield_allocation {
1008            self.with_loaned_item(id, |ctx, item| {
1009                let ty = item.kind_mut().as_type_mut().unwrap();
1010                let layout = ty.layout(ctx);
1011                ty.as_comp_mut()
1012                    .unwrap()
1013                    .compute_bitfield_units(ctx, layout.as_ref());
1014            });
1015        }
1016    }
1017
1018    /// Assign a new generated name for each anonymous field.
1019    fn deanonymize_fields(&mut self) {
1020        let _t = self.timer("deanonymize_fields");
1021
1022        let comp_item_ids: Vec<ItemId> = self
1023            .items()
1024            .filter_map(|(id, item)| {
1025                if item.kind().as_type()?.is_comp() {
1026                    return Some(id);
1027                }
1028                None
1029            })
1030            .collect();
1031
1032        for id in comp_item_ids {
1033            self.with_loaned_item(id, |ctx, item| {
1034                item.kind_mut()
1035                    .as_type_mut()
1036                    .unwrap()
1037                    .as_comp_mut()
1038                    .unwrap()
1039                    .deanonymize_fields(ctx);
1040            });
1041        }
1042    }
1043
1044    /// Iterate over all items and replace any item that has been named in a
1045    /// `replaces="SomeType"` annotation with the replacement type.
1046    fn process_replacements(&mut self) {
1047        let _t = self.timer("process_replacements");
1048        if self.replacements.is_empty() {
1049            debug!("No replacements to process");
1050            return;
1051        }
1052
1053        // FIXME: This is linear, but the replaces="xxx" annotation was already
1054        // there, and for better or worse it's useful, sigh...
1055        //
1056        // We leverage the ResolvedTypeRef thing, though, which is cool :P.
1057
1058        let mut replacements = vec![];
1059
1060        for (id, item) in self.items() {
1061            if item.annotations().use_instead_of().is_some() {
1062                continue;
1063            }
1064
1065            // Calls to `canonical_name` are expensive, so eagerly filter out
1066            // items that cannot be replaced.
1067            let Some(ty) = item.kind().as_type() else {
1068                continue;
1069            };
1070
1071            match *ty.kind() {
1072                TypeKind::Comp(..) |
1073                TypeKind::TemplateAlias(..) |
1074                TypeKind::Enum(..) |
1075                TypeKind::Alias(..) => {}
1076                _ => continue,
1077            }
1078
1079            let path = item.path_for_allowlisting(self);
1080            let replacement = self.replacements.get(&path[1..]);
1081
1082            if let Some(replacement) = replacement {
1083                if *replacement != id {
1084                    // We set this just after parsing the annotation. It's
1085                    // very unlikely, but this can happen.
1086                    if self.resolve_item_fallible(*replacement).is_some() {
1087                        replacements.push((
1088                            id.expect_type_id(self),
1089                            replacement.expect_type_id(self),
1090                        ));
1091                    }
1092                }
1093            }
1094        }
1095
1096        for (id, replacement_id) in replacements {
1097            debug!("Replacing {id:?} with {replacement_id:?}");
1098            let new_parent = {
1099                let item_id: ItemId = id.into();
1100                let item = self.items[item_id.0].as_mut().unwrap();
1101                *item.kind_mut().as_type_mut().unwrap().kind_mut() =
1102                    TypeKind::ResolvedTypeRef(replacement_id);
1103                item.parent_id()
1104            };
1105
1106            // Relocate the replacement item from where it was declared, to
1107            // where the thing it is replacing was declared.
1108            //
1109            // First, we'll make sure that its parent ID is correct.
1110
1111            let old_parent = self.resolve_item(replacement_id).parent_id();
1112            if new_parent == old_parent {
1113                // Same parent and therefore also same containing
1114                // module. Nothing to do here.
1115                continue;
1116            }
1117
1118            let replacement_item_id: ItemId = replacement_id.into();
1119            self.items[replacement_item_id.0]
1120                .as_mut()
1121                .unwrap()
1122                .set_parent_for_replacement(new_parent);
1123
1124            // Second, make sure that it is in the correct module's children
1125            // set.
1126
1127            let old_module = {
1128                let immut_self = &*self;
1129                old_parent
1130                    .ancestors(immut_self)
1131                    .chain(Some(immut_self.root_module.into()))
1132                    .find(|id| {
1133                        let item = immut_self.resolve_item(*id);
1134                        item.as_module().is_some_and(|m| {
1135                            m.children().contains(&replacement_id.into())
1136                        })
1137                    })
1138            };
1139            let old_module = old_module
1140                .expect("Every replacement item should be in a module");
1141
1142            let new_module = {
1143                let immut_self = &*self;
1144                new_parent
1145                    .ancestors(immut_self)
1146                    .find(|id| immut_self.resolve_item(*id).is_module())
1147            };
1148            let new_module =
1149                new_module.unwrap_or_else(|| self.root_module.into());
1150
1151            if new_module == old_module {
1152                // Already in the correct module.
1153                continue;
1154            }
1155
1156            self.items[old_module.0]
1157                .as_mut()
1158                .unwrap()
1159                .as_module_mut()
1160                .unwrap()
1161                .children_mut()
1162                .remove(&replacement_id.into());
1163
1164            self.items[new_module.0]
1165                .as_mut()
1166                .unwrap()
1167                .as_module_mut()
1168                .unwrap()
1169                .children_mut()
1170                .insert(replacement_id.into());
1171        }
1172    }
1173
1174    /// Enter the code generation phase, invoke the given callback `cb`, and
1175    /// leave the code generation phase.
1176    pub(crate) fn gen<F, Out>(
1177        mut self,
1178        cb: F,
1179    ) -> Result<(Out, BindgenOptions), CodegenError>
1180    where
1181        F: FnOnce(&Self) -> Result<Out, CodegenError>,
1182    {
1183        self.in_codegen = true;
1184
1185        self.resolve_typerefs();
1186        self.compute_bitfield_units();
1187        self.process_replacements();
1188
1189        self.deanonymize_fields();
1190
1191        self.assert_no_dangling_references();
1192
1193        // Compute the allowlisted set after processing replacements and
1194        // resolving type refs, as those are the final mutations of the IR
1195        // graph, and their completion means that the IR graph is now frozen.
1196        self.compute_allowlisted_and_codegen_items();
1197
1198        // Make sure to do this after processing replacements, since that messes
1199        // with the parentage and module children, and we want to assert that it
1200        // messes with them correctly.
1201        self.assert_every_item_in_a_module();
1202
1203        self.compute_has_vtable();
1204        self.compute_sizedness();
1205        self.compute_has_destructor();
1206        self.find_used_template_parameters();
1207        self.compute_enum_typedef_combos();
1208        self.compute_cannot_derive_debug();
1209        self.compute_cannot_derive_default();
1210        self.compute_cannot_derive_copy();
1211        self.compute_has_type_param_in_array();
1212        self.compute_has_float();
1213        self.compute_cannot_derive_hash();
1214        self.compute_cannot_derive_partialord_partialeq_or_eq();
1215
1216        let ret = cb(&self)?;
1217        Ok((ret, self.options))
1218    }
1219
1220    /// When the `__testing_only_extra_assertions` feature is enabled, this
1221    /// function walks the IR graph and asserts that we do not have any edges
1222    /// referencing an `ItemId` for which we do not have an associated IR item.
1223    fn assert_no_dangling_references(&self) {
1224        if cfg!(feature = "__testing_only_extra_assertions") {
1225            for _ in self.assert_no_dangling_item_traversal() {
1226                // The iterator's next method does the asserting for us.
1227            }
1228        }
1229    }
1230
1231    fn assert_no_dangling_item_traversal(
1232        &self,
1233    ) -> traversal::AssertNoDanglingItemsTraversal {
1234        assert!(self.in_codegen_phase());
1235        assert!(self.current_module == self.root_module);
1236
1237        let roots = self.items().map(|(id, _)| id);
1238        traversal::AssertNoDanglingItemsTraversal::new(
1239            self,
1240            roots,
1241            traversal::all_edges,
1242        )
1243    }
1244
1245    /// When the `__testing_only_extra_assertions` feature is enabled, walk over
1246    /// every item and ensure that it is in the children set of one of its
1247    /// module ancestors.
1248    fn assert_every_item_in_a_module(&self) {
1249        if cfg!(feature = "__testing_only_extra_assertions") {
1250            assert!(self.in_codegen_phase());
1251            assert!(self.current_module == self.root_module);
1252
1253            for (id, _item) in self.items() {
1254                if id == self.root_module {
1255                    continue;
1256                }
1257
1258                assert!(
1259                    {
1260                        let id = id
1261                            .into_resolver()
1262                            .through_type_refs()
1263                            .through_type_aliases()
1264                            .resolve(self)
1265                            .id();
1266                        id.ancestors(self)
1267                            .chain(Some(self.root_module.into()))
1268                            .any(|ancestor| {
1269                                debug!("Checking if {id:?} is a child of {ancestor:?}");
1270                                self.resolve_item(ancestor)
1271                                    .as_module()
1272                                    .is_some_and(|m| m.children().contains(&id))
1273                            })
1274                    },
1275                    "{id:?} should be in some ancestor module's children set"
1276                );
1277            }
1278        }
1279    }
1280
1281    /// Compute for every type whether it is sized or not, and whether it is
1282    /// sized or not as a base class.
1283    fn compute_sizedness(&mut self) {
1284        let _t = self.timer("compute_sizedness");
1285        assert!(self.sizedness.is_none());
1286        self.sizedness = Some(analyze::<SizednessAnalysis>(self));
1287    }
1288
1289    /// Look up whether the type with the given ID is sized or not.
1290    pub(crate) fn lookup_sizedness(&self, id: TypeId) -> SizednessResult {
1291        assert!(
1292            self.in_codegen_phase(),
1293            "We only compute sizedness after we've entered codegen"
1294        );
1295
1296        self.sizedness
1297            .as_ref()
1298            .unwrap()
1299            .get(&id)
1300            .copied()
1301            .unwrap_or(SizednessResult::ZeroSized)
1302    }
1303
1304    /// Compute whether the type has vtable.
1305    fn compute_has_vtable(&mut self) {
1306        let _t = self.timer("compute_has_vtable");
1307        assert!(self.have_vtable.is_none());
1308        self.have_vtable = Some(analyze::<HasVtableAnalysis>(self));
1309    }
1310
1311    /// Look up whether the item with `id` has vtable or not.
1312    pub(crate) fn lookup_has_vtable(&self, id: TypeId) -> HasVtableResult {
1313        assert!(
1314            self.in_codegen_phase(),
1315            "We only compute vtables when we enter codegen"
1316        );
1317
1318        // Look up the computed value for whether the item with `id` has a
1319        // vtable or not.
1320        self.have_vtable
1321            .as_ref()
1322            .unwrap()
1323            .get(&id.into())
1324            .copied()
1325            .unwrap_or(HasVtableResult::No)
1326    }
1327
1328    /// Compute whether the type has a destructor.
1329    fn compute_has_destructor(&mut self) {
1330        let _t = self.timer("compute_has_destructor");
1331        assert!(self.have_destructor.is_none());
1332        self.have_destructor = Some(analyze::<HasDestructorAnalysis>(self));
1333    }
1334
1335    /// Look up whether the item with `id` has a destructor.
1336    pub(crate) fn lookup_has_destructor(&self, id: TypeId) -> bool {
1337        assert!(
1338            self.in_codegen_phase(),
1339            "We only compute destructors when we enter codegen"
1340        );
1341
1342        self.have_destructor.as_ref().unwrap().contains(&id.into())
1343    }
1344
1345    fn find_used_template_parameters(&mut self) {
1346        let _t = self.timer("find_used_template_parameters");
1347        if self.options.allowlist_recursively {
1348            let used_params = analyze::<UsedTemplateParameters>(self);
1349            self.used_template_parameters = Some(used_params);
1350        } else {
1351            // If you aren't recursively allowlisting, then we can't really make
1352            // any sense of template parameter usage, and you're on your own.
1353            let mut used_params = HashMap::default();
1354            for &id in self.allowlisted_items() {
1355                used_params.entry(id).or_insert_with(|| {
1356                    id.self_template_params(self)
1357                        .into_iter()
1358                        .map(|p| p.into())
1359                        .collect()
1360                });
1361            }
1362            self.used_template_parameters = Some(used_params);
1363        }
1364    }
1365
1366    /// Return `true` if `item` uses the given `template_param`, `false`
1367    /// otherwise.
1368    ///
1369    /// This method may only be called during the codegen phase, because the
1370    /// template usage information is only computed as we enter the codegen
1371    /// phase.
1372    ///
1373    /// If the item is blocklisted, then we say that it always uses the template
1374    /// parameter. This is a little subtle. The template parameter usage
1375    /// analysis only considers allowlisted items, and if any blocklisted item
1376    /// shows up in the generated bindings, it is the user's responsibility to
1377    /// manually provide a definition for them. To give them the most
1378    /// flexibility when doing that, we assume that they use every template
1379    /// parameter and always pass template arguments through in instantiations.
1380    pub(crate) fn uses_template_parameter(
1381        &self,
1382        item: ItemId,
1383        template_param: TypeId,
1384    ) -> bool {
1385        assert!(
1386            self.in_codegen_phase(),
1387            "We only compute template parameter usage as we enter codegen"
1388        );
1389
1390        if self.resolve_item(item).is_blocklisted(self) {
1391            return true;
1392        }
1393
1394        let template_param = template_param
1395            .into_resolver()
1396            .through_type_refs()
1397            .through_type_aliases()
1398            .resolve(self)
1399            .id();
1400
1401        self.used_template_parameters
1402            .as_ref()
1403            .expect("should have found template parameter usage if we're in codegen")
1404            .get(&item).is_some_and(|items_used_params| items_used_params.contains(&template_param))
1405    }
1406
1407    /// Return `true` if `item` uses any unbound, generic template parameters,
1408    /// `false` otherwise.
1409    ///
1410    /// Has the same restrictions that `uses_template_parameter` has.
1411    pub(crate) fn uses_any_template_parameters(&self, item: ItemId) -> bool {
1412        assert!(
1413            self.in_codegen_phase(),
1414            "We only compute template parameter usage as we enter codegen"
1415        );
1416
1417        self.used_template_parameters
1418            .as_ref()
1419            .expect(
1420                "should have template parameter usage info in codegen phase",
1421            )
1422            .get(&item)
1423            .is_some_and(|used| !used.is_empty())
1424    }
1425
1426    // This deserves a comment. Builtin types don't get a valid declaration, so
1427    // we can't add it to the cursor->type map.
1428    //
1429    // That being said, they're not generated anyway, and are few, so the
1430    // duplication and special-casing is fine.
1431    //
1432    // If at some point we care about the memory here, probably a map TypeKind
1433    // -> builtin type ItemId would be the best to improve that.
1434    fn add_builtin_item(&mut self, item: Item) {
1435        debug!("add_builtin_item: item = {item:?}");
1436        debug_assert!(item.kind().is_type());
1437        self.add_item_to_module(&item);
1438        let id = item.id();
1439        let old_item = mem::replace(&mut self.items[id.0], Some(item));
1440        assert!(old_item.is_none(), "Inserted type twice?");
1441    }
1442
1443    fn build_root_module(id: ItemId) -> Item {
1444        let module = Module::new(Some("root".into()), ModuleKind::Normal);
1445        Item::new(id, None, None, id, ItemKind::Module(module), None)
1446    }
1447
1448    /// Get the root module.
1449    pub(crate) fn root_module(&self) -> ModuleId {
1450        self.root_module
1451    }
1452
1453    /// Resolve a type with the given ID.
1454    ///
1455    /// Panics if there is no item for the given `TypeId` or if the resolved
1456    /// item is not a `Type`.
1457    pub(crate) fn resolve_type(&self, type_id: TypeId) -> &Type {
1458        self.resolve_item(type_id).kind().expect_type()
1459    }
1460
1461    /// Resolve a function with the given ID.
1462    ///
1463    /// Panics if there is no item for the given `FunctionId` or if the resolved
1464    /// item is not a `Function`.
1465    pub(crate) fn resolve_func(&self, func_id: FunctionId) -> &Function {
1466        self.resolve_item(func_id).kind().expect_function()
1467    }
1468
1469    /// Resolve the given `ItemId` as a type, or `None` if there is no item with
1470    /// the given ID.
1471    ///
1472    /// Panics if the ID resolves to an item that is not a type.
1473    pub(crate) fn safe_resolve_type(&self, type_id: TypeId) -> Option<&Type> {
1474        self.resolve_item_fallible(type_id)
1475            .map(|t| t.kind().expect_type())
1476    }
1477
1478    /// Resolve the given `ItemId` into an `Item`, or `None` if no such item
1479    /// exists.
1480    pub(crate) fn resolve_item_fallible<Id: Into<ItemId>>(
1481        &self,
1482        id: Id,
1483    ) -> Option<&Item> {
1484        self.items.get(id.into().0)?.as_ref()
1485    }
1486
1487    /// Resolve the given `ItemId` into an `Item`.
1488    ///
1489    /// Panics if the given ID does not resolve to any item.
1490    pub(crate) fn resolve_item<Id: Into<ItemId>>(&self, item_id: Id) -> &Item {
1491        let item_id = item_id.into();
1492        match self.resolve_item_fallible(item_id) {
1493            Some(item) => item,
1494            None => panic!("Not an item: {item_id:?}"),
1495        }
1496    }
1497
1498    /// Get the current module.
1499    pub(crate) fn current_module(&self) -> ModuleId {
1500        self.current_module
1501    }
1502
1503    /// Add a semantic parent for a given type definition.
1504    ///
1505    /// We do this from the type declaration, in order to be able to find the
1506    /// correct type definition afterwards.
1507    ///
1508    /// TODO(emilio): We could consider doing this only when
1509    /// `declaration.lexical_parent() != definition.lexical_parent()`, but it's
1510    /// not sure it's worth it.
1511    pub(crate) fn add_semantic_parent(
1512        &mut self,
1513        definition: Cursor,
1514        parent_id: ItemId,
1515    ) {
1516        self.semantic_parents.insert(definition, parent_id);
1517    }
1518
1519    /// Returns a known semantic parent for a given definition.
1520    pub(crate) fn known_semantic_parent(
1521        &self,
1522        definition: Cursor,
1523    ) -> Option<ItemId> {
1524        self.semantic_parents.get(&definition).copied()
1525    }
1526
1527    /// Given a cursor pointing to the location of a template instantiation,
1528    /// return a tuple of the form `(declaration_cursor, declaration_id,
1529    /// num_expected_template_args)`.
1530    ///
1531    /// Note that `declaration_id` is not guaranteed to be in the context's item
1532    /// set! It is possible that it is a partial type that we are still in the
1533    /// middle of parsing.
1534    fn get_declaration_info_for_template_instantiation(
1535        &self,
1536        instantiation: &Cursor,
1537    ) -> Option<(Cursor, ItemId, usize)> {
1538        instantiation
1539            .cur_type()
1540            .canonical_declaration(Some(instantiation))
1541            .and_then(|canon_decl| {
1542                self.get_resolved_type(&canon_decl).and_then(
1543                    |template_decl_id| {
1544                        let num_params =
1545                            template_decl_id.num_self_template_params(self);
1546                        if num_params == 0 {
1547                            None
1548                        } else {
1549                            Some((
1550                                *canon_decl.cursor(),
1551                                template_decl_id.into(),
1552                                num_params,
1553                            ))
1554                        }
1555                    },
1556                )
1557            })
1558            .or_else(|| {
1559                // If we haven't already parsed the declaration of
1560                // the template being instantiated, then it *must*
1561                // be on the stack of types we are currently
1562                // parsing. If it wasn't then clang would have
1563                // already errored out before we started
1564                // constructing our IR because you can't instantiate
1565                // a template until it is fully defined.
1566                instantiation
1567                    .referenced()
1568                    .and_then(|referenced| {
1569                        self.currently_parsed_types()
1570                            .iter()
1571                            .find(|partial_ty| *partial_ty.decl() == referenced)
1572                    })
1573                    .and_then(|template_decl| {
1574                        let num_template_params =
1575                            template_decl.num_self_template_params(self);
1576                        if num_template_params == 0 {
1577                            None
1578                        } else {
1579                            Some((
1580                                *template_decl.decl(),
1581                                template_decl.id(),
1582                                num_template_params,
1583                            ))
1584                        }
1585                    })
1586            })
1587    }
1588
1589    /// Parse a template instantiation, eg `Foo<int>`.
1590    ///
1591    /// This is surprisingly difficult to do with libclang, due to the fact that
1592    /// it doesn't provide explicit template argument information, except for
1593    /// function template declarations(!?!??!).
1594    ///
1595    /// The only way to do this is manually inspecting the AST and looking for
1596    /// `TypeRefs` and `TemplateRefs` inside. This, unfortunately, doesn't work for
1597    /// more complex cases, see the comment on the assertion below.
1598    ///
1599    /// To add insult to injury, the AST itself has structure that doesn't make
1600    /// sense. Sometimes `Foo<Bar<int>>` has an AST with nesting like you might
1601    /// expect: `(Foo (Bar (int)))`. Other times, the AST we get is completely
1602    /// flat: `(Foo Bar int)`.
1603    ///
1604    /// To see an example of what this method handles:
1605    ///
1606    /// ```c++
1607    /// template<typename T>
1608    /// class Incomplete {
1609    ///   T p;
1610    /// };
1611    ///
1612    /// template<typename U>
1613    /// class Foo {
1614    ///   Incomplete<U> bar;
1615    /// };
1616    /// ```
1617    ///
1618    /// Finally, template instantiations are always children of the current
1619    /// module. They use their template's definition for their name, so the
1620    /// parent is only useful for ensuring that their layout tests get
1621    /// codegen'd.
1622    fn instantiate_template(
1623        &mut self,
1624        with_id: ItemId,
1625        template: TypeId,
1626        ty: &clang::Type,
1627        location: Cursor,
1628    ) -> Option<TypeId> {
1629        let num_expected_args =
1630            self.resolve_type(template).num_self_template_params(self);
1631        if num_expected_args == 0 {
1632            warn!(
1633                "Tried to instantiate a template for which we could not \
1634                 determine any template parameters"
1635            );
1636            return None;
1637        }
1638
1639        let mut args = vec![];
1640        let mut found_const_arg = false;
1641        let mut children = location.collect_children();
1642
1643        if children.iter().all(|c| !c.has_children()) {
1644            // This is insanity... If clang isn't giving us a properly nested
1645            // AST for which template arguments belong to which template we are
1646            // instantiating, we'll need to construct it ourselves. However,
1647            // there is an extra `NamespaceRef, NamespaceRef, ..., TemplateRef`
1648            // representing a reference to the outermost template declaration
1649            // that we need to filter out of the children. We need to do this
1650            // filtering because we already know which template declaration is
1651            // being specialized via the `location`'s type, and if we do not
1652            // filter it out, we'll add an extra layer of template instantiation
1653            // on accident.
1654            let idx = children
1655                .iter()
1656                .position(|c| c.kind() == clang_sys::CXCursor_TemplateRef);
1657            if let Some(idx) = idx {
1658                if children
1659                    .iter()
1660                    .take(idx)
1661                    .all(|c| c.kind() == clang_sys::CXCursor_NamespaceRef)
1662                {
1663                    children = children.into_iter().skip(idx + 1).collect();
1664                }
1665            }
1666        }
1667
1668        for child in children.iter().rev() {
1669            match child.kind() {
1670                clang_sys::CXCursor_TypeRef |
1671                clang_sys::CXCursor_TypedefDecl |
1672                clang_sys::CXCursor_TypeAliasDecl => {
1673                    // The `with_id` ID will potentially end up unused if we give up
1674                    // on this type (for example, because it has const value
1675                    // template args), so if we pass `with_id` as the parent, it is
1676                    // potentially a dangling reference. Instead, use the canonical
1677                    // template declaration as the parent. It is already parsed and
1678                    // has a known-resolvable `ItemId`.
1679                    let ty = Item::from_ty_or_ref(
1680                        child.cur_type(),
1681                        *child,
1682                        Some(template.into()),
1683                        self,
1684                    );
1685                    args.push(ty);
1686                }
1687                clang_sys::CXCursor_TemplateRef => {
1688                    let (
1689                        template_decl_cursor,
1690                        template_decl_id,
1691                        num_expected_template_args,
1692                    ) = self.get_declaration_info_for_template_instantiation(
1693                        child,
1694                    )?;
1695
1696                    if num_expected_template_args == 0 ||
1697                        child.has_at_least_num_children(
1698                            num_expected_template_args,
1699                        )
1700                    {
1701                        // Do a happy little parse. See comment in the TypeRef
1702                        // match arm about parent IDs.
1703                        let ty = Item::from_ty_or_ref(
1704                            child.cur_type(),
1705                            *child,
1706                            Some(template.into()),
1707                            self,
1708                        );
1709                        args.push(ty);
1710                    } else {
1711                        // This is the case mentioned in the doc comment where
1712                        // clang gives us a flattened AST and we have to
1713                        // reconstruct which template arguments go to which
1714                        // instantiation :(
1715                        let args_len = args.len();
1716                        if args_len < num_expected_template_args {
1717                            warn!(
1718                                "Found a template instantiation without \
1719                                 enough template arguments"
1720                            );
1721                            return None;
1722                        }
1723
1724                        let mut sub_args: Vec<_> = args
1725                            .drain(args_len - num_expected_template_args..)
1726                            .collect();
1727                        sub_args.reverse();
1728
1729                        let sub_name = Some(template_decl_cursor.spelling());
1730                        let sub_inst = TemplateInstantiation::new(
1731                            // This isn't guaranteed to be a type that we've
1732                            // already finished parsing yet.
1733                            template_decl_id.as_type_id_unchecked(),
1734                            sub_args,
1735                        );
1736                        let sub_kind =
1737                            TypeKind::TemplateInstantiation(sub_inst);
1738                        let sub_ty = Type::new(
1739                            sub_name,
1740                            template_decl_cursor
1741                                .cur_type()
1742                                .fallible_layout(self)
1743                                .ok(),
1744                            sub_kind,
1745                            false,
1746                        );
1747                        let sub_id = self.next_item_id();
1748                        let sub_item = Item::new(
1749                            sub_id,
1750                            None,
1751                            None,
1752                            self.current_module.into(),
1753                            ItemKind::Type(sub_ty),
1754                            Some(child.location()),
1755                        );
1756
1757                        // Bypass all the validations in add_item explicitly.
1758                        debug!(
1759                            "instantiate_template: inserting nested \
1760                             instantiation item: {:?}",
1761                            sub_item
1762                        );
1763                        self.add_item_to_module(&sub_item);
1764                        debug_assert_eq!(sub_id, sub_item.id());
1765                        self.items[sub_id.0] = Some(sub_item);
1766                        args.push(sub_id.as_type_id_unchecked());
1767                    }
1768                }
1769                _ => {
1770                    warn!(
1771                        "Found template arg cursor we can't handle: {child:?}"
1772                    );
1773                    found_const_arg = true;
1774                }
1775            }
1776        }
1777
1778        if found_const_arg {
1779            // This is a dependently typed template instantiation. That is, an
1780            // instantiation of a template with one or more const values as
1781            // template arguments, rather than only types as template
1782            // arguments. For example, `Foo<true, 5>` versus `Bar<bool, int>`.
1783            // We can't handle these instantiations, so just punt in this
1784            // situation...
1785            warn!(
1786                "Found template instantiated with a const value; \
1787                 bindgen can't handle this kind of template instantiation!"
1788            );
1789            return None;
1790        }
1791
1792        if args.len() != num_expected_args {
1793            warn!(
1794                "Found a template with an unexpected number of template \
1795                 arguments"
1796            );
1797            return None;
1798        }
1799
1800        args.reverse();
1801        let type_kind = TypeKind::TemplateInstantiation(
1802            TemplateInstantiation::new(template, args),
1803        );
1804        let name = ty.spelling();
1805        let name = if name.is_empty() { None } else { Some(name) };
1806        let ty = Type::new(
1807            name,
1808            ty.fallible_layout(self).ok(),
1809            type_kind,
1810            ty.is_const(),
1811        );
1812        let item = Item::new(
1813            with_id,
1814            None,
1815            None,
1816            self.current_module.into(),
1817            ItemKind::Type(ty),
1818            Some(location.location()),
1819        );
1820
1821        // Bypass all the validations in add_item explicitly.
1822        debug!("instantiate_template: inserting item: {item:?}");
1823        self.add_item_to_module(&item);
1824        debug_assert_eq!(with_id, item.id());
1825        self.items[with_id.0] = Some(item);
1826        Some(with_id.as_type_id_unchecked())
1827    }
1828
1829    /// If we have already resolved the type for the given type declaration,
1830    /// return its `ItemId`. Otherwise, return `None`.
1831    pub(crate) fn get_resolved_type(
1832        &self,
1833        decl: &clang::CanonicalTypeDeclaration,
1834    ) -> Option<TypeId> {
1835        self.types
1836            .get(&TypeKey::Declaration(*decl.cursor()))
1837            .or_else(|| {
1838                decl.cursor()
1839                    .usr()
1840                    .and_then(|usr| self.types.get(&TypeKey::Usr(usr)))
1841            })
1842            .copied()
1843    }
1844
1845    /// Looks up for an already resolved type, either because it's builtin, or
1846    /// because we already have it in the map.
1847    pub(crate) fn builtin_or_resolved_ty(
1848        &mut self,
1849        with_id: ItemId,
1850        parent_id: Option<ItemId>,
1851        ty: &clang::Type,
1852        location: Option<Cursor>,
1853    ) -> Option<TypeId> {
1854        use clang_sys::{CXCursor_TypeAliasTemplateDecl, CXCursor_TypeRef};
1855        debug!("builtin_or_resolved_ty: {ty:?}, {location:?}, {with_id:?}, {parent_id:?}");
1856
1857        if let Some(decl) = ty.canonical_declaration(location.as_ref()) {
1858            if let Some(id) = self.get_resolved_type(&decl) {
1859                debug!(
1860                    "Already resolved ty {id:?}, {decl:?}, {ty:?} {location:?}"
1861                );
1862                // If the declaration already exists, then either:
1863                //
1864                //   * the declaration is a template declaration of some sort,
1865                //     and we are looking at an instantiation or specialization
1866                //     of it, or
1867                //   * we have already parsed and resolved this type, and
1868                //     there's nothing left to do.
1869                if let Some(location) = location {
1870                    if decl.cursor().is_template_like() &&
1871                        *ty != decl.cursor().cur_type()
1872                    {
1873                        // For specialized type aliases, there's no way to get the
1874                        // template parameters as of this writing (for a struct
1875                        // specialization we wouldn't be in this branch anyway).
1876                        //
1877                        // Explicitly return `None` if there aren't any
1878                        // unspecialized parameters (contains any `TypeRef`) so we
1879                        // resolve the canonical type if there is one and it's
1880                        // exposed.
1881                        //
1882                        // This is _tricky_, I know :(
1883                        if decl.cursor().kind() ==
1884                            CXCursor_TypeAliasTemplateDecl &&
1885                            !location.contains_cursor(CXCursor_TypeRef) &&
1886                            ty.canonical_type().is_valid_and_exposed()
1887                        {
1888                            return None;
1889                        }
1890
1891                        return self
1892                            .instantiate_template(with_id, id, ty, location)
1893                            .or(Some(id));
1894                    }
1895                }
1896
1897                return Some(self.build_ty_wrapper(with_id, id, parent_id, ty));
1898            }
1899        }
1900
1901        debug!("Not resolved, maybe builtin?");
1902        self.build_builtin_ty(ty)
1903    }
1904
1905    /// Make a new item that is a resolved type reference to the `wrapped_id`.
1906    ///
1907    /// This is unfortunately a lot of bloat, but is needed to properly track
1908    /// constness et al.
1909    ///
1910    /// We should probably make the constness tracking separate, so it doesn't
1911    /// bloat that much, but hey, we already bloat the heck out of builtin
1912    /// types.
1913    pub(crate) fn build_ty_wrapper(
1914        &mut self,
1915        with_id: ItemId,
1916        wrapped_id: TypeId,
1917        parent_id: Option<ItemId>,
1918        ty: &clang::Type,
1919    ) -> TypeId {
1920        self.build_wrapper(with_id, wrapped_id, parent_id, ty, ty.is_const())
1921    }
1922
1923    /// A wrapper over a type that adds a const qualifier explicitly.
1924    ///
1925    /// Needed to handle const methods in C++, wrapping the type .
1926    pub(crate) fn build_const_wrapper(
1927        &mut self,
1928        with_id: ItemId,
1929        wrapped_id: TypeId,
1930        parent_id: Option<ItemId>,
1931        ty: &clang::Type,
1932    ) -> TypeId {
1933        self.build_wrapper(
1934            with_id, wrapped_id, parent_id, ty, /* is_const = */ true,
1935        )
1936    }
1937
1938    fn build_wrapper(
1939        &mut self,
1940        with_id: ItemId,
1941        wrapped_id: TypeId,
1942        parent_id: Option<ItemId>,
1943        ty: &clang::Type,
1944        is_const: bool,
1945    ) -> TypeId {
1946        let spelling = ty.spelling();
1947        let layout = ty.fallible_layout(self).ok();
1948        let location = ty.declaration().location();
1949        let type_kind = TypeKind::ResolvedTypeRef(wrapped_id);
1950        let ty = Type::new(Some(spelling), layout, type_kind, is_const);
1951        let item = Item::new(
1952            with_id,
1953            None,
1954            None,
1955            parent_id.unwrap_or_else(|| self.current_module.into()),
1956            ItemKind::Type(ty),
1957            Some(location),
1958        );
1959        self.add_builtin_item(item);
1960        with_id.as_type_id_unchecked()
1961    }
1962
1963    /// Returns the next item ID to be used for an item.
1964    pub(crate) fn next_item_id(&mut self) -> ItemId {
1965        let ret = ItemId(self.items.len());
1966        self.items.push(None);
1967        ret
1968    }
1969
1970    fn build_builtin_ty(&mut self, ty: &clang::Type) -> Option<TypeId> {
1971        use clang_sys::*;
1972        let type_kind = match ty.kind() {
1973            CXType_NullPtr => TypeKind::NullPtr,
1974            CXType_Void => TypeKind::Void,
1975            CXType_Bool => TypeKind::Int(IntKind::Bool),
1976            CXType_Int => TypeKind::Int(IntKind::Int),
1977            CXType_UInt => TypeKind::Int(IntKind::UInt),
1978            CXType_Char_S => TypeKind::Int(IntKind::Char { is_signed: true }),
1979            CXType_Char_U => TypeKind::Int(IntKind::Char { is_signed: false }),
1980            CXType_SChar => TypeKind::Int(IntKind::SChar),
1981            CXType_UChar => TypeKind::Int(IntKind::UChar),
1982            CXType_Short => TypeKind::Int(IntKind::Short),
1983            CXType_UShort => TypeKind::Int(IntKind::UShort),
1984            CXType_WChar => TypeKind::Int(IntKind::WChar),
1985            CXType_Char16 => TypeKind::Int(IntKind::U16),
1986            CXType_Char32 => TypeKind::Int(IntKind::U32),
1987            CXType_Long => TypeKind::Int(IntKind::Long),
1988            CXType_ULong => TypeKind::Int(IntKind::ULong),
1989            CXType_LongLong => TypeKind::Int(IntKind::LongLong),
1990            CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
1991            CXType_Int128 => TypeKind::Int(IntKind::I128),
1992            CXType_UInt128 => TypeKind::Int(IntKind::U128),
1993            CXType_Float16 | CXType_Half => TypeKind::Float(FloatKind::Float16),
1994            CXType_Float => TypeKind::Float(FloatKind::Float),
1995            CXType_Double => TypeKind::Float(FloatKind::Double),
1996            CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
1997            CXType_Float128 => TypeKind::Float(FloatKind::Float128),
1998            CXType_Complex => {
1999                let float_type =
2000                    ty.elem_type().expect("Not able to resolve complex type?");
2001                let float_kind = match float_type.kind() {
2002                    CXType_Float16 | CXType_Half => FloatKind::Float16,
2003                    CXType_Float => FloatKind::Float,
2004                    CXType_Double => FloatKind::Double,
2005                    CXType_LongDouble => FloatKind::LongDouble,
2006                    CXType_Float128 => FloatKind::Float128,
2007                    _ => panic!(
2008                        "Non floating-type complex? {ty:?}, {float_type:?}",
2009                    ),
2010                };
2011                TypeKind::Complex(float_kind)
2012            }
2013            _ => return None,
2014        };
2015
2016        let spelling = ty.spelling();
2017        let is_const = ty.is_const();
2018        let layout = ty.fallible_layout(self).ok();
2019        let location = ty.declaration().location();
2020        let ty = Type::new(Some(spelling), layout, type_kind, is_const);
2021        let id = self.next_item_id();
2022        let item = Item::new(
2023            id,
2024            None,
2025            None,
2026            self.root_module.into(),
2027            ItemKind::Type(ty),
2028            Some(location),
2029        );
2030        self.add_builtin_item(item);
2031        Some(id.as_type_id_unchecked())
2032    }
2033
2034    /// Get the current Clang translation unit that is being processed.
2035    pub(crate) fn translation_unit(&self) -> &clang::TranslationUnit {
2036        &self.translation_unit
2037    }
2038
2039    /// Initialize fallback translation unit if it does not exist and
2040    /// then return a mutable reference to the fallback translation unit.
2041    pub(crate) fn try_ensure_fallback_translation_unit(
2042        &mut self,
2043    ) -> Option<&mut clang::FallbackTranslationUnit> {
2044        if self.fallback_tu.is_none() {
2045            let file = format!(
2046                "{}/.macro_eval.c",
2047                match self.options().clang_macro_fallback_build_dir {
2048                    Some(ref path) => path.as_os_str().to_str()?,
2049                    None => ".",
2050                }
2051            );
2052
2053            let index = clang::Index::new(false, false);
2054
2055            let mut header_names_to_compile = Vec::new();
2056            let mut header_paths = Vec::new();
2057            let mut header_contents = String::new();
2058            for input_header in &self.options.input_headers {
2059                let path = Path::new(input_header.as_ref());
2060                if let Some(header_path) = path.parent() {
2061                    if header_path == Path::new("") {
2062                        header_paths.push(".");
2063                    } else {
2064                        header_paths.push(header_path.as_os_str().to_str()?);
2065                    }
2066                } else {
2067                    header_paths.push(".");
2068                }
2069                let header_name = path.file_name()?.to_str()?;
2070                header_names_to_compile
2071                    .push(header_name.split(".h").next()?.to_string());
2072                header_contents +=
2073                    format!("\n#include <{header_name}>").as_str();
2074            }
2075            let header_to_precompile = format!(
2076                "{}/{}",
2077                match self.options().clang_macro_fallback_build_dir {
2078                    Some(ref path) => path.as_os_str().to_str()?,
2079                    None => ".",
2080                },
2081                header_names_to_compile.join("-") + "-precompile.h"
2082            );
2083            let pch = header_to_precompile.clone() + ".pch";
2084
2085            let mut header_to_precompile_file = OpenOptions::new()
2086                .create(true)
2087                .truncate(true)
2088                .write(true)
2089                .open(&header_to_precompile)
2090                .ok()?;
2091            header_to_precompile_file
2092                .write_all(header_contents.as_bytes())
2093                .ok()?;
2094
2095            let mut c_args = Vec::new();
2096            c_args.push("-x".to_string().into_boxed_str());
2097            c_args.push("c-header".to_string().into_boxed_str());
2098            for header_path in header_paths {
2099                c_args.push(format!("-I{header_path}").into_boxed_str());
2100            }
2101            c_args.extend(
2102                self.options
2103                    .clang_args
2104                    .iter()
2105                    .filter(|next| {
2106                        !self.options.input_headers.contains(next) &&
2107                            next.as_ref() != "-include"
2108                    })
2109                    .cloned(),
2110            );
2111            let mut tu = clang::TranslationUnit::parse(
2112                &index,
2113                &header_to_precompile,
2114                &c_args,
2115                &[],
2116                clang_sys::CXTranslationUnit_ForSerialization,
2117            )?;
2118            tu.save(&pch).ok()?;
2119
2120            let mut c_args = vec![
2121                "-include-pch".to_string().into_boxed_str(),
2122                pch.clone().into_boxed_str(),
2123            ];
2124            c_args.extend(
2125                self.options
2126                    .clang_args
2127                    .clone()
2128                    .iter()
2129                    .filter(|next| {
2130                        !self.options.input_headers.contains(next) &&
2131                            next.as_ref() != "-include"
2132                    })
2133                    .cloned(),
2134            );
2135            self.fallback_tu = Some(clang::FallbackTranslationUnit::new(
2136                file,
2137                header_to_precompile,
2138                pch,
2139                &c_args,
2140            )?);
2141        }
2142
2143        self.fallback_tu.as_mut()
2144    }
2145
2146    /// Have we parsed the macro named `macro_name` already?
2147    pub(crate) fn parsed_macro(&self, macro_name: &[u8]) -> bool {
2148        self.parsed_macros.contains_key(macro_name)
2149    }
2150
2151    /// Get the currently parsed macros.
2152    pub(crate) fn parsed_macros(
2153        &self,
2154    ) -> &StdHashMap<Vec<u8>, cexpr::expr::EvalResult> {
2155        debug_assert!(!self.in_codegen_phase());
2156        &self.parsed_macros
2157    }
2158
2159    /// Mark the macro named `macro_name` as parsed.
2160    pub(crate) fn note_parsed_macro(
2161        &mut self,
2162        id: Vec<u8>,
2163        value: cexpr::expr::EvalResult,
2164    ) {
2165        self.parsed_macros.insert(id, value);
2166    }
2167
2168    /// Are we in the codegen phase?
2169    pub(crate) fn in_codegen_phase(&self) -> bool {
2170        self.in_codegen
2171    }
2172
2173    /// Mark the type with the given `name` as replaced by the type with ID
2174    /// `potential_ty`.
2175    ///
2176    /// Replacement types are declared using the `replaces="xxx"` annotation,
2177    /// and implies that the original type is hidden.
2178    pub(crate) fn replace(&mut self, name: &[String], potential_ty: ItemId) {
2179        match self.replacements.entry(name.into()) {
2180            Entry::Vacant(entry) => {
2181                debug!("Defining replacement for {name:?} as {potential_ty:?}");
2182                entry.insert(potential_ty);
2183            }
2184            Entry::Occupied(occupied) => {
2185                warn!(
2186                    "Replacement for {name:?} already defined as {:?}; \
2187                     ignoring duplicate replacement definition as {potential_ty:?}",
2188                    occupied.get(),
2189                );
2190            }
2191        }
2192    }
2193
2194    /// Has the item with the given `name` and `id` been replaced by another
2195    /// type?
2196    pub(crate) fn is_replaced_type<Id: Into<ItemId>>(
2197        &self,
2198        path: &[String],
2199        id: Id,
2200    ) -> bool {
2201        let id = id.into();
2202        matches!(self.replacements.get(path), Some(replaced_by) if *replaced_by != id)
2203    }
2204
2205    /// Is the type with the given `name` marked as opaque?
2206    pub(crate) fn opaque_by_name(&self, path: &[String]) -> bool {
2207        debug_assert!(
2208            self.in_codegen_phase(),
2209            "You're not supposed to call this yet"
2210        );
2211        self.options.opaque_types.matches(path[1..].join("::"))
2212    }
2213
2214    /// Get the options used to configure this bindgen context.
2215    pub(crate) fn options(&self) -> &BindgenOptions {
2216        &self.options
2217    }
2218
2219    /// Tokenizes a namespace cursor in order to get the name and kind of the
2220    /// namespace.
2221    fn tokenize_namespace(
2222        &self,
2223        cursor: &Cursor,
2224    ) -> (Option<String>, ModuleKind) {
2225        assert_eq!(
2226            cursor.kind(),
2227            ::clang_sys::CXCursor_Namespace,
2228            "Be a nice person"
2229        );
2230
2231        let mut module_name = None;
2232        let spelling = cursor.spelling();
2233        if !spelling.is_empty() {
2234            module_name = Some(spelling);
2235        }
2236
2237        let mut kind = ModuleKind::Normal;
2238        let mut looking_for_name = false;
2239        for token in cursor.tokens().iter() {
2240            match token.spelling() {
2241                b"inline" => {
2242                    debug_assert!(
2243                        kind != ModuleKind::Inline,
2244                        "Multiple inline keywords?"
2245                    );
2246                    kind = ModuleKind::Inline;
2247                    // When hitting a nested inline namespace we get a spelling
2248                    // that looks like ["inline", "foo"]. Deal with it properly.
2249                    looking_for_name = true;
2250                }
2251                // The double colon allows us to handle nested namespaces like
2252                // namespace foo::bar { }
2253                //
2254                // libclang still gives us two namespace cursors, which is cool,
2255                // but the tokenization of the second begins with the double
2256                // colon. That's ok, so we only need to handle the weird
2257                // tokenization here.
2258                b"namespace" | b"::" => {
2259                    looking_for_name = true;
2260                }
2261                b"{" => {
2262                    // This should be an anonymous namespace.
2263                    assert!(looking_for_name);
2264                    break;
2265                }
2266                name => {
2267                    if looking_for_name {
2268                        if module_name.is_none() {
2269                            module_name = Some(
2270                                String::from_utf8_lossy(name).into_owned(),
2271                            );
2272                        }
2273                        break;
2274                    } else {
2275                        // This is _likely_, but not certainly, a macro that's
2276                        // been placed just before the namespace keyword.
2277                        // Unfortunately, clang tokens don't let us easily see
2278                        // through the ifdef tokens, so we don't know what this
2279                        // token should really be. Instead of panicking though,
2280                        // we warn the user that we assumed the token was blank,
2281                        // and then move on.
2282                        //
2283                        // See also https://github.com/rust-lang/rust-bindgen/issues/1676.
2284                        warn!(
2285                            "Ignored unknown namespace prefix '{}' at {token:?} in {cursor:?}",
2286                            String::from_utf8_lossy(name),
2287                        );
2288                    }
2289                }
2290            }
2291        }
2292
2293        if cursor.is_inline_namespace() {
2294            kind = ModuleKind::Inline;
2295        }
2296
2297        (module_name, kind)
2298    }
2299
2300    /// Given a `CXCursor_Namespace` cursor, return the item ID of the
2301    /// corresponding module, or create one on the fly.
2302    pub(crate) fn module(&mut self, cursor: Cursor) -> ModuleId {
2303        use clang_sys::*;
2304        assert_eq!(cursor.kind(), CXCursor_Namespace, "Be a nice person");
2305        let cursor = cursor.canonical();
2306        if let Some(id) = self.modules.get(&cursor) {
2307            return *id;
2308        }
2309
2310        let (module_name, kind) = self.tokenize_namespace(&cursor);
2311
2312        let module_id = self.next_item_id();
2313        let module = Module::new(module_name, kind);
2314        let module = Item::new(
2315            module_id,
2316            None,
2317            None,
2318            self.current_module.into(),
2319            ItemKind::Module(module),
2320            Some(cursor.location()),
2321        );
2322
2323        let module_id = module.id().as_module_id_unchecked();
2324        self.modules.insert(cursor, module_id);
2325
2326        self.add_item(module, None, None);
2327
2328        module_id
2329    }
2330
2331    /// Start traversing the module with the given `module_id`, invoke the
2332    /// callback `cb`, and then return to traversing the original module.
2333    pub(crate) fn with_module<F>(&mut self, module_id: ModuleId, cb: F)
2334    where
2335        F: FnOnce(&mut Self),
2336    {
2337        debug_assert!(self.resolve_item(module_id).kind().is_module(), "Wat");
2338
2339        let previous_id = self.current_module;
2340        self.current_module = module_id;
2341
2342        cb(self);
2343
2344        self.current_module = previous_id;
2345    }
2346
2347    /// Iterate over all (explicitly or transitively) allowlisted items.
2348    ///
2349    /// If no items are explicitly allowlisted, then all items are considered
2350    /// allowlisted.
2351    pub(crate) fn allowlisted_items(&self) -> &ItemSet {
2352        assert!(self.in_codegen_phase());
2353        assert!(self.current_module == self.root_module);
2354
2355        self.allowlisted.as_ref().unwrap()
2356    }
2357
2358    /// Check whether a particular blocklisted type implements a trait or not.
2359    /// Results may be cached.
2360    pub(crate) fn blocklisted_type_implements_trait(
2361        &self,
2362        item: &Item,
2363        derive_trait: DeriveTrait,
2364    ) -> CanDerive {
2365        assert!(self.in_codegen_phase());
2366        assert!(self.current_module == self.root_module);
2367
2368        *self
2369            .blocklisted_types_implement_traits
2370            .borrow_mut()
2371            .entry(derive_trait)
2372            .or_default()
2373            .entry(item.id())
2374            .or_insert_with(|| {
2375                item.expect_type()
2376                    .name()
2377                    .and_then(|name| {
2378                        if self.options.parse_callbacks.is_empty() {
2379                            // Sized integer types from <stdint.h> get mapped to Rust primitive
2380                            // types regardless of whether they are blocklisted, so ensure that
2381                            // standard traits are considered derivable for them too.
2382                            if self.is_stdint_type(name) {
2383                                Some(CanDerive::Yes)
2384                            } else {
2385                                Some(CanDerive::No)
2386                            }
2387                        } else {
2388                            self.options.last_callback(|cb| {
2389                                cb.blocklisted_type_implements_trait(
2390                                    name,
2391                                    derive_trait,
2392                                )
2393                            })
2394                        }
2395                    })
2396                    .unwrap_or(CanDerive::No)
2397            })
2398    }
2399
2400    /// Is the given type a type from <stdint.h> that corresponds to a Rust primitive type?
2401    pub(crate) fn is_stdint_type(&self, name: &str) -> bool {
2402        match name {
2403            "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
2404            "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
2405            "intptr_t" | "ptrdiff_t" => true,
2406            "size_t" | "ssize_t" => self.options.size_t_is_usize,
2407            _ => false,
2408        }
2409    }
2410
2411    /// Get a reference to the set of items we should generate.
2412    pub(crate) fn codegen_items(&self) -> &ItemSet {
2413        assert!(self.in_codegen_phase());
2414        assert!(self.current_module == self.root_module);
2415        self.codegen_items.as_ref().unwrap()
2416    }
2417
2418    /// Compute the allowlisted items set and populate `self.allowlisted`.
2419    fn compute_allowlisted_and_codegen_items(&mut self) {
2420        assert!(self.in_codegen_phase());
2421        assert!(self.current_module == self.root_module);
2422        assert!(self.allowlisted.is_none());
2423        let _t = self.timer("compute_allowlisted_and_codegen_items");
2424
2425        let roots = {
2426            let mut roots = self
2427                .items()
2428                // Only consider roots that are enabled for codegen.
2429                .filter(|&(_, item)| item.is_enabled_for_codegen(self))
2430                .filter(|&(_, item)| {
2431                    // If nothing is explicitly allowlisted, then everything is fair
2432                    // game.
2433                    if self.options().allowlisted_types.is_empty() &&
2434                        self.options().allowlisted_functions.is_empty() &&
2435                        self.options().allowlisted_vars.is_empty() &&
2436                        self.options().allowlisted_files.is_empty() &&
2437                        self.options().allowlisted_items.is_empty()
2438                    {
2439                        return true;
2440                    }
2441
2442                    // If this is a type that explicitly replaces another, we assume
2443                    // you know what you're doing.
2444                    if item.annotations().use_instead_of().is_some() {
2445                        return true;
2446                    }
2447
2448                    // Items with a source location in an explicitly allowlisted file
2449                    // are always included.
2450                    if !self.options().allowlisted_files.is_empty() {
2451                        if let Some(location) = item.location() {
2452                            let (file, _, _, _) = location.location();
2453                            if let Some(filename) = file.name() {
2454                                if self
2455                                    .options()
2456                                    .allowlisted_files
2457                                    .matches(filename)
2458                                {
2459                                    return true;
2460                                }
2461                            }
2462                        }
2463                    }
2464
2465                    let name = item.path_for_allowlisting(self)[1..].join("::");
2466                    debug!("allowlisted_items: testing {name:?}");
2467
2468                    if self.options().allowlisted_items.matches(&name) {
2469                        return true;
2470                    }
2471
2472                    match *item.kind() {
2473                        ItemKind::Module(..) => true,
2474                        ItemKind::Function(_) => {
2475                            self.options().allowlisted_functions.matches(&name)
2476                        }
2477                        ItemKind::Var(_) => {
2478                            self.options().allowlisted_vars.matches(&name)
2479                        }
2480                        ItemKind::Type(ref ty) => {
2481                            if self.options().allowlisted_types.matches(&name) {
2482                                return true;
2483                            }
2484
2485                            // Auto-allowlist types that don't need code
2486                            // generation if not allowlisting recursively, to
2487                            // make the #[derive] analysis not be lame.
2488                            if !self.options().allowlist_recursively {
2489                                match *ty.kind() {
2490                                    TypeKind::Void |
2491                                    TypeKind::NullPtr |
2492                                    TypeKind::Int(..) |
2493                                    TypeKind::Float(..) |
2494                                    TypeKind::Complex(..) |
2495                                    TypeKind::Array(..) |
2496                                    TypeKind::Vector(..) |
2497                                    TypeKind::Pointer(..) |
2498                                    TypeKind::Reference(..) |
2499                                    TypeKind::Function(..) |
2500                                    TypeKind::ResolvedTypeRef(..) |
2501                                    TypeKind::Opaque |
2502                                    TypeKind::TypeParam => return true,
2503                                    _ => {}
2504                                }
2505                                if self.is_stdint_type(&name) {
2506                                    return true;
2507                                }
2508                            }
2509
2510                            // Unnamed top-level enums are special and we
2511                            // allowlist them via the `allowlisted_vars` filter,
2512                            // since they're effectively top-level constants,
2513                            // and there's no way for them to be referenced
2514                            // consistently.
2515                            let parent = self.resolve_item(item.parent_id());
2516                            if !parent.is_module() {
2517                                return false;
2518                            }
2519
2520                            let TypeKind::Enum(ref enum_) = *ty.kind() else {
2521                                return false;
2522                            };
2523
2524                            if ty.name().is_some() {
2525                                return false;
2526                            }
2527
2528                            let mut prefix_path =
2529                                parent.path_for_allowlisting(self).clone();
2530                            enum_.variants().iter().any(|variant| {
2531                                prefix_path.push(
2532                                    variant.name_for_allowlisting().into(),
2533                                );
2534                                let name = prefix_path[1..].join("::");
2535                                prefix_path.pop().unwrap();
2536                                self.options().allowlisted_vars.matches(&name)
2537                                    || self
2538                                        .options()
2539                                        .allowlisted_items
2540                                        .matches(name)
2541                            })
2542                        }
2543                    }
2544                })
2545                .map(|(id, _)| id)
2546                .collect::<Vec<_>>();
2547
2548            // The reversal preserves the expected ordering of traversal,
2549            // resulting in more stable-ish bindgen-generated names for
2550            // anonymous types (like unions).
2551            roots.reverse();
2552            roots
2553        };
2554
2555        let allowlisted_items_predicate =
2556            if self.options().allowlist_recursively {
2557                traversal::all_edges
2558            } else {
2559                // Only follow InnerType edges from the allowlisted roots.
2560                // Such inner types (e.g. anonymous structs/unions) are
2561                // always emitted by codegen, and they need to be allowlisted
2562                // to make sure they are processed by e.g. the derive analysis.
2563                traversal::only_inner_type_edges
2564            };
2565
2566        let allowlisted = AllowlistedItemsTraversal::new(
2567            self,
2568            roots.clone(),
2569            allowlisted_items_predicate,
2570        )
2571        .collect::<ItemSet>();
2572
2573        let codegen_items = if self.options().allowlist_recursively {
2574            AllowlistedItemsTraversal::new(
2575                self,
2576                roots,
2577                traversal::codegen_edges,
2578            )
2579            .collect::<ItemSet>()
2580        } else {
2581            allowlisted.clone()
2582        };
2583
2584        self.allowlisted = Some(allowlisted);
2585        self.codegen_items = Some(codegen_items);
2586
2587        for item in self.options().allowlisted_functions.unmatched_items() {
2588            unused_regex_diagnostic(item, "--allowlist-function", self);
2589        }
2590
2591        for item in self.options().allowlisted_vars.unmatched_items() {
2592            unused_regex_diagnostic(item, "--allowlist-var", self);
2593        }
2594
2595        for item in self.options().allowlisted_types.unmatched_items() {
2596            unused_regex_diagnostic(item, "--allowlist-type", self);
2597        }
2598
2599        for item in self.options().allowlisted_items.unmatched_items() {
2600            unused_regex_diagnostic(item, "--allowlist-items", self);
2601        }
2602    }
2603
2604    /// Convenient method for getting the prefix to use for most traits in
2605    /// codegen depending on the `use_core` option.
2606    pub(crate) fn trait_prefix(&self) -> Ident {
2607        if self.options().use_core {
2608            self.rust_ident_raw("core")
2609        } else {
2610            self.rust_ident_raw("std")
2611        }
2612    }
2613
2614    /// Call if an opaque array is generated
2615    pub(crate) fn generated_opaque_array(&self) {
2616        self.generated_opaque_array.set(true)
2617    }
2618
2619    /// Whether we need to generate the opaque array type
2620    pub(crate) fn need_opaque_array_type(&self) -> bool {
2621        self.generated_opaque_array.get()
2622    }
2623
2624    /// Call if a bindgen complex is generated
2625    pub(crate) fn generated_bindgen_complex(&self) {
2626        self.generated_bindgen_complex.set(true);
2627    }
2628
2629    /// Whether we need to generate the bindgen complex type
2630    pub(crate) fn need_bindgen_complex_type(&self) -> bool {
2631        self.generated_bindgen_complex.get()
2632    }
2633
2634    /// Call if a bindgen float16 is generated
2635    pub(crate) fn generated_bindgen_float16(&self) {
2636        self.generated_bindgen_float16.set(true);
2637    }
2638
2639    /// Whether we need to generate the bindgen float16 type
2640    pub(crate) fn need_bindgen_float16_type(&self) -> bool {
2641        self.generated_bindgen_float16.get()
2642    }
2643
2644    /// Compute which `enum`s have an associated `typedef` definition.
2645    fn compute_enum_typedef_combos(&mut self) {
2646        let _t = self.timer("compute_enum_typedef_combos");
2647        assert!(self.enum_typedef_combos.is_none());
2648
2649        let mut enum_typedef_combos = HashSet::default();
2650        for item in &self.items {
2651            if let Some(ItemKind::Module(module)) =
2652                item.as_ref().map(Item::kind)
2653            {
2654                // Find typedefs in this module, and build set of their names.
2655                let mut names_of_typedefs = HashSet::default();
2656                for child_id in module.children() {
2657                    if let Some(ItemKind::Type(ty)) =
2658                        self.items[child_id.0].as_ref().map(Item::kind)
2659                    {
2660                        if let (Some(name), TypeKind::Alias(type_id)) =
2661                            (ty.name(), ty.kind())
2662                        {
2663                            // We disregard aliases that refer to the enum
2664                            // itself, such as in `typedef enum { ... } Enum;`.
2665                            if type_id
2666                                .into_resolver()
2667                                .through_type_refs()
2668                                .through_type_aliases()
2669                                .resolve(self)
2670                                .expect_type()
2671                                .is_int()
2672                            {
2673                                names_of_typedefs.insert(name);
2674                            }
2675                        }
2676                    }
2677                }
2678
2679                // Find enums in this module, and record the ID of each one that
2680                // has a typedef.
2681                for child_id in module.children() {
2682                    if let Some(ItemKind::Type(ty)) =
2683                        self.items[child_id.0].as_ref().map(Item::kind)
2684                    {
2685                        if let (Some(name), true) = (ty.name(), ty.is_enum()) {
2686                            if names_of_typedefs.contains(name) {
2687                                enum_typedef_combos.insert(*child_id);
2688                            }
2689                        }
2690                    }
2691                }
2692            }
2693        }
2694
2695        self.enum_typedef_combos = Some(enum_typedef_combos);
2696    }
2697
2698    /// Look up whether `id` refers to an `enum` whose underlying type is
2699    /// defined by a `typedef`.
2700    pub(crate) fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
2701        assert!(
2702            self.in_codegen_phase(),
2703            "We only compute enum_typedef_combos when we enter codegen",
2704        );
2705        self.enum_typedef_combos.as_ref().unwrap().contains(&id)
2706    }
2707
2708    /// Compute whether we can derive debug.
2709    fn compute_cannot_derive_debug(&mut self) {
2710        let _t = self.timer("compute_cannot_derive_debug");
2711        assert!(self.cannot_derive_debug.is_none());
2712        if self.options.derive_debug {
2713            self.cannot_derive_debug =
2714                Some(as_cannot_derive_set(analyze::<CannotDerive>((
2715                    self,
2716                    DeriveTrait::Debug,
2717                ))));
2718        }
2719    }
2720
2721    /// Look up whether the item with `id` can
2722    /// derive debug or not.
2723    pub(crate) fn lookup_can_derive_debug<Id: Into<ItemId>>(
2724        &self,
2725        id: Id,
2726    ) -> bool {
2727        let id = id.into();
2728        assert!(
2729            self.in_codegen_phase(),
2730            "We only compute can_derive_debug when we enter codegen"
2731        );
2732
2733        // Look up the computed value for whether the item with `id` can
2734        // derive debug or not.
2735        !self.cannot_derive_debug.as_ref().unwrap().contains(&id)
2736    }
2737
2738    /// Compute whether we can derive default.
2739    fn compute_cannot_derive_default(&mut self) {
2740        let _t = self.timer("compute_cannot_derive_default");
2741        assert!(self.cannot_derive_default.is_none());
2742        if self.options.derive_default {
2743            self.cannot_derive_default =
2744                Some(as_cannot_derive_set(analyze::<CannotDerive>((
2745                    self,
2746                    DeriveTrait::Default,
2747                ))));
2748        }
2749    }
2750
2751    /// Look up whether the item with `id` can
2752    /// derive default or not.
2753    pub(crate) fn lookup_can_derive_default<Id: Into<ItemId>>(
2754        &self,
2755        id: Id,
2756    ) -> bool {
2757        let id = id.into();
2758        assert!(
2759            self.in_codegen_phase(),
2760            "We only compute can_derive_default when we enter codegen"
2761        );
2762
2763        // Look up the computed value for whether the item with `id` can
2764        // derive default or not.
2765        !self.cannot_derive_default.as_ref().unwrap().contains(&id)
2766    }
2767
2768    /// Compute whether we can derive copy.
2769    fn compute_cannot_derive_copy(&mut self) {
2770        let _t = self.timer("compute_cannot_derive_copy");
2771        assert!(self.cannot_derive_copy.is_none());
2772        self.cannot_derive_copy =
2773            Some(as_cannot_derive_set(analyze::<CannotDerive>((
2774                self,
2775                DeriveTrait::Copy,
2776            ))));
2777    }
2778
2779    /// Compute whether we can derive hash.
2780    fn compute_cannot_derive_hash(&mut self) {
2781        let _t = self.timer("compute_cannot_derive_hash");
2782        assert!(self.cannot_derive_hash.is_none());
2783        if self.options.derive_hash {
2784            self.cannot_derive_hash =
2785                Some(as_cannot_derive_set(analyze::<CannotDerive>((
2786                    self,
2787                    DeriveTrait::Hash,
2788                ))));
2789        }
2790    }
2791
2792    /// Look up whether the item with `id` can
2793    /// derive hash or not.
2794    pub(crate) fn lookup_can_derive_hash<Id: Into<ItemId>>(
2795        &self,
2796        id: Id,
2797    ) -> bool {
2798        let id = id.into();
2799        assert!(
2800            self.in_codegen_phase(),
2801            "We only compute can_derive_debug when we enter codegen"
2802        );
2803
2804        // Look up the computed value for whether the item with `id` can
2805        // derive hash or not.
2806        !self.cannot_derive_hash.as_ref().unwrap().contains(&id)
2807    }
2808
2809    /// Compute whether we can derive `PartialOrd`, `PartialEq` or `Eq`.
2810    fn compute_cannot_derive_partialord_partialeq_or_eq(&mut self) {
2811        let _t = self.timer("compute_cannot_derive_partialord_partialeq_or_eq");
2812        assert!(self.cannot_derive_partialeq_or_partialord.is_none());
2813        if self.options.derive_partialord ||
2814            self.options.derive_partialeq ||
2815            self.options.derive_eq
2816        {
2817            self.cannot_derive_partialeq_or_partialord =
2818                Some(analyze::<CannotDerive>((
2819                    self,
2820                    DeriveTrait::PartialEqOrPartialOrd,
2821                )));
2822        }
2823    }
2824
2825    /// Look up whether the item with `id` can derive `Partial{Eq,Ord}`.
2826    pub(crate) fn lookup_can_derive_partialeq_or_partialord<
2827        Id: Into<ItemId>,
2828    >(
2829        &self,
2830        id: Id,
2831    ) -> CanDerive {
2832        let id = id.into();
2833        assert!(
2834            self.in_codegen_phase(),
2835            "We only compute can_derive_partialeq_or_partialord when we enter codegen"
2836        );
2837
2838        // Look up the computed value for whether the item with `id` can
2839        // derive partialeq or not.
2840        self.cannot_derive_partialeq_or_partialord
2841            .as_ref()
2842            .unwrap()
2843            .get(&id)
2844            .copied()
2845            .unwrap_or(CanDerive::Yes)
2846    }
2847
2848    /// Look up whether the item with `id` can derive `Copy` or not.
2849    pub(crate) fn lookup_can_derive_copy<Id: Into<ItemId>>(
2850        &self,
2851        id: Id,
2852    ) -> bool {
2853        assert!(
2854            self.in_codegen_phase(),
2855            "We only compute can_derive_debug when we enter codegen"
2856        );
2857
2858        // Look up the computed value for whether the item with `id` can
2859        // derive `Copy` or not.
2860        let id = id.into();
2861
2862        !self.lookup_has_type_param_in_array(id) &&
2863            !self.cannot_derive_copy.as_ref().unwrap().contains(&id)
2864    }
2865
2866    /// Compute whether the type has type parameter in array.
2867    fn compute_has_type_param_in_array(&mut self) {
2868        let _t = self.timer("compute_has_type_param_in_array");
2869        assert!(self.has_type_param_in_array.is_none());
2870        self.has_type_param_in_array =
2871            Some(analyze::<HasTypeParameterInArray>(self));
2872    }
2873
2874    /// Look up whether the item with `id` has type parameter in array or not.
2875    pub(crate) fn lookup_has_type_param_in_array<Id: Into<ItemId>>(
2876        &self,
2877        id: Id,
2878    ) -> bool {
2879        assert!(
2880            self.in_codegen_phase(),
2881            "We only compute has array when we enter codegen"
2882        );
2883
2884        // Look up the computed value for whether the item with `id` has
2885        // type parameter in array or not.
2886        self.has_type_param_in_array
2887            .as_ref()
2888            .unwrap()
2889            .contains(&id.into())
2890    }
2891
2892    /// Compute whether the type has float.
2893    fn compute_has_float(&mut self) {
2894        let _t = self.timer("compute_has_float");
2895        assert!(self.has_float.is_none());
2896        if self.options.derive_eq || self.options.derive_ord {
2897            self.has_float = Some(analyze::<HasFloat>(self));
2898        }
2899    }
2900
2901    /// Look up whether the item with `id` has array or not.
2902    pub(crate) fn lookup_has_float<Id: Into<ItemId>>(&self, id: Id) -> bool {
2903        assert!(
2904            self.in_codegen_phase(),
2905            "We only compute has float when we enter codegen"
2906        );
2907
2908        // Look up the computed value for whether the item with `id` has
2909        // float or not.
2910        self.has_float.as_ref().unwrap().contains(&id.into())
2911    }
2912
2913    /// Check if `--no-partialeq` flag is enabled for this item.
2914    pub(crate) fn no_partialeq_by_name(&self, item: &Item) -> bool {
2915        let name = item.path_for_allowlisting(self)[1..].join("::");
2916        self.options().no_partialeq_types.matches(name)
2917    }
2918
2919    /// Check if `--no-copy` flag is enabled for this item.
2920    pub(crate) fn no_copy_by_name(&self, item: &Item) -> bool {
2921        let name = item.path_for_allowlisting(self)[1..].join("::");
2922        self.options().no_copy_types.matches(name)
2923    }
2924
2925    /// Check if `--no-debug` flag is enabled for this item.
2926    pub(crate) fn no_debug_by_name(&self, item: &Item) -> bool {
2927        let name = item.path_for_allowlisting(self)[1..].join("::");
2928        self.options().no_debug_types.matches(name)
2929    }
2930
2931    /// Check if `--no-default` flag is enabled for this item.
2932    pub(crate) fn no_default_by_name(&self, item: &Item) -> bool {
2933        let name = item.path_for_allowlisting(self)[1..].join("::");
2934        self.options().no_default_types.matches(name)
2935    }
2936
2937    /// Check if `--no-hash` flag is enabled for this item.
2938    pub(crate) fn no_hash_by_name(&self, item: &Item) -> bool {
2939        let name = item.path_for_allowlisting(self)[1..].join("::");
2940        self.options().no_hash_types.matches(name)
2941    }
2942
2943    /// Check if `--must-use-type` flag is enabled for this item.
2944    pub(crate) fn must_use_type_by_name(&self, item: &Item) -> bool {
2945        let name = item.path_for_allowlisting(self)[1..].join("::");
2946        self.options().must_use_types.matches(name)
2947    }
2948
2949    /// Wrap some tokens in an `unsafe` block if the `--wrap-unsafe-ops` option is enabled.
2950    pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream {
2951        if self.options.wrap_unsafe_ops {
2952            quote!(unsafe { #tokens })
2953        } else {
2954            tokens.into_token_stream()
2955        }
2956    }
2957
2958    /// Get the suffix to be added to `static` functions if the `--wrap-static-fns` option is
2959    /// enabled.
2960    pub(crate) fn wrap_static_fns_suffix(&self) -> &str {
2961        self.options()
2962            .wrap_static_fns_suffix
2963            .as_deref()
2964            .unwrap_or(crate::DEFAULT_NON_EXTERN_FNS_SUFFIX)
2965    }
2966}
2967
2968/// A builder struct for configuring item resolution options.
2969#[derive(Debug, Copy, Clone)]
2970pub(crate) struct ItemResolver {
2971    id: ItemId,
2972    through_type_refs: bool,
2973    through_type_aliases: bool,
2974}
2975
2976impl ItemId {
2977    /// Create an `ItemResolver` from this item ID.
2978    pub(crate) fn into_resolver(self) -> ItemResolver {
2979        self.into()
2980    }
2981}
2982
2983impl<T> From<T> for ItemResolver
2984where
2985    T: Into<ItemId>,
2986{
2987    fn from(id: T) -> ItemResolver {
2988        ItemResolver::new(id)
2989    }
2990}
2991
2992impl ItemResolver {
2993    /// Construct a new `ItemResolver` from the given ID.
2994    pub(crate) fn new<Id: Into<ItemId>>(id: Id) -> ItemResolver {
2995        let id = id.into();
2996        ItemResolver {
2997            id,
2998            through_type_refs: false,
2999            through_type_aliases: false,
3000        }
3001    }
3002
3003    /// Keep resolving through `Type::TypeRef` items.
3004    pub(crate) fn through_type_refs(mut self) -> ItemResolver {
3005        self.through_type_refs = true;
3006        self
3007    }
3008
3009    /// Keep resolving through `Type::Alias` items.
3010    pub(crate) fn through_type_aliases(mut self) -> ItemResolver {
3011        self.through_type_aliases = true;
3012        self
3013    }
3014
3015    /// Finish configuring and perform the actual item resolution.
3016    pub(crate) fn resolve(self, ctx: &BindgenContext) -> &Item {
3017        assert!(ctx.collected_typerefs());
3018
3019        let mut id = self.id;
3020        let mut seen_ids = HashSet::default();
3021        loop {
3022            let item = ctx.resolve_item(id);
3023
3024            // Detect cycles and bail out. These can happen in certain cases
3025            // involving incomplete qualified dependent types (#2085).
3026            if !seen_ids.insert(id) {
3027                return item;
3028            }
3029
3030            let ty_kind = item.as_type().map(|t| t.kind());
3031            match ty_kind {
3032                Some(&TypeKind::ResolvedTypeRef(next_id))
3033                    if self.through_type_refs =>
3034                {
3035                    id = next_id.into();
3036                }
3037                // We intentionally ignore template aliases here, as they are
3038                // more complicated, and don't represent a simple renaming of
3039                // some type.
3040                Some(&TypeKind::Alias(next_id))
3041                    if self.through_type_aliases =>
3042                {
3043                    id = next_id.into();
3044                }
3045                _ => return item,
3046            }
3047        }
3048    }
3049}
3050
3051/// A type that we are in the middle of parsing.
3052#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3053pub(crate) struct PartialType {
3054    decl: Cursor,
3055    // Just an ItemId, and not a TypeId, because we haven't finished this type
3056    // yet, so there's still time for things to go wrong.
3057    id: ItemId,
3058}
3059
3060impl PartialType {
3061    /// Construct a new `PartialType`.
3062    pub(crate) fn new(decl: Cursor, id: ItemId) -> PartialType {
3063        // assert!(decl == decl.canonical());
3064        PartialType { decl, id }
3065    }
3066
3067    /// The cursor pointing to this partial type's declaration location.
3068    pub(crate) fn decl(&self) -> &Cursor {
3069        &self.decl
3070    }
3071
3072    /// The item ID allocated for this type. This is *NOT* a key for an entry in
3073    /// the context's item set yet!
3074    pub(crate) fn id(&self) -> ItemId {
3075        self.id
3076    }
3077}
3078
3079impl TemplateParameters for PartialType {
3080    fn self_template_params(&self, _ctx: &BindgenContext) -> Vec<TypeId> {
3081        // Maybe at some point we will eagerly parse named types, but for now we
3082        // don't and this information is unavailable.
3083        vec![]
3084    }
3085
3086    fn num_self_template_params(&self, _ctx: &BindgenContext) -> usize {
3087        // Wouldn't it be nice if libclang would reliably give us this
3088        // information‽
3089        match self.decl().kind() {
3090            clang_sys::CXCursor_ClassTemplate |
3091            clang_sys::CXCursor_FunctionTemplate |
3092            clang_sys::CXCursor_TypeAliasTemplateDecl => {
3093                let mut num_params = 0;
3094                self.decl().visit(|c| {
3095                    match c.kind() {
3096                        clang_sys::CXCursor_TemplateTypeParameter |
3097                        clang_sys::CXCursor_TemplateTemplateParameter |
3098                        clang_sys::CXCursor_NonTypeTemplateParameter => {
3099                            num_params += 1;
3100                        }
3101                        _ => {}
3102                    };
3103                    clang_sys::CXChildVisit_Continue
3104                });
3105                num_params
3106            }
3107            _ => 0,
3108        }
3109    }
3110}
3111
3112fn unused_regex_diagnostic(item: &str, name: &str, _ctx: &BindgenContext) {
3113    warn!("unused option: {name} {item}");
3114
3115    #[cfg(feature = "experimental")]
3116    if _ctx.options().emit_diagnostics {
3117        use crate::diagnostics::{Diagnostic, Level};
3118
3119        Diagnostic::default()
3120            .with_title(
3121                format!("Unused regular expression: `{item}`."),
3122                Level::Warning,
3123            )
3124            .add_annotation(
3125                format!("This regular expression was passed to `{name}`."),
3126                Level::Note,
3127            )
3128            .display();
3129    }
3130}