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