Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/bindgen/codegen/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 199 kB image not shown  

Quellcode-Bibliothek mod.rs

  Sprache: Rust
 

mod dyngen;
pub(cratemod error;

mod helpers;
mod impl_debug;
mod impl_partialeq;
mod postprocessing;
mod serialize;
pub(cratemod struct_layout;

#[cfg(test)]
#[allow(warnings)]
pub(cratemod bitfield_unit;
#[cfg(all(test, target_endian = "little"))]
mod bitfield_unit_tests;

use self::dyngen::DynamicItems;
use self::helpers::attributes;
use self::struct_layout::StructLayoutTracker;

use super::BindgenOptions;

use crate::callbacks::{
    AttributeInfo, DeriveInfo, DiscoveredItem, DiscoveredItemId, FieldInfo,
    TypeKind as DeriveTypeKind,
};
use crate::codegen::error::Error;
use crate::ir::analysis::{HasVtable, Sizedness};
use crate::ir::annotations::{
    Annotations, FieldAccessorKind, FieldVisibilityKind,
};
use crate::ir::comp::{
    Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods,
    Method, MethodKind,
};
use crate::ir::context::{BindgenContext, ItemId};
use crate::ir::derive::{
    CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
    CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
};
use crate::ir::dot;
use crate::ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
use crate::ir::function::{
    ClangAbi, Function, FunctionKind, FunctionSig, Linkage,
};
use crate::ir::int::IntKind;
use crate::ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
use crate::ir::item_kind::ItemKind;
use crate::ir::layout::Layout;
use crate::ir::module::Module;
use crate::ir::objc::{ObjCInterface, ObjCMethod};
use crate::ir::template::{
    AsTemplateParam, TemplateInstantiation, TemplateParameters,
};
use crate::ir::ty::{Type, TypeKind};
use crate::ir::var::Var;

use proc_macro2::{Ident, Span};
use quote::{ToTokens, TokenStreamExt};

use crate::{Entry, HashMap, HashSet};
use std::borrow::Cow;
use std::cell::Cell;
use std::collections::VecDeque;
use std::ffi::CStr;
use std::fmt::{self, Write};
use std::ops;
use std::str::{self, FromStr};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CodegenError {
    Serialize { msg: String, loc: String },
    Io(String),
}

impl From<std::io::Error> for CodegenError {
    fn from(err: std::io::Error) -> Self {
        Self::Io(err.to_string())
    }
}

impl fmt::Display for CodegenError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Serialize { msg, loc } => {
                write!(f, "serialization error at {loc}: {msg}")
            }
            Self::Io(err) => err.fmt(f),
        }
    }
}

// Name of type defined in constified enum module
pub(cratestatic CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type";

fn top_level_path(
    ctx: &BindgenContext,
    item: &Item,
) -> Vec<proc_macro2::TokenStream> {
    let mut path = vec![quote! { self }];

    if ctx.options().enable_cxx_namespaces {
        for _ in 0..item.codegen_depth(ctx) {
            path.push(quote! { super });
        }
    }

    path
}

fn root_import(
    ctx: &BindgenContext,
    module: &Item,
) -> proc_macro2::TokenStream {
    assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up");
    assert!(module.is_module());

    let mut path = top_level_path(ctx, module);

    let root = ctx.root_module().canonical_name(ctx);
    let root_ident = ctx.rust_ident(root);
    path.push(quote! { #root_ident });

    let mut tokens = quote! {};
    tokens.append_separated(path, quote!(::));

    quote! {
        #[allow(unused_imports)]
        use #tokens ;
    }
}

bitflags! {
    #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    struct DerivableTraits: u16 {
        const DEBUG       = 1 << 0;
        const DEFAULT     = 1 << 1;
        const COPY        = 1 << 2;
        const CLONE       = 1 << 3;
        const HASH        = 1 << 4;
        const PARTIAL_ORD = 1 << 5;
        const ORD         = 1 << 6;
        const PARTIAL_EQ  = 1 << 7;
        const EQ          = 1 << 8;
    }
}

fn derives_of_item(
    item: &Item,
    ctx: &BindgenContext,
    packed: bool,
) -> DerivableTraits {
    let mut derivable_traits = DerivableTraits::empty();

    if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
        derivable_traits |= DerivableTraits::COPY;

        // FIXME: This requires extra logic if you have a big array in a
        // templated struct. The reason for this is that the magic:
        //     fn clone(&self) -> Self { *self }
        // doesn't work for templates.
        //
        // It's not hard to fix though.
        derivable_traits |= DerivableTraits::CLONE;
    } else if packed {
        // If the struct or union is packed, deriving from Copy is required for
        // deriving from any other trait.
        return derivable_traits;
    }

    if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() {
        derivable_traits |= DerivableTraits::DEBUG;
    }

    if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
        derivable_traits |= DerivableTraits::DEFAULT;
    }

    if item.can_derive_hash(ctx) {
        derivable_traits |= DerivableTraits::HASH;
    }

    if item.can_derive_partialord(ctx) {
        derivable_traits |= DerivableTraits::PARTIAL_ORD;
    }

    if item.can_derive_ord(ctx) {
        derivable_traits |= DerivableTraits::ORD;
    }

    if item.can_derive_partialeq(ctx) {
        derivable_traits |= DerivableTraits::PARTIAL_EQ;
    }

    if item.can_derive_eq(ctx) {
        derivable_traits |= DerivableTraits::EQ;
    }

    derivable_traits
}

impl From<DerivableTraits> for Vec<&'static str> {
    fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> {
        [
            (DerivableTraits::DEBUG, "Debug"),
            (DerivableTraits::DEFAULT, "Default"),
            (DerivableTraits::COPY, "Copy"),
            (DerivableTraits::CLONE, "Clone"),
            (DerivableTraits::HASH, "Hash"),
            (DerivableTraits::PARTIAL_ORD, "PartialOrd"),
            (DerivableTraits::ORD, "Ord"),
            (DerivableTraits::PARTIAL_EQ, "PartialEq"),
            (DerivableTraits::EQ, "Eq"),
        ]
        .iter()
        .filter_map(|&(flag, derive)| {
            Some(derive).filter(|_| derivable_traits.contains(flag))
        })
        .collect()
    }
}

struct WrapAsVariadic {
    new_name: String,
    idx_of_va_list_arg: usize,
}

struct CodegenResult<'a> {
    items: Vec<proc_macro2::TokenStream>,
    dynamic_items: DynamicItems,

    /// A monotonic counter used to add stable unique ID's to stuff that doesn't
    /// need to be referenced by anything.
    codegen_id: &'a Cell<usize>,

    /// Whether a bindgen union has been generated at least once.
    saw_bindgen_union: bool,

    /// Whether an incomplete array has been generated at least once.
    saw_incomplete_array: bool,

    /// Whether Objective C types have been seen at least once.
    saw_objc: bool,

    /// Whether Apple block types have been seen at least once.
    saw_block: bool,

    /// Whether a bitfield allocation unit has been seen at least once.
    saw_bitfield_unit: bool,

    items_seen: HashSet<ItemId>,
    /// The set of generated function/var names, needed because in C/C++ is
    /// legal to do something like:
    ///
    /// ```c++
    /// extern "C" {
    ///   void foo();
    ///   extern int bar;
    /// }
    ///
    /// extern "C" {
    ///   void foo();
    ///   extern int bar;
    /// }
    /// ```
    ///
    /// Being these two different declarations.
    functions_seen: HashSet<String>,
    vars_seen: HashSet<String>,

    /// Used for making bindings to overloaded functions. Maps from a canonical
    /// function name to the number of overloads we have already codegen'd for
    /// that name. This lets us give each overload a unique suffix.
    overload_counters: HashMap<String, u32>,

    /// List of items to serialize. With optionally the argument for the wrap as
    /// variadic transformation to be applied.
    items_to_serialize: Vec<(ItemId, Option<WrapAsVariadic>)>,
}

impl<'a> CodegenResult<'a> {
    fn new(codegen_id: &'a Cell<usize>) -> Self {
        CodegenResult {
            items: vec![],
            dynamic_items: DynamicItems::new(),
            saw_bindgen_union: false,
            saw_incomplete_array: false,
            saw_objc: false,
            saw_block: false,
            saw_bitfield_unit: false,
            codegen_id,
            items_seen: Default::default(),
            functions_seen: Default::default(),
            vars_seen: Default::default(),
            overload_counters: Default::default(),
            items_to_serialize: Default::default(),
        }
    }

    fn dynamic_items(&mut self) -> &mut DynamicItems {
        &mut self.dynamic_items
    }

    fn saw_bindgen_union(&mut self) {
        self.saw_bindgen_union = true;
    }

    fn saw_incomplete_array(&mut self) {
        self.saw_incomplete_array = true;
    }

    fn saw_objc(&mut self) {
        self.saw_objc = true;
    }

    fn saw_block(&mut self) {
        self.saw_block = true;
    }

    fn saw_bitfield_unit(&mut self) {
        self.saw_bitfield_unit = true;
    }

    fn seen<Id: Into<ItemId>>(&self, item: Id) -> bool {
        self.items_seen.contains(&item.into())
    }

    fn set_seen<Id: Into<ItemId>>(&mut self, item: Id) {
        self.items_seen.insert(item.into());
    }

    fn seen_function(&self, name: &str) -> bool {
        self.functions_seen.contains(name)
    }

    fn saw_function(&mut self, name: &str) {
        self.functions_seen.insert(name.into());
    }

    /// Get the overload number for the given function name. Increments the
    /// counter internally so the next time we ask for the overload for this
    /// name, we get the incremented value, and so on.
    fn overload_number(&mut self, name: &str) -> u32 {
        let counter = self.overload_counters.entry(name.into()).or_insert(0);
        let number = *counter;
        *counter += 1;
        number
    }

    fn seen_var(&self, name: &str) -> bool {
        self.vars_seen.contains(name)
    }

    fn saw_var(&mut self, name: &str) {
        self.vars_seen.insert(name.into());
    }

    fn inner<F>(&mut self, cb: F) -> Vec<proc_macro2::TokenStream>
    where
        F: FnOnce(&mut Self),
    {
        let mut new = Self::new(self.codegen_id);

        cb(&mut new);

        self.saw_incomplete_array |= new.saw_incomplete_array;
        self.saw_objc |= new.saw_objc;
        self.saw_block |= new.saw_block;
        self.saw_bitfield_unit |= new.saw_bitfield_unit;
        self.saw_bindgen_union |= new.saw_bindgen_union;

        new.items
    }
}

impl ops::Deref for CodegenResult<'_> {
    type Target = Vec<proc_macro2::TokenStream>;

    fn deref(&self) -> &Self::Target {
        &self.items
    }
}

impl ops::DerefMut for CodegenResult<'_> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.items
    }
}

/// A trait to convert a rust type into a pointer, optionally const, to the same
/// type.
trait ToPtr {
    fn to_ptr(self, is_const: bool) -> syn::Type;
}

impl ToPtr for syn::Type {
    fn to_ptr(self, is_const: bool) -> syn::Type {
        if is_const {
            syn::parse_quote! { *const #self }
        } else {
            syn::parse_quote! { *mut #self }
        }
    }
}

/// An extension trait for `syn::Type` that lets us append any implicit
/// template parameters that exist for some type, if necessary.
trait WithImplicitTemplateParams {
    fn with_implicit_template_params(
        self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> Self;
}

impl WithImplicitTemplateParams for syn::Type {
    fn with_implicit_template_params(
        self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> Self {
        let item = item.id().into_resolver().through_type_refs().resolve(ctx);

        let params = match *item.expect_type().kind() {
            TypeKind::UnresolvedTypeRef(..) => {
                unreachable!("already resolved unresolved type refs")
            }
            TypeKind::ResolvedTypeRef(..) => {
                unreachable!("we resolved item through type refs")
            }
            // None of these types ever have implicit template parameters.
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Pointer(..) |
            TypeKind::Reference(..) |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Array(..) |
            TypeKind::TypeParam |
            TypeKind::Opaque |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::ObjCId |
            TypeKind::ObjCSel |
            TypeKind::TemplateInstantiation(..) => None,
            _ => {
                let params = item.used_template_params(ctx);
                if params.is_empty() {
                    None
                } else {
                    Some(params.into_iter().map(|p| {
                        p.try_to_rust_ty(ctx, &()).expect(
                            "template params cannot fail to be a rust type",
                        )
                    }))
                }
            }
        };

        if let Some(params) = params {
            syn::parse_quote! { #self<#(#params),*> }
        } else {
            self
        }
    }
}

trait CodeGenerator {
    /// Extra information from the caller.
    type Extra;

    /// Extra information returned to the caller.
    type Return;

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        extra: &Self::Extra,
    ) -> Self::Return;
}

impl Item {
    fn process_before_codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult,
    ) -> bool {
        if !self.is_enabled_for_codegen(ctx) {
            return false;
        }

        if self.is_blocklisted(ctx) || result.seen(self.id()) {
            debug!(
                "<Item as CodeGenerator>::process_before_codegen: Ignoring hidden or seen: \
                 self = {self:?}"
            );
            return false;
        }

        if !ctx.codegen_items().contains(&self.id()) {
            // TODO(emilio, #453): Figure out what to do when this happens
            // legitimately, we could track the opaque stuff and disable the
            // assertion there I guess.
            warn!("Found non-allowlisted item in code generation: {self:?}");
        }

        result.set_seen(self.id());
        true
    }
}

impl CodeGenerator for Item {
    type Extra = ();
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        _extra: &(),
    ) {
        debug!("<Item as CodeGenerator>::codegen: self = {self:?}");
        if !self.process_before_codegen(ctx, result) {
            return;
        }

        match *self.kind() {
            ItemKind::Module(ref module) => {
                module.codegen(ctx, result, self);
            }
            ItemKind::Function(ref fun) => {
                fun.codegen(ctx, result, self);
            }
            ItemKind::Var(ref var) => {
                var.codegen(ctx, result, self);
            }
            ItemKind::Type(ref ty) => {
                ty.codegen(ctx, result, self);
            }
        }
    }
}

impl CodeGenerator for Module {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        debug!("<Module as CodeGenerator>::codegen: item = {item:?}");

        let codegen_self = |result: &mut CodegenResult,
                            found_any: &mut bool| {
            for child in self.children() {
                if ctx.codegen_items().contains(child) {
                    *found_any = true;
                    ctx.resolve_item(*child).codegen(ctx, result, &());
                }
            }

            if item.id() == ctx.root_module() {
                if result.saw_block {
                    utils::prepend_block_header(ctx, &mut *result);
                }
                if result.saw_bindgen_union {
                    utils::prepend_union_types(ctx, &mut *result);
                }
                if result.saw_incomplete_array {
                    utils::prepend_incomplete_array_types(ctx, &mut *result);
                }
                if ctx.need_bindgen_float16_type() {
                    utils::prepend_float16_type(&mut *result);
                }
                if ctx.need_bindgen_complex_type() {
                    utils::prepend_complex_type(&mut *result);
                }
                utils::prepend_opaque_array_types(ctx, &mut *result);
                if result.saw_objc {
                    utils::prepend_objc_header(ctx, &mut *result);
                }
                if result.saw_bitfield_unit {
                    utils::prepend_bitfield_unit_type(ctx, &mut *result);
                }
            }
        };

        if !ctx.options().enable_cxx_namespaces ||
            (self.is_inline() &&
                !ctx.options().conservative_inline_namespaces)
        {
            codegen_self(result, &mut false);
            return;
        }

        let mut found_any = false;
        let inner_items = result.inner(|result| {
            result.push(root_import(ctx, item));

            let path = item
                .namespace_aware_canonical_path(ctx)
                .join("::")
                .into_boxed_str();
            if let Some(raw_lines) = ctx.options().module_lines.get(&path) {
                for raw_line in raw_lines {
                    found_any = true;
                    result.push(
                        proc_macro2::TokenStream::from_str(raw_line).unwrap(),
                    );
                }
            }

            codegen_self(result, &mut found_any);
        });

        // Don't bother creating an empty module.
        if !found_any {
            return;
        }

        let name = item.canonical_name(ctx);
        let ident = ctx.rust_ident(name);
        result.push(if item.id() == ctx.root_module() {
            quote! {
                #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
                pub mod #ident {
                    #( #inner_items )*
                }
            }
        } else {
            quote! {
                pub mod #ident {
                    #( #inner_items )*
                }
            }
        });
    }
}

impl CodeGenerator for Var {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        use crate::ir::var::VarType;
        debug!("<Var as CodeGenerator>::codegen: item = {item:?}");
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let canonical_name = item.canonical_name(ctx);

        if result.seen_var(&canonical_name) {
            return;
        }
        result.saw_var(&canonical_name);

        let canonical_ident = ctx.rust_ident(&canonical_name);

        // We can't generate bindings to static variables of templates. The
        // number of actual variables for a single declaration are open ended
        // and we don't know what instantiations do or don't exist.
        if !item.all_template_params(ctx).is_empty() {
            return;
        }

        let mut attrs = vec![];
        if let Some(comment) = item.comment(ctx) {
            attrs.push(attributes::doc(&comment));
        }

        let var_ty = self.ty();
        let ty = var_ty.to_rust_ty_or_opaque(ctx, &());

        if let Some(val) = self.val() {
            match *val {
                VarType::Bool(val) => {
                    result.push(quote! {
                        #(#attrs)*
                        pub const #canonical_ident : #ty = #val ;
                    });
                }
                VarType::Int(val) => {
                    let int_kind = var_ty
                        .into_resolver()
                        .through_type_aliases()
                        .through_type_refs()
                        .resolve(ctx)
                        .expect_type()
                        .as_integer()
                        .unwrap();
                    let val = if int_kind.is_signed() {
                        helpers::ast_ty::int_expr(val)
                    } else {
                        helpers::ast_ty::uint_expr(val as _)
                    };
                    result.push(quote! {
                        #(#attrs)*
                        pub const #canonical_ident : #ty = #val ;
                    });
                }
                VarType::String(ref bytes) => {
                    let prefix = ctx.trait_prefix();

                    let options = ctx.options();
                    let rust_features = options.rust_features;

                    let mut cstr_bytes = bytes.clone();
                    cstr_bytes.push(0);
                    let len = proc_macro2::Literal::usize_unsuffixed(
                        cstr_bytes.len(),
                    );
                    let cstr =
                        if options.generate_cstr && rust_features.const_cstr {
                            CStr::from_bytes_with_nul(&cstr_bytes).ok()
                        } else {
                            None
                        };
                    if let Some(cstr) = cstr {
                        let cstr_ty = quote! { ::#prefix::ffi::CStr };
                        if rust_features.literal_cstr {
                            let cstr = proc_macro2::Literal::c_string(cstr);
                            result.push(quote! {
                                #(#attrs)*
                                pub const #canonical_ident: &#cstr_ty = #cstr;
                            });
                        } else {
                            let bytes =
                                proc_macro2::Literal::byte_string(&cstr_bytes);
                            result.push(quote! {
                                #(#attrs)*
                                #[allow(unsafe_code)]
                                pub const #canonical_ident: &#cstr_ty = unsafe {
                                    #cstr_ty::from_bytes_with_nul_unchecked(#bytes)
                                };
                            });
                        }
                    } else {
                        // TODO: Here we ignore the type we just made up, probably
                        // we should refactor how the variable type and ty ID work.
                        let array_ty = quote! { [u8; #len] };
                        let bytes =
                            proc_macro2::Literal::byte_string(&cstr_bytes);
                        let lifetime =
                            if true { None } else { Some(quote! { 'static }) }
                                .into_iter();

                        result.push(quote! {
                            #(#attrs)*
                            pub const #canonical_ident: &#(#lifetime )*#array_ty = #bytes ;
                        });
                    }
                }
                VarType::Float(f) => {
                    if let Ok(expr) = helpers::ast_ty::float_expr(f) {
                        result.push(quote! {
                            #(#attrs)*
                            pub const #canonical_ident : #ty = #expr ;
                        });
                    }
                }
                VarType::Char(c) => {
                    result.push(quote! {
                        #(#attrs)*
                        pub const #canonical_ident : #ty = #c ;
                    });
                }
            }
        } else {
            let symbol: &str = self.link_name().unwrap_or_else(|| {
                let link_name =
                    self.mangled_name().unwrap_or_else(|| self.name());
                if utils::names_will_be_identical_after_mangling(
                    &canonical_name,
                    link_name,
                    None,
                ) {
                    canonical_name.as_str()
                } else {
                    attrs.push(attributes::link_name::<false>(link_name));
                    link_name
                }
            });

            let maybe_mut = if self.is_const() {
                quote! {}
            } else {
                quote! { mut }
            };

            let safety = ctx
                .options()
                .rust_features
                .unsafe_extern_blocks
                .then(|| quote!(unsafe));

            let tokens = quote!(
                #safety extern "C" {
                    #(#attrs)*
                    pub static #maybe_mut #canonical_ident#ty;
                }
            );

            if ctx.options().dynamic_library_name.is_some() {
                result.dynamic_items().push_var(
                    &canonical_ident,
                    symbol,
                    &self
                        .ty()
                        .to_rust_ty_or_opaque(ctx, &())
                        .into_token_stream(),
                    ctx.options().dynamic_link_require_all,
                    ctx.options().wrap_unsafe_ops,
                );
            } else {
                result.push(tokens);
            }
        }
    }
}

impl CodeGenerator for Type {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        debug!("<Type as CodeGenerator>::codegen: item = {item:?}");
        debug_assert!(item.is_enabled_for_codegen(ctx));

        match *self.kind() {
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Array(..) |
            TypeKind::Vector(..) |
            TypeKind::Pointer(..) |
            TypeKind::Reference(..) |
            TypeKind::Function(..) |
            TypeKind::ResolvedTypeRef(..) |
            TypeKind::Opaque |
            TypeKind::TypeParam => {
                // These items don't need code generation, they only need to be
                // converted to rust types in fields, arguments, and such.
                // NOTE(emilio): If you add to this list, make sure to also add
                // it to BindgenContext::compute_allowlisted_and_codegen_items.
            }
            TypeKind::TemplateInstantiation(ref inst) => {
                inst.codegen(ctx, result, item);
            }
            TypeKind::BlockPointer(inner) => {
                if !ctx.options().generate_block {
                    return;
                }

                let inner_item =
                    inner.into_resolver().through_type_refs().resolve(ctx);
                let name = item.canonical_name(ctx);

                let inner_rust_type = {
                    if let TypeKind::Function(fnsig) =
                        inner_item.kind().expect_type().kind()
                    {
                        utils::fnsig_block(ctx, fnsig)
                    } else {
                        panic!("invalid block typedef: {inner_item:?}")
                    }
                };

                let rust_name = ctx.rust_ident(name);

                let mut tokens = if let Some(comment) = item.comment(ctx) {
                    attributes::doc(&comment)
                } else {
                    quote! {}
                };

                tokens.append_all(quote! {
                    pub type #rust_name = #inner_rust_type ;
                });

                result.push(tokens);
                result.saw_block();
            }
            TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
            TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => {
                let inner_item =
                    inner.into_resolver().through_type_refs().resolve(ctx);
                let name = item.canonical_name(ctx);
                let path = item.canonical_path(ctx);

                {
                    let through_type_aliases = inner
                        .into_resolver()
                        .through_type_refs()
                        .through_type_aliases()
                        .resolve(ctx);

                    // Try to catch the common pattern:
                    //
                    // typedef struct foo { ... } foo;
                    //
                    // here, and also other more complex cases like #946.
                    if through_type_aliases.canonical_path(ctx) == path {
                        return;
                    }
                }

                // If this is a known named type, disallow generating anything
                // for it too. If size_t -> usize conversions are enabled, we
                // need to check that these conversions are permissible, but
                // nothing needs to be generated, still.
                let spelling = self.name().expect("Unnamed alias?");
                if utils::type_from_named(ctx, spelling).is_some() {
                    if let "size_t" | "ssize_t" = spelling {
                        let layout = inner_item
                            .kind()
                            .expect_type()
                            .layout(ctx)
                            .expect("No layout?");
                        assert_eq!(
                            layout.size,
                            ctx.target_pointer_size(),
                            "Target platform requires `--no-size_t-is-usize`. The size of `{spelling}` ({}) does not match the target pointer size ({})",
                            layout.size,
                            ctx.target_pointer_size(),
                            );
                        assert_eq!(
                            layout.align,
                            ctx.target_pointer_size(),
                            "Target platform requires `--no-size_t-is-usize`. The alignment of `{spelling}` ({}) does not match the target pointer size ({})",
                            layout.align,
                            ctx.target_pointer_size(),
                        );
                    }
                    return;
                }

                let mut outer_params = item.used_template_params(ctx);

                let is_opaque = item.is_opaque(ctx, &());
                let inner_rust_type = if is_opaque {
                    outer_params = vec![];
                    self.to_opaque(ctx, item)
                } else {
                    // Its possible that we have better layout information than
                    // the inner type does, so fall back to an opaque blob based
                    // on our layout if converting the inner item fails.
                    inner_item
                        .try_to_rust_ty_or_opaque(ctx, &())
                        .unwrap_or_else(|_| self.to_opaque(ctx, item))
                        .with_implicit_template_params(ctx, inner_item)
                };

                {
                    // FIXME(emilio): This is a workaround to avoid generating
                    // incorrect type aliases because of types that we haven't
                    // been able to resolve (because, eg, they depend on a
                    // template parameter).
                    //
                    // It's kind of a shame not generating them even when they
                    // could be referenced, but we already do the same for items
                    // with invalid template parameters, and at least this way
                    // they can be replaced, instead of generating plain invalid
                    // code.
                    let inner_canon_type =
                        inner_item.expect_type().canonical_type(ctx);
                    if inner_canon_type.is_invalid_type_param() {
                        warn!(
                            "Item contained invalid named type, skipping: \
                             {item:?}, {inner_item:?}"
                        );
                        return;
                    }
                }

                let rust_name = ctx.rust_ident(&name);

                utils::call_discovered_item_callback(ctx, item, || {
                    DiscoveredItem::Alias {
                        alias_name: rust_name.to_string(),
                        alias_for: DiscoveredItemId::new(
                            inner_item.id().as_usize(),
                        ),
                    }
                });

                let mut tokens = if let Some(comment) = item.comment(ctx) {
                    attributes::doc(&comment)
                } else {
                    quote! {}
                };

                let alias_style = if ctx.options().type_alias.matches(&name) {
                    AliasVariation::TypeAlias
                } else if ctx.options().new_type_alias.matches(&name) {
                    AliasVariation::NewType
                } else if ctx.options().new_type_alias_deref.matches(&name) {
                    AliasVariation::NewTypeDeref
                } else {
                    ctx.options().default_alias_style
                };

                // We prefer using `pub use` over `pub type` because of:
                // https://github.com/rust-lang/rust/issues/26264
                if matches!(inner_rust_type, syn::Type::Path(_)) &&
                    outer_params.is_empty() &&
                    !is_opaque &&
                    alias_style == AliasVariation::TypeAlias &&
                    inner_item.expect_type().canonical_type(ctx).is_enum()
                {
                    tokens.append_all(quote! {
                        pub use
                    });
                    let path = top_level_path(ctx, item);
                    tokens.append_separated(path, quote!(::));
                    tokens.append_all(quote! {
                        :: #inner_rust_type  as #rust_name ;
                    });
                    result.push(tokens);
                    return;
                }

                tokens.append_all(match alias_style {
                    AliasVariation::TypeAlias => quote! {
                        pub type #rust_name
                    },
                    AliasVariation::NewType | AliasVariation::NewTypeDeref => {
                        let mut attributes =
                            vec![attributes::repr("transparent")];
                        let packed = false// Types can't be packed in Rust.
                        let derivable_traits =
                            derives_of_item(item, ctx, packed);
                        let mut derives: Vec<_> = derivable_traits.into();
                        // The custom derives callback may return a list of derive attributes;
                        // add them to the end of the list.
                        let custom_derives =
                            ctx.options().all_callbacks(|cb| {
                                cb.add_derives(&DeriveInfo {
                                    name: &name,
                                    kind: DeriveTypeKind::Struct,
                                })
                            });
                        // In most cases this will be a no-op, since custom_derives will be empty.
                        derives
                            .extend(custom_derives.iter().map(|s| s.as_str()));
                        attributes.push(attributes::derives(&derives));

                        let custom_attributes =
                            ctx.options().all_callbacks(|cb| {
                                cb.add_attributes(&AttributeInfo {
                                    name: &name,
                                    kind: DeriveTypeKind::Struct,
                                })
                            });
                        attributes.extend(
                            custom_attributes
                                .iter()
                                .map(|s| s.parse().unwrap()),
                        );

                        quote! {
                            #( #attributes )*
                            pub struct #rust_name
                        }
                    }
                });

                let params: Vec<_> = outer_params
                    .into_iter()
                    .filter_map(|p| p.as_template_param(ctx, &()))
                    .collect();
                if params
                    .iter()
                    .any(|p| ctx.resolve_type(*p).is_invalid_type_param())
                {
                    warn!(
                        "Item contained invalid template \
                         parameter: {item:?}"
                    );
                    return;
                }
                let params: Vec<_> = params
                    .iter()
                    .map(|p| {
                        p.try_to_rust_ty(ctx, &()).expect(
                            "type parameters can always convert to rust ty OK",
                        )
                    })
                    .collect();

                if !params.is_empty() {
                    tokens.append_all(quote! {
                        < #( #params ),* >
                    });
                }

                tokens.append_all(match alias_style {
                    AliasVariation::TypeAlias => quote! {
                        = #inner_rust_type ;
                    },
                    AliasVariation::NewType | AliasVariation::NewTypeDeref => {
                        let visibility = ctx
                            .options()
                            .last_callback(|cb| {
                                cb.field_visibility(FieldInfo {
                                    type_name: &item.canonical_name(ctx),
                                    field_name: "0",
                                    field_type_name: inner_item
                                        .expect_type()
                                        .name(),
                                })
                            })
                            .unwrap_or(ctx.options().default_visibility);
                        let access_spec = access_specifier(visibility);
                        quote! {
                            (#access_spec #inner_rust_type) ;
                        }
                    }
                });

                if alias_style == AliasVariation::NewTypeDeref {
                    let prefix = ctx.trait_prefix();
                    tokens.append_all(quote! {
                        impl ::#prefix::ops::Deref for #rust_name {
                            type Target = #inner_rust_type;
                            #[inline]
                            fn deref(&self) -> &Self::Target {
                                &self.0
                            }
                        }
                        impl ::#prefix::ops::DerefMut for #rust_name {
                            #[inline]
                            fn deref_mut(&mut self) -> &mut Self::Target {
                                &mut self.0
                            }
                        }
                    });
                }

                result.push(tokens);
            }
            TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
            TypeKind::ObjCId | TypeKind::ObjCSel => {
                result.saw_objc();
            }
            TypeKind::ObjCInterface(ref interface) => {
                interface.codegen(ctx, result, item);
            }
            ref u @ TypeKind::UnresolvedTypeRef(..) => {
                unreachable!("Should have been resolved after parsing {u:?}!")
            }
        }
    }
}

struct Vtable<'a> {
    item_id: ItemId,
    /// A reference to the originating compound object.
    #[allow(dead_code)]
    comp_info: &'a CompInfo,
}

impl<'a> Vtable<'a> {
    fn new(item_id: ItemId, comp_info: &'a CompInfo) -> Self {
        Vtable { item_id, comp_info }
    }
}

impl CodeGenerator for Vtable<'_> {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        assert_eq!(item.id(), self.item_id);
        debug_assert!(item.is_enabled_for_codegen(ctx));
        let name = ctx.rust_ident(self.canonical_name(ctx));

        // For now, we will only generate vtables for classes that:
        // - do not inherit from others (compilers merge VTable from primary parent class).
        // - do not contain a virtual destructor (requires ordering; platforms generate different vtables).
        if ctx.options().vtable_generation &&
            self.comp_info.base_members().is_empty() &&
            self.comp_info.destructor().is_none()
        {
            let class_ident = ctx.rust_ident(self.item_id.canonical_name(ctx));

            let methods = self
                .comp_info
                .methods()
                .iter()
                .filter_map(|m| {
                    if !m.is_virtual() {
                        return None;
                    }

                    let function_item = ctx.resolve_item(m.signature());
                    let function = function_item.expect_function();
                    let signature_item = ctx.resolve_item(function.signature());
                    let TypeKind::Function(ref signature) = signature_item.expect_type().kind() else { panic!("Function signature type mismatch") };

                    // FIXME: Is there a canonical name without the class prepended?
                    let function_name = function_item.canonical_name(ctx);

                    // FIXME: Need to account for overloading with times_seen (separately from regular function path).
                    let function_name = ctx.rust_ident(function_name);
                    let mut args = utils::fnsig_arguments(ctx, signature);
                    let ret = utils::fnsig_return_ty(ctx, signature);

                    args[0] = if m.is_const() {
                        quote! { this: *const #class_ident }
                    } else {
                        quote! { this: *mut #class_ident }
                    };

                    Some(quote! {
                        pub #function_name : unsafe extern "C" fn#( #args ),* ) #ret
                    })
                })
                .collect::<Vec<_>>();

            result.push(quote! {
                #[repr(C)]
                pub struct #name {
                    #( #methods ),*
                }
            });
        } else {
            // For the cases we don't support, simply generate an empty struct.
            let void = helpers::ast_ty::c_void(ctx);

            result.push(quote! {
                #[repr(C)]
                pub struct #name ( #void );
            });
        }
    }
}

impl ItemCanonicalName for Vtable<'_> {
    fn canonical_name(&self, ctx: &BindgenContext) -> String {
        format!("{}__bindgen_vtable"self.item_id.canonical_name(ctx))
    }
}

impl TryToRustTy for Vtable<'_> {
    type Extra = ();

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<syn::Type> {
        let name = ctx.rust_ident(self.canonical_name(ctx));
        Ok(syn::parse_quote! { #name })
    }
}

impl CodeGenerator for TemplateInstantiation {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        debug_assert!(item.is_enabled_for_codegen(ctx));

        // Although uses of instantiations don't need code generation, and are
        // just converted to rust types in fields, vars, etc, we take this
        // opportunity to generate tests for their layout here. If the
        // instantiation is opaque, then its presumably because we don't
        // properly understand it (maybe because of specializations), and so we
        // shouldn't emit layout tests either.
        if !ctx.options().layout_tests || self.is_opaque(ctx, item) {
            return;
        }

        // For consistency with other layout tests, gate this on offset_of.
        let compile_time = ctx.options().rust_features().offset_of;

        // If there are any unbound type parameters, then we can't generate a
        // layout test because we aren't dealing with a concrete type with a
        // concrete size and alignment.
        if ctx.uses_any_template_parameters(item.id()) {
            return;
        }

        let layout = item.kind().expect_type().layout(ctx);

        if let Some(layout) = layout {
            let size = layout.size;
            let align = layout.align;

            let name = item.full_disambiguated_name(ctx);
            let fn_name = if compile_time {
                None
            } else {
                let mut fn_name =
                    format!("__bindgen_test_layout_{name}_instantiation");
                let times_seen = result.overload_number(&fn_name);
                if times_seen > 0 {
                    write!(&mut fn_name, "_{times_seen}").unwrap();
                }
                Some(ctx.rust_ident_raw(fn_name))
            };

            let prefix = ctx.trait_prefix();
            let ident = item.to_rust_ty_or_opaque(ctx, &());
            let size_of_expr = quote! {
                ::#prefix::mem::size_of::<#ident>()
            };
            let align_of_expr = quote! {
                ::#prefix::mem::align_of::<#ident>()
            };
            let size_of_err =
                format!("Size of template specialization: {name}");
            let align_of_err =
                format!("Align of template specialization: {name}");

            if compile_time {
                // In an ideal world this would be assert_eq!, but that is not
                // supported in const fn due to the need for string formatting.
                // If #size_of_expr > #size, this will index OOB, and if
                // #size_of_expr < #size, the subtraction will overflow, both
                // of which print enough information to see what has gone wrong.
                result.push(quote! {
                    #[allow(clippy::unnecessary_operation, clippy::identity_op)]
                    const _: () = {
                        [#size_of_err][#size_of_expr - #size];
                        [#align_of_err][#align_of_expr - #align];
                    };
                });
            } else {
                result.push(quote! {
                    #[test]
                    fn #fn_name() {
                        assert_eq!(#size_of_expr#size#size_of_err);
                        assert_eq!(#align_of_expr#align#align_of_err);
                    }
                });
            }
        }
    }
}

/// Trait for implementing the code generation of a struct or union field.
trait FieldCodegen<'a> {
    type Extra;

    #[allow(clippy::too_many_arguments)]
    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        visibility_kind: FieldVisibilityKind,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        parent_item: &Item,
        last_field: bool,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        extra: Self::Extra,
    ) where
        F: Extend<proc_macro2::TokenStream>,
        M: Extend<proc_macro2::TokenStream>;
}

impl FieldCodegen<'_> for Field {
    type Extra = ();

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        visibility_kind: FieldVisibilityKind,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        parent_item: &Item,
        last_field: bool,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        _: (),
    ) where
        F: Extend<proc_macro2::TokenStream>,
        M: Extend<proc_macro2::TokenStream>,
    {
        match *self {
            Field::DataMember(ref data) => {
                data.codegen(
                    ctx,
                    visibility_kind,
                    accessor_kind,
                    parent,
                    parent_item,
                    last_field,
                    result,
                    struct_layout,
                    fields,
                    methods,
                    (),
                );
            }
            Field::Bitfields(ref unit) => {
                unit.codegen(
                    ctx,
                    visibility_kind,
                    accessor_kind,
                    parent,
                    parent_item,
                    last_field,
                    result,
                    struct_layout,
                    fields,
                    methods,
                    (),
                );
            }
        }
    }
}

fn wrap_union_field_if_needed(
    ctx: &BindgenContext,
    struct_layout: &StructLayoutTracker,
    ty: syn::Type,
    result: &mut CodegenResult,
) -> syn::Type {
    if struct_layout.is_rust_union() {
        if struct_layout.can_copy_union_fields() {
            ty
        } else {
            let prefix = ctx.trait_prefix();
            syn::parse_quote! { ::#prefix::mem::ManuallyDrop<#ty> }
        }
    } else {
        result.saw_bindgen_union();
        if ctx.options().enable_cxx_namespaces {
            syn::parse_quote! { root::__BindgenUnionField<#ty> }
        } else {
            syn::parse_quote! { __BindgenUnionField<#ty> }
        }
    }
}

impl FieldCodegen<'_> for FieldData {
    type Extra = ();

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        parent_visibility_kind: FieldVisibilityKind,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        parent_item: &Item,
        last_field: bool,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        _: (),
    ) where
        F: Extend<proc_macro2::TokenStream>,
        M: Extend<proc_macro2::TokenStream>,
    {
        // Bitfields are handled by `FieldCodegen` implementations for
        // `BitfieldUnit` and `Bitfield`.
        assert!(self.bitfield_width().is_none());

        let field_item =
            self.ty().into_resolver().through_type_refs().resolve(ctx);
        let field_ty = field_item.expect_type();
        let ty = self
            .ty()
            .to_rust_ty_or_opaque(ctx, &())
            .with_implicit_template_params(ctx, field_item);

        // NB: If supported, we use proper `union` types.
        let ty = if parent.is_union() {
            wrap_union_field_if_needed(ctx, struct_layout, ty, result)
        } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
            // Only FAM if its the last field
            if ctx.options().flexarray_dst && last_field {
                struct_layout.saw_flexible_array();
                syn::parse_quote! { FAM }
            } else {
                result.saw_incomplete_array();

                let inner = item.to_rust_ty_or_opaque(ctx, &());

                if ctx.options().enable_cxx_namespaces {
                    syn::parse_quote! { root::__IncompleteArrayField<#inner> }
                } else {
                    syn::parse_quote! { __IncompleteArrayField<#inner> }
                }
            }
        } else {
            ty
        };

        let mut field = quote! {};
        if ctx.options().generate_comments {
            if let Some(raw_comment) = self.comment() {
                let comment = ctx.options().process_comment(raw_comment);
                field = attributes::doc(&comment);
            }
        }

        let field_name = self
            .name()
            .map(|name| ctx.rust_mangle(name).into_owned())
            .expect("Each field should have a name in codegen!");
        let field_name = field_name.as_str();
        let field_ident = ctx.rust_ident_raw(field_name);

        if let Some(padding_field) =
            struct_layout.saw_field(field_name, field_ty, self.offset())
        {
            fields.extend(Some(padding_field));
        }

        let visibility = compute_visibility(
            ctx,
            self.is_public(),
            ctx.options().last_callback(|cb| {
                cb.field_visibility(FieldInfo {
                    type_name: &parent_item.canonical_name(ctx),
                    field_name,
                    field_type_name: field_ty.name(),
                })
            }),
            self.annotations(),
            parent_visibility_kind,
        );
        let accessor_kind =
            self.annotations().accessor_kind().unwrap_or(accessor_kind);

        match visibility {
            FieldVisibilityKind::Private => {
                field.append_all(quote! {
                    #field_ident : #ty ,
                });
            }
            FieldVisibilityKind::PublicCrate => {
                field.append_all(quote! {
                    pub(crate#field_ident : #ty ,
                });
            }
            FieldVisibilityKind::Public => {
                field.append_all(quote! {
                    pub #field_ident : #ty ,
                });
            }
        }

        fields.extend(Some(field));

        // TODO: Factor the following code out, please!
        if accessor_kind == FieldAccessorKind::None {
            return;
        }

        let getter_name = ctx.rust_ident_raw(format!("get_{field_name}"));
        let mutable_getter_name =
            ctx.rust_ident_raw(format!("get_{field_name}_mut"));

        methods.extend(Some(match accessor_kind {
            FieldAccessorKind::None => unreachable!(),
            FieldAccessorKind::Regular => {
                quote! {
                    #[inline]
                    pub fn #getter_name(&self) -> & #ty {
                        &self.#field_ident
                    }

                    #[inline]
                    pub fn #mutable_getter_name(&mut self) -> &>mut #ty {
                        &mut self.#field_ident
                    }
                }
            }
            FieldAccessorKind::Unsafe => {
                quote! {
                    #[inline]
                    pub unsafe fn #getter_name(&self) -> & #ty {
                        &self.#field_ident
                    }

                    #[inline]
                    pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty {
                        &mut self.#field_ident
                    }
                }
            }
            FieldAccessorKind::Immutable => {
                quote! {
                    #[inline]
                    pub fn #getter_name(&self) -> & #ty {
                        &self.#field_ident
                    }
                }
            }
        }));
    }
}

impl BitfieldUnit {
    /// Get the constructor name for this bitfield unit.
    fn ctor_name(&self) -> proc_macro2::TokenStream {
        let ctor_name = Ident::new(
            &format!("new_bitfield_{}"self.nth()),
            Span::call_site(),
        );
        quote! {
            #ctor_name
        }
    }
}

impl Bitfield {
    /// Extend an under construction bitfield unit constructor with this
    /// bitfield. This sets the relevant bits on the `__bindgen_bitfield_unit`
    /// variable that's being constructed.
    fn extend_ctor_impl(
        &self,
        ctx: &BindgenContext,
        param_name: &proc_macro2::TokenStream,
        mut ctor_impl: proc_macro2::TokenStream,
    ) -> proc_macro2::TokenStream {
        let bitfield_ty = ctx.resolve_type(self.ty());
        let bitfield_ty_layout = bitfield_ty
            .layout(ctx)
            .expect("Bitfield without layout? Gah!");
        let bitfield_int_ty = helpers::integer_type(bitfield_ty_layout).expect(
            "Should already have verified that the bitfield is \
                 representable as an int",
        );

        let offset = self.offset_into_unit();
        let width = self.width() as u8;
        let prefix = ctx.trait_prefix();

        ctor_impl.append_all(quote! {
            __bindgen_bitfield_unit.set(
                #offset,
                #width,
                {
                    let #param_name#bitfield_int_ty = unsafe {
                        ::#prefix::mem::transmute(#param_name)
                    };
                    #param_name as u64
                }
            );
        });

        ctor_impl
    }
}

fn access_specifier(
    visibility: FieldVisibilityKind,
) -> proc_macro2::TokenStream {
    match visibility {
        FieldVisibilityKind::Private => quote! {},
        FieldVisibilityKind::PublicCrate => quote! { pub(crate) },
        FieldVisibilityKind::Public => quote! { pub },
    }
}

/// Compute a fields or structs visibility based on multiple conditions.
/// 1. If the element was declared public, and we respect such CXX accesses specs
///    (context option) => By default Public, but this can be overruled by an `annotation`.
///
/// 2. If the element was declared private, and we respect such CXX accesses specs
///    (context option) => By default Private, but this can be overruled by an `annotation`.
///
/// 3. If we do not respect visibility modifiers, the result depends on the `annotation`,
///    if any, or the passed `default_kind`.
///
fn compute_visibility(
    ctx: &BindgenContext,
    is_declared_public: bool,
    callback_override: Option<FieldVisibilityKind>,
    annotations: &Annotations,
    default_kind: FieldVisibilityKind,
) -> FieldVisibilityKind {
    callback_override
        .or_else(|| annotations.visibility_kind())
        .unwrap_or_else(|| {
            match (is_declared_public, ctx.options().respect_cxx_access_specs) {
                (truetrue) => {
                    // declared as public, cxx specs are respected
                    FieldVisibilityKind::Public
                }
                (falsetrue) => {
                    // declared as private, cxx specs are respected
                    FieldVisibilityKind::Private
                }
                (_, false) => {
                    // cxx specs are not respected, declaration does not matter.
                    default_kind
                }
            }
        })
}

impl FieldCodegen<'_> for BitfieldUnit {
    type Extra = ();

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        visibility_kind: FieldVisibilityKind,
        accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        parent_item: &Item,
        last_field: bool,
        result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        fields: &mut F,
        methods: &mut M,
        _: (),
    ) where
        F: Extend<proc_macro2::TokenStream>,
        M: Extend<proc_macro2::TokenStream>,
    {
        use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;

        result.saw_bitfield_unit();

        let layout = self.layout();
        let unit_field_ty = helpers::bitfield_unit(ctx, layout);
        let field_ty = {
            let unit_field_ty = unit_field_ty.clone();
            if parent.is_union() {
                wrap_union_field_if_needed(
                    ctx,
                    struct_layout,
                    unit_field_ty,
                    result,
                )
            } else {
                unit_field_ty
            }
        };

        let unit_field_name = format!("_bitfield_{}"self.nth());
        let unit_field_ident = ctx.rust_ident(&unit_field_name);

        let ctor_name = self.ctor_name();
        let mut ctor_params = vec![];
        let mut ctor_impl = quote! {};

        // We cannot generate any constructor if the underlying storage can't
        // implement AsRef<[u8]> / AsMut<[u8]> / etc, or can't derive Default.
        //
        // We don't check `larger_arrays` here because Default does still have
        // the 32 items limitation.
        let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;

        let mut unit_visibility = visibility_kind;
        let bfields = self.bitfields();
        for (idx, bf) in bfields.iter().enumerate() {
            // Codegen not allowed for anonymous bitfields
            if bf.name().is_none() {
                continue;
            }

            let mut bitfield_representable_as_int = true;
            let mut bitfield_visibility = visibility_kind;
            bf.codegen(
                ctx,
                visibility_kind,
                accessor_kind,
                parent,
                parent_item,
                last_field && idx == bfields.len() - 1,
                result,
                struct_layout,
                fields,
                methods,
                (
                    &unit_field_name,
                    &unit_field_ty,
                    &mut bitfield_representable_as_int,
                    &mut bitfield_visibility,
                ),
            );
            if bitfield_visibility < unit_visibility {
                unit_visibility = bitfield_visibility;
            }

            // Generating a constructor requires the bitfield to be representable as an integer.
            if !bitfield_representable_as_int {
                generate_ctor = false;
                continue;
            }

            let param_name = bitfield_getter_name(ctx, bf);
            let bitfield_ty_item = ctx.resolve_item(bf.ty());
            let bitfield_ty = bitfield_ty_item.expect_type();
            let bitfield_ty =
                bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);

            ctor_params.push(quote! {
                #param_name : #bitfield_ty
            });
            ctor_impl = bf.extend_ctor_impl(ctx, ¶m_name, ctor_impl);
        }

        let access_spec = access_specifier(unit_visibility);

        let field = quote! {
            #access_spec #unit_field_ident : #field_ty ,
        };
        fields.extend(Some(field));

        if generate_ctor {
            methods.extend(Some(quote! {
                #[inline]
                #access_spec fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty {
                    let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default();
                    #ctor_impl
                    __bindgen_bitfield_unit
                }
            }));
        }

        struct_layout.saw_bitfield_unit(layout);
    }
}

fn bitfield_getter_name(
    ctx: &BindgenContext,
    bitfield: &Bitfield,
) -> proc_macro2::TokenStream {
    let name = bitfield.getter_name();
    let name = ctx.rust_ident_raw(name);
    quote! { #name }
}

fn bitfield_raw_getter_name(
    ctx: &BindgenContext,
    bitfield: &Bitfield,
) -> proc_macro2::TokenStream {
    let name = bitfield.getter_name();
    let name = ctx.rust_ident_raw(format!("{name}_raw"));
    quote! { #name }
}

fn bitfield_setter_name(
    ctx: &BindgenContext,
    bitfield: &Bitfield,
) -> proc_macro2::TokenStream {
    let setter = bitfield.setter_name();
    let setter = ctx.rust_ident_raw(setter);
    quote! { #setter }
}

fn bitfield_raw_setter_name(
    ctx: &BindgenContext,
    bitfield: &Bitfield,
) -> proc_macro2::TokenStream {
    let setter = bitfield.setter_name();
    let setter = ctx.rust_ident_raw(format!("{setter}_raw"));
    quote! { #setter }
}

impl<'a> FieldCodegen<'a> for Bitfield {
    type Extra = (
        &'a str,
        &'a syn::Type,
        &'a mut bool,
        &'a mut FieldVisibilityKind,
    );

    fn codegen<F, M>(
        &self,
        ctx: &BindgenContext,
        visibility_kind: FieldVisibilityKind,
        _accessor_kind: FieldAccessorKind,
        parent: &CompInfo,
        parent_item: &Item,
        _last_field: bool,
        _result: &mut CodegenResult,
        struct_layout: &mut StructLayoutTracker,
        _fields: &mut F,
        methods: &mut M,
        (
            unit_field_name,
            unit_field_ty,
            bitfield_representable_as_int,
            bitfield_visibility,
        ): (
            &'a str,
            &'a syn::Type,
            &mut bool,
            &'a mut FieldVisibilityKind,
        ),
    ) where
        F: Extend<proc_macro2::TokenStream>,
        M: Extend<proc_macro2::TokenStream>,
    {
        let prefix = ctx.trait_prefix();
        let getter_name = bitfield_getter_name(ctx, self);
        let setter_name = bitfield_setter_name(ctx, self);
        let raw_getter_name = bitfield_raw_getter_name(ctx, self);
        let raw_setter_name = bitfield_raw_setter_name(ctx, self);
        let unit_field_ident = Ident::new(unit_field_name, Span::call_site());

        let bitfield_ty_item = ctx.resolve_item(self.ty());
        let bitfield_ty = bitfield_ty_item.expect_type();
        let bitfield_ty_ident = bitfield_ty.name();

        let bitfield_ty_layout = bitfield_ty
            .layout(ctx)
            .expect("Bitfield without layout? Gah!");
        let bitfield_int_ty =
            if let Some(int_ty) = helpers::integer_type(bitfield_ty_layout) {
                *bitfield_representable_as_int = true;
                int_ty
            } else {
                *bitfield_representable_as_int = false;
                return;
            };

        let bitfield_ty =
            bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);

        let offset = self.offset_into_unit();
        let width = self.width() as u8;

        let override_visibility = self.name().and_then(|field_name| {
            ctx.options().last_callback(|cb| {
                cb.field_visibility(FieldInfo {
                    type_name: &parent_item.canonical_name(ctx),
                    field_name,
                    field_type_name: bitfield_ty_ident,
                })
            })
        });
        *bitfield_visibility = compute_visibility(
            ctx,
            self.is_public(),
            override_visibility,
            self.annotations(),
            visibility_kind,
        );
        let access_spec = access_specifier(*bitfield_visibility);

        if parent.is_union() && !struct_layout.is_rust_union() {
            methods.extend(Some(quote! {
                #[inline]
                #access_spec fn #getter_name(&self) -> #bitfield_ty {
                    unsafe {
                        ::#prefix::mem::transmute(
                            self.#unit_field_ident.as_ref().get(#offset#width)
                                as #bitfield_int_ty
                        )
                    }
                }

                #[inline]
                #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
                    unsafe {
                        let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
                        self.#unit_field_ident.as_mut().set(
                            #offset,
                            #width,
                            val as u64
                        )
                    }
                }
            }));

            methods.extend(Some(quote! {
                #[inline]
                #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty {
                    unsafe {
                        ::#prefix::mem::transmute(<#unit_field_ty>::raw_get(
                            (*::#prefix::ptr::addr_of!((*this).#unit_field_ident)).as_ref() as *const _,
                            #offset,
                            #width,
                        ) as #bitfield_int_ty)
                    }
                }

                #[inline]
                #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) {
                    unsafe {
                        let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
                        <#unit_field_ty>::raw_set(
                            (*::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident)).as_mut() as *mut _,
                            #offset,
                            #width,
                            val as u64,
                        )
                    }
                }
            }));
        } else {
            methods.extend(Some(quote! {
                #[inline]
                #access_spec fn #getter_name(&self) -> #bitfield_ty {
                    unsafe {
                        ::#prefix::mem::transmute(
                            self.#unit_field_ident.get(#offset#width)
                                as #bitfield_int_ty
                        )
                    }
                }

                #[inline]
                #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
                    unsafe {
                        let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
                        self.#unit_field_ident.set(
                            #offset,
                            #width,
                            val as u64
                        )
                    }
                }
            }));

            methods.extend(Some(quote! {
                #[inline]
                #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty {
                    unsafe {
                        ::#prefix::mem::transmute(<#unit_field_ty>::raw_get(
                            ::#prefix::ptr::addr_of!((*this).#unit_field_ident),
                            #offset,
                            #width,
                        ) as #bitfield_int_ty)
                    }
                }

                #[inline]
                #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) {
                    unsafe {
                        let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
                        <#unit_field_ty>::raw_set(
                            ::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident),
                            #offset,
                            #width,
                            val as u64,
                        )
                    }
                }
            }));
        }
    }
}

impl CodeGenerator for CompInfo {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        debug!("<CompInfo as CodeGenerator>::codegen: item = {item:?}");
        debug_assert!(item.is_enabled_for_codegen(ctx));

        // Don't output classes with template parameters that aren't types, and
        // also don't output template specializations, neither total or partial.
        if self.has_non_type_template_params() {
            return;
        }

        let ty = item.expect_type();
        let layout = ty.layout(ctx);
        let mut packed = self.is_packed(ctx, layout.as_ref());

        let canonical_name = item.canonical_name(ctx);
        let canonical_ident = ctx.rust_ident(&canonical_name);

        // Generate the vtable from the method list if appropriate.
        //
        // TODO: I don't know how this could play with virtual methods that are
        // not in the list of methods found by us, we'll see. Also, could the
        // order of the vtable pointers vary?
        //
        // FIXME: Once we generate proper vtables, we need to codegen the
        // vtable, but *not* generate a field for it in the case that
        // HasVtable::has_vtable_ptr is false but HasVtable::has_vtable is true.
        //
        // Also, we need to generate the vtable in such a way it "inherits" from
        // the parent too.
        let is_opaque = item.is_opaque(ctx, &());
        let mut fields = vec![];
        let visibility = item
            .annotations()
            .visibility_kind()
            .unwrap_or(ctx.options().default_visibility);
        let mut struct_layout = StructLayoutTracker::new(
            ctx,
            self,
            ty,
            &canonical_name,
            visibility,
            packed,
        );

        let mut generic_param_names = vec![];

        for (idx, ty) in item.used_template_params(ctx).iter().enumerate() {
            let param = ctx.resolve_type(*ty);
            let name = param.name().unwrap();
            let ident = ctx.rust_ident(name);
            generic_param_names.push(ident.clone());

            let prefix = ctx.trait_prefix();
            let field_name = ctx.rust_ident(format!("_phantom_{idx}"));
            fields.push(quote! {
                pub #field_name : ::#prefix::marker::PhantomData<
                    ::#prefix::cell::UnsafeCell<#ident>
                > ,
            });
        }

        if !is_opaque {
            if item.has_vtable_ptr(ctx) {
                let vtable = Vtable::new(item.id(), self);
                vtable.codegen(ctx, result, item);

                let vtable_type = vtable
                    .try_to_rust_ty(ctx, &())
                    .expect("vtable to Rust type conversion is infallible")
                    .to_ptr(true);

                fields.push(quote! {
                    pub vtable_: #vtable_type ,
                });

                struct_layout.saw_vtable();
            }

            for base in self.base_members() {
                if !base.requires_storage(ctx) {
                    continue;
                }

                let inner_item = ctx.resolve_item(base.ty);
                let inner = inner_item
                    .to_rust_ty_or_opaque(ctx, &())
                    .with_implicit_template_params(ctx, inner_item);
                let field_name = ctx.rust_ident(&base.field_name);

                struct_layout.saw_base(inner_item.expect_type());

                let visibility = match (
                    base.is_public(),
                    ctx.options().respect_cxx_access_specs,
                ) {
                    (truetrue) => FieldVisibilityKind::Public,
                    (falsetrue) => FieldVisibilityKind::Private,
                    _ => ctx.options().default_visibility,
                };

                let access_spec = access_specifier(visibility);
                fields.push(quote! {
                    #access_spec #field_name#inner,
                });
            }
        }

        let mut methods = vec![];
        if !is_opaque {
            let struct_accessor_kind = item
                .annotations()
                .accessor_kind()
                .unwrap_or(FieldAccessorKind::None);
            let field_decls = self.fields();
            for (idx, field) in field_decls.iter().enumerate() {
                field.codegen(
                    ctx,
                    visibility,
                    struct_accessor_kind,
                    self,
                    item,
                    idx == field_decls.len() - 1,
                    result,
                    &mut struct_layout,
                    &mut fields,
                    &mut methods,
                    (),
                );
            }
            // Check whether an explicit padding field is needed
            // at the end.
            if let Some(comp_layout) = layout {
                fields.extend(
                    struct_layout
                        .add_tail_padding(&canonical_name, comp_layout),
                );
            }
        }

        if is_opaque {
            // Opaque item should not have generated methods, fields.
            debug_assert!(fields.is_empty());
            debug_assert!(methods.is_empty());
        }

        let is_union = self.kind() == CompKind::Union;
        let layout = item.kind().expect_type().layout(ctx);
        let zero_sized = item.is_zero_sized(ctx);
        let forward_decl = self.is_forward_declaration();

        let mut explicit_align = None;

        // C++ requires every struct to be addressable, so what C++ compilers do
        // is making the struct 1-byte sized.
        //
        // This is apparently not the case for C, see:
        // https://github.com/rust-lang/rust-bindgen/issues/551
        //
        // Just get the layout, and assume C++ if not.
        //
        // NOTE: This check is conveniently here to avoid the dummy fields we
        // may add for unused template parameters.
        if !forward_decl && zero_sized {
            let has_address = if is_opaque {
                // Generate the address field if it's an opaque type and
                // couldn't determine the layout of the blob.
                layout.is_none()
            } else {
                layout.map_or(true, |l| l.size != 0)
            };

            if has_address {
                let layout = Layout::new(11);
                struct_layout.saw_field_with_layout(
                    "_address",
                    layout,
                    /* offset = */ Some(0),
                );
                fields.push(quote! {
                    pub _address: u8,
                });
            }
        }

        if is_opaque {
            match layout {
                Some(l) => {
                    explicit_align = Some(l.align);
                    let ty = helpers::blob(ctx, l, false);
                    fields.push(quote! {
                        pub _bindgen_opaque_blob: #ty ,
                    });
                }
                None => {
                    if !forward_decl {
                        warn!("Opaque type without layout! Expect dragons!");
                    }
                }
            }
        } else if !is_union && !zero_sized {
            if let Some(padding_field) =
                layout.and_then(|layout| struct_layout.pad_struct(layout))
            {
                fields.push(padding_field);
            }

            if let Some(layout) = layout {
                if struct_layout.requires_explicit_align(layout) {
                    if layout.align == 1 {
                        packed = true;
                    } else {
                        explicit_align = Some(layout.align);
                    }
                }
            }
        } else if is_union && !forward_decl {
            if let Some(layout) = layout {
                // TODO(emilio): It'd be nice to unify this with the struct path above somehow.
                if struct_layout.requires_explicit_align(layout) {
                    explicit_align = Some(layout.align);
                }
                if !struct_layout.is_rust_union() {
                    let ty = helpers::blob(ctx, layout, false);
                    fields.push(quote! {
                        pub bindgen_union_field: #ty,
                    });
                }
            }
        }

        if forward_decl {
            fields.push(quote! {
                _unused: [u8; 0],
            });
        }

        let (flex_array_generic, flex_inner_ty) = if ctx.options().flexarray_dst
        {
            match self.flex_array_member(ctx) {
                Some(ty) => {
                    let inner = ty.to_rust_ty_or_opaque(ctx, &());
                    (
                        Some(quote! { FAM: ?Sized = [ #inner0 ] }),
                        Some(quote! { #inner }),
                    )
                }
                None => (None, None),
            }
        } else {
            (None, None)
        };

        // Generics, including the flexible array member.
        //
        // generics - generic parameters for the struct declaration
        // impl_generics_labels - generic parameters for `impl<...>`
        // impl_generics_params - generic parameters for `impl structname<...>`
        //
        // `impl` blocks are for non-FAM related impls like Default, etc
        let (generics, impl_generics_labels, impl_generics_params) =
            if !generic_param_names.is_empty() || flex_array_generic.is_some() {
                let (flex_sized, flex_fam) = match flex_inner_ty.as_ref() {
                    None => (None, None),
                    Some(ty) => (
                        Some(quote! { [ #ty0 ] }),
                        Some(quote! { FAM: ?Sized = [ #ty0 ] }),
                    ),
                };

                (
                    quote! {
                        < #( #generic_param_names , )* #flex_fam >
                    },
                    quote! {
                        < #( #generic_param_names , )* >
                    },
                    quote! {
                        < #( #generic_param_names , )* #flex_sized >
                    },
                )
            } else {
                (quote! {}, quote! {}, quote! {})
            };

        let mut attributes = vec![];
        let mut needs_clone_impl = false;
        let mut needs_default_impl = false;
        let mut needs_debug_impl = false;
        let mut needs_partialeq_impl = false;
        let needs_flexarray_impl = flex_array_generic.is_some();
        if let Some(comment) = item.comment(ctx) {
            attributes.push(attributes::doc(&comment));
        }

        // if a type has both a "packed" attribute and an "align(N)" attribute, then check if the
        // "packed" attr is redundant, and do not include it if so.
        if packed &&
            !is_opaque &&
            !(explicit_align.is_some() &&
                self.already_packed(ctx).unwrap_or(false))
        {
            let n = layout.map_or(1, |l| l.align);
            let packed_repr = if n == 1 {
                "packed".to_string()
            } else {
                format!("packed({n})")
            };
            attributes.push(attributes::repr_list(&["C", &packed_repr]));
        } else {
            attributes.push(attributes::repr("C"));
        }

        // Ensure that the struct has the correct alignment even in presence of alignas and co.
        if let Some(explicit) = explicit_align {
            // If we need explicit alignment and can do it, we prefer to insert a dummy field at
            // the beginning of the struct. This avoids hitting
            // https://github.com/rust-lang/rust-bindgen/issues/2179
            // Do it for bitfields only for now for backwards compat.
            if self.has_bitfields() && explicit <= 8 {
                let align_ty = match explicit {
                    8 => quote! { u64 },
                    4 => quote! { u32 },
                    2 => quote! { u16 },
                    _ => quote! { u8  },
                };
                let align_field = quote! {
                    pub _bindgen_align: [#align_ty0],
                };
                fields.insert(0, align_field);
            } else {
                let explicit = helpers::ast_ty::int_expr(explicit as i64);
                attributes.push(quote! {
                    #[repr(align(#explicit))]
                });
            }
        }

        let derivable_traits = derives_of_item(item, ctx, packed);
        if !derivable_traits.contains(DerivableTraits::DEBUG) {
            needs_debug_impl = ctx.options().derive_debug &&
                ctx.options().impl_debug &&
                !ctx.no_debug_by_name(item) &&
                !item.annotations().disallow_debug();
        }

        if !derivable_traits.contains(DerivableTraits::DEFAULT) {
            needs_default_impl = ctx.options().derive_default &&
                !self.is_forward_declaration() &&
                !ctx.no_default_by_name(item) &&
                !item.annotations().disallow_default();
        }

        let all_template_params = item.all_template_params(ctx);

        if derivable_traits.contains(DerivableTraits::COPY) &&
            !derivable_traits.contains(DerivableTraits::CLONE)
        {
            needs_clone_impl = true;
        }

        if !derivable_traits.contains(DerivableTraits::PARTIAL_EQ) {
            needs_partialeq_impl = ctx.options().derive_partialeq &&
                ctx.options().impl_partialeq &&
                ctx.lookup_can_derive_partialeq_or_partialord(item.id()) ==
                    CanDerive::Manually;
        }

        let mut derives: Vec<_> = derivable_traits.into();
        derives.extend(item.annotations().derives().iter().map(String::as_str));

        let is_rust_union = is_union && struct_layout.is_rust_union();

        utils::call_discovered_item_callback(ctx, item, || match self.kind() {
            CompKind::Struct => DiscoveredItem::Struct {
                original_name: item
                    .kind()
                    .expect_type()
                    .name()
                    .map(String::from),
                final_name: canonical_ident.to_string(),
            },
            CompKind::Union => DiscoveredItem::Union {
                original_name: item
                    .kind()
                    .expect_type()
                    .name()
                    .map(String::from),
                final_name: canonical_ident.to_string(),
            },
        });

        // The custom derives callback may return a list of derive attributes;
        // add them to the end of the list.
        let custom_derives = ctx.options().all_callbacks(|cb| {
            cb.add_derives(&DeriveInfo {
                name: &canonical_name,
                kind: if is_rust_union {
                    DeriveTypeKind::Union
                } else {
                    DeriveTypeKind::Struct
                },
            })
        });
        // In most cases this will be a no-op, since custom_derives will be empty.
        derives.extend(custom_derives.iter().map(|s| s.as_str()));

        if !derives.is_empty() {
            attributes.push(attributes::derives(&derives));
        }

        attributes.extend(
            item.annotations()
                .attributes()
                .iter()
                .map(|s| s.parse().unwrap()),
        );

        let custom_attributes = ctx.options().all_callbacks(|cb| {
            cb.add_attributes(&AttributeInfo {
                name: &canonical_name,
                kind: if is_rust_union {
                    DeriveTypeKind::Union
                } else {
                    DeriveTypeKind::Struct
                },
            })
        });
        attributes.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));

        if item.must_use(ctx) {
            attributes.push(attributes::must_use());
        }

        let mut tokens = if is_rust_union {
            quote! {
                #( #attributes )*
                pub union #canonical_ident
            }
        } else {
            quote! {
                #( #attributes )*
                pub struct #canonical_ident
            }
        };

        tokens.append_all(quote! {
            #generics {
                #( #fields )*
            }
        });
        result.push(tokens);

        // Generate the inner types and all that stuff.
        //
        // TODO: In the future we might want to be smart, and use nested
        // modules, and whatnot.
        for ty in self.inner_types() {
            let child_item = ctx.resolve_item(*ty);
            // assert_eq!(child_item.parent_id(), item.id());
            child_item.codegen(ctx, result, &());
        }

        // NOTE: Some unexposed attributes (like alignment attributes) may
        // affect layout, so we're bad and pray to the gods for avoid sending
        // all the tests to shit when parsing things like max_align_t.
        if self.found_unknown_attr() {
            warn!("Type {canonical_ident} has an unknown attribute that may affect layout");
        }

        if all_template_params.is_empty() {
            if !is_opaque {
                for var in self.inner_vars() {
                    ctx.resolve_item(*var).codegen(ctx, result, &());
                }
            }

            if ctx.options().layout_tests && !self.is_forward_declaration() {
                if let Some(layout) = layout {
                    let compile_time = ctx.options().rust_features().offset_of;
                    let fn_name = if compile_time {
                        None
                    } else {
                        let fn_name =
                            format!("bindgen_test_layout_{canonical_ident}");
                        Some(ctx.rust_ident_raw(fn_name))
                    };
                    let prefix = ctx.trait_prefix();
                    let size_of_expr = quote! {
                        ::#prefix::mem::size_of::<#canonical_ident>()
                    };
                    let align_of_expr = quote! {
                        ::#prefix::mem::align_of::<#canonical_ident>()
                    };
                    let size = layout.size;
                    let align = layout.align;
                    let size_of_err = format!("Size of {canonical_ident}");
                    let align_of_err =
                        format!("Alignment of {canonical_ident}");

                    let check_struct_align = if compile_time {
                        quote! {
                            [#align_of_err][#align_of_expr - #align];
                        }
                    } else {
                        quote! {
                            assert_eq!(#align_of_expr#align#align_of_err);
                        }
                    };

                    let should_skip_field_offset_checks = is_opaque;

                    let check_field_offset = if should_skip_field_offset_checks
                    {
                        vec![]
                    } else {
                        self.fields()
                            .iter()
                            .filter_map(|field| {
                                let Field::DataMember(field) = field else { return None };
                                let name = field.name()?;
                                field.offset().map(|offset| {
                                    let field_offset = offset / 8;
                                    let field_name = ctx.rust_ident(name);
                                    let offset_of_err = format!("Offset of field: {canonical_ident}::{field_name}");
                                    if compile_time {
                                        quote! {
                                            [#offset_of_err][
                                                ::#prefix::mem::offset_of!(#canonical_ident#field_name) - #field_offset
                                            ];
                                        }
                                    } else {
                                        quote! {
                                            assert_eq!(
                                                unsafe {
                                                    ::#prefix::ptr::addr_of!((*ptr).#field_nameas usize - ptr as usize
                                                },
                                                #field_offset,
                                                #offset_of_err
                                            );
                                        }
                                    }
                                })
                            })
                            .collect()
                    };

                    let uninit_decl = if check_field_offset.is_empty() ||
                        compile_time
                    {
                        None
                    } else {
                        // FIXME: When MSRV >= 1.59.0, we can use
                        // > const PTR: *const #canonical_ident = ::#prefix::mem::MaybeUninit::uninit().as_ptr();
                        Some(quote! {
                            // Use a shared MaybeUninit so that rustc with
                            // opt-level=0 doesn't take too much stack space,
                            // see #2218.
                            const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit();
                            let ptr = UNINIT.as_ptr();
                        })
                    };

                    if compile_time {
                        result.push(quote! {
                            #[allow(clippy::unnecessary_operation, clippy::identity_op)]
                            const _: () = {
                                [#size_of_err][#size_of_expr - #size];
                                #check_struct_align
                                #( #check_field_offset )*
                            };
                        });
                    } else {
                        result.push(quote! {
                            #[test]
                            fn #fn_name() {
                                #uninit_decl
                                assert_eq!(#size_of_expr#size#size_of_err);
                                #check_struct_align
                                #( #check_field_offset )*
                            }
                        });
                    }
                }
            }

            let mut method_names = Default::default();
            let discovered_id = DiscoveredItemId::new(item.id().as_usize());
            if ctx.options().codegen_config.methods() {
                for method in self.methods() {
                    assert_ne!(method.kind(), MethodKind::Constructor);
                    method.codegen_method(
                        ctx,
                        &mut methods,
                        &mut method_names,
                        result,
                        self,
                        discovered_id,
                    );
                }
            }

            if ctx.options().codegen_config.constructors() {
                for sig in self.constructors() {
                    Method::new(
                        MethodKind::Constructor,
                        *sig,
                        /* const */
                        false,
                    )
                    .codegen_method(
                        ctx,
                        &mut methods,
                        &mut method_names,
                        result,
                        self,
                        discovered_id,
                    );
                }
            }

            if ctx.options().codegen_config.destructors() {
                if let Some((kind, destructor)) = self.destructor() {
                    debug_assert!(kind.is_destructor());
                    Method::new(kind, destructor, false).codegen_method(
                        ctx,
                        &mut methods,
                        &mut method_names,
                        result,
                        self,
                        discovered_id,
                    );
                }
            }
        }

        // NB: We can't use to_rust_ty here since for opaque types this tries to
        // use the specialization knowledge to generate a blob field.
        let ty_for_impl = quote! {
            #canonical_ident #impl_generics_params
        };

        if needs_clone_impl {
            result.push(quote! {
                impl #impl_generics_labels Clone for #ty_for_impl {
                    fn clone(&self) -> Self { *self }
                }
            });
        }

        if needs_flexarray_impl {
            result.push(self.generate_flexarray(
                ctx,
                &canonical_ident,
                flex_inner_ty.as_ref(),
                &generic_param_names,
                &impl_generics_labels,
            ));
        }

        if needs_default_impl {
            let prefix = ctx.trait_prefix();
            let body = quote! {
                let mut s = ::#prefix::mem::MaybeUninit::<Self>::uninit();
                unsafe {
                    ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 01);
                    s.assume_init()
                }
            };
            // Note we use `ptr::write_bytes()` instead of `mem::zeroed()` because the latter does
            // not necessarily ensure padding bytes are zeroed. Some C libraries are sensitive to
            // non-zero padding bytes, especially when forwards/backwards compatibility is
            // involved.
            result.push(quote! {
                impl #impl_generics_labels Default for #ty_for_impl {
                    fn default() -> Self {
                        #body
                    }
                }
            });
        }

        if needs_debug_impl {
            let impl_ = impl_debug::gen_debug_impl(
                ctx,
                self.fields(),
                item,
                self.kind(),
            );

            let prefix = ctx.trait_prefix();

            result.push(quote! {
                impl #impl_generics_labels ::#prefix::fmt::Debug for #ty_for_impl {
                    #impl_
                }
            });
        }

        if needs_partialeq_impl {
            if let Some(impl_) = impl_partialeq::gen_partialeq_impl(
                ctx,
                self,
                item,
                &ty_for_impl,
            ) {
                let partialeq_bounds = if generic_param_names.is_empty() {
                    quote! {}
                } else {
                    let bounds = generic_param_names.iter().map(|t| {
                        quote! { #t: PartialEq }
                    });
                    quote! { where #( #bounds ),* }
                };

                let prefix = ctx.trait_prefix();
                result.push(quote! {
                    impl #impl_generics_labels ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds {
                        #impl_
                    }
                });
            }
        }

        if !methods.is_empty() {
            result.push(quote! {
                impl #impl_generics_labels #ty_for_impl {
                    #( #methods )*
                }
            });
        }
    }
}

impl CompInfo {
    fn generate_flexarray(
        &self,
        ctx: &BindgenContext,
        canonical_ident: &Ident,
        flex_inner_ty: Option<&proc_macro2::TokenStream>,
        generic_param_names: &[Ident],
        impl_generics_labels: &proc_macro2::TokenStream,
    ) -> proc_macro2::TokenStream {
        let prefix = ctx.trait_prefix();

        let flex_array = flex_inner_ty.as_ref().map(|ty| quote! { [ #ty ] });

        let dst_ty_for_impl = quote! {
            #canonical_ident < #( #generic_param_names , )* #flex_array >

        };
        let sized_ty_for_impl = quote! {
            #canonical_ident < #( #generic_param_names , )* [ #flex_inner_ty0 ] >
        };

        let layout = if ctx.options().rust_features().layout_for_ptr {
            quote! {
                pub fn layout(len: usize) -> ::#prefix::alloc::Layout {
                    // SAFETY: Null pointers are OK if we don't deref them
                    unsafe {
                        let p: *const Self = ::#prefix::ptr::from_raw_parts(::#prefix::ptr::null::<()>(), len);
                        ::#prefix::alloc::Layout::for_value_raw(p)
                    }
                }
            }
        } else {
            quote!()
        };

        let (from_ptr_dst, from_ptr_sized) = if ctx
            .options()
            .rust_features()
            .ptr_metadata
        {
            let flex_ref_inner = ctx.wrap_unsafe_ops(quote! {
                Self::flex_ptr(self, len)
            });
            let flex_ref_mut_inner = ctx.wrap_unsafe_ops(quote! {
                Self::flex_ptr_mut(self, len).assume_init()
            });
            let flex_ptr_inner = ctx.wrap_unsafe_ops(quote! {
                &*::#prefix::ptr::from_raw_parts(ptr as *const (), len)
            });
            let flex_ptr_mut_inner = ctx.wrap_unsafe_ops(quote! {
                // Initialize reference without ever exposing it, as its possibly uninitialized
                let mut uninit = ::#prefix::mem::MaybeUninit::<&mut #dst_ty_for_impl>::uninit();
                (uninit.as_mut_ptr() as *mut *mut #dst_ty_for_impl)
                    .write(::#prefix::ptr::from_raw_parts_mut(ptr as *mut (), len));

                uninit
            });

            (
                quote! {
                    #[inline]
                    pub fn fixed(&self) -> (& #sized_ty_for_impl, usize) {
                        unsafe {
                            let (ptr, len) = (self as *const Self).to_raw_parts();
                            (&*(ptr as *const #sized_ty_for_impl), len)
                        }
                    }

                    #[inline]
                    pub fn fixed_mut(&mut self) -> (&mut #sized_ty_for_impl, usize) {
                        unsafe {
                            let (ptr, len) = (self as *mut Self).to_raw_parts();
                            (&mut *(ptr as *mut #sized_ty_for_impl), len)
                        }
                    }
                },
                quote! {
                    /// Convert a sized prefix to an unsized structure with the given length.
                    ///
                    /// SAFETY: Underlying storage is initialized up to at least `len` elements.
                    pub unsafe fn flex_ref(&self, len: usize) -> &#dst_ty_for_impl {
                        // SAFETY: Reference is always valid as pointer. Caller is guaranteeing `len`.
                        #flex_ref_inner
                    }

                    /// Convert a mutable sized prefix to an unsized structure with the given length.
                    ///
                    /// SAFETY: Underlying storage is initialized up to at least `len` elements.
                    #[inline]
                    pub unsafe fn flex_ref_mut(&mut self, len: usize) -> &mut #dst_ty_for_impl {
                        // SAFETY: Reference is always valid as pointer. Caller is guaranteeing `len`.
                        #flex_ref_mut_inner
                    }

                    /// Construct DST variant from a pointer and a size.
                    ///
                    /// NOTE: lifetime of returned reference is not tied to any underlying storage.
                    /// SAFETY: `ptr` is valid. Underlying storage is fully initialized up to at least `len` elements.
                    #[inline]
                    pub unsafe fn flex_ptr<'unbounded>(ptr: *const Self, len: usize) -> &'unbounded #dst_ty_for_impl {
                       #flex_ptr_inner
                    }

                    /// Construct mutable DST variant from a pointer and a
                    /// size. The returned `&mut` reference is initialized
                    /// pointing to memory referenced by `ptr`, but there's
                    /// no requirement that that memory be initialized.
                    ///
                    /// NOTE: lifetime of returned reference is not tied to any underlying storage.
                    /// SAFETY: `ptr` is valid. Underlying storage has space for at least `len` elements.
                    #[inline]
                    pub unsafe fn flex_ptr_mut<'unbounded>(
                        ptr: *mut Self,
                        len: usize,
                    ) -> ::#prefix::mem::MaybeUninit<&'unbounded mut #dst_ty_for_impl> {
                        #flex_ptr_mut_inner
                    }
                },
            )
        } else {
            (quote!(), quote!())
        };

        quote! {
            impl #impl_generics_labels #dst_ty_for_impl {
                #layout
                #from_ptr_dst
            }

            impl #impl_generics_labels #sized_ty_for_impl {
                #from_ptr_sized
            }
        }
    }
}

impl Method {
    fn codegen_method(
        &self,
        ctx: &BindgenContext,
        methods: &mut Vec<proc_macro2::TokenStream>,
        method_names: &mut HashSet<String>,
        result: &mut CodegenResult<'_>,
        _parent: &CompInfo,
        parent_id: DiscoveredItemId,
    ) {
        assert!({
            let cc = &ctx.options().codegen_config;
            match self.kind() {
                MethodKind::Constructor => cc.constructors(),
                MethodKind::Destructor |
                MethodKind::VirtualDestructor { .. } => cc.destructors(),
                MethodKind::Static |
                MethodKind::Normal |
                MethodKind::Virtual { .. } => cc.methods(),
            }
        });

        // TODO(emilio): We could generate final stuff at least.
        if self.is_virtual() {
            return// FIXME
        }

        // First of all, output the actual function.
        let function_item = ctx.resolve_item(self.signature());
        if !function_item.process_before_codegen(ctx, result) {
            return;
        }
        let function = function_item.expect_function();
        let times_seen = function.codegen(ctx, result, function_item);
        let Some(times_seen) = times_seen else { return };
        let signature_item = ctx.resolve_item(function.signature());
        let mut name = match self.kind() {
            MethodKind::Constructor => "new".into(),
            MethodKind::Destructor => "destruct".into(),
            _ => function.name().to_owned(),
        };

        let TypeKind::Function(ref signature) =
            *signature_item.expect_type().kind()
        else {
            panic!("How in the world?")
        };

        let supported_abi = signature.abi(ctx, Some(&*name)).is_ok();
        if !supported_abi {
            return;
        }

        // Do not generate variadic methods, since rust does not allow
        // implementing them, and we don't do a good job at it anyway.
        if signature.is_variadic() {
            return;
        }

        if method_names.contains(&name) {
            let mut count = 1;
            let mut new_name;

            while {
                new_name = format!("{name}{count}");
                method_names.contains(&new_name)
            } {
                count += 1;
            }

            name = new_name;
        }

        method_names.insert(name.clone());

        utils::call_discovered_item_callback(ctx, function_item, || {
            DiscoveredItem::Method {
                parent: parent_id,
                final_name: name.clone(),
            }
        });

        let mut function_name = function_item.canonical_name(ctx);
        if times_seen > 0 {
            write!(&mut function_name, "{times_seen}").unwrap();
        }
        let function_name = ctx.rust_ident(function_name);
        let mut args = utils::fnsig_arguments(ctx, signature);
        let mut ret = utils::fnsig_return_ty(ctx, signature);

        if !self.is_static() && !self.is_constructor() {
            args[0] = if self.is_const() {
                quote! { &self }
            } else {
                quote! { &mut self }
            };
        }

        // If it's a constructor, we always return `Self`, and we inject the
        // "this" parameter, so there's no need to ask the user for it.
        //
        // Note that constructors in Clang are represented as functions with
        // return-type = void.
        if self.is_constructor() {
            args.remove(0);
            ret = quote! { -> Self };
        }

        let mut exprs =
            helpers::ast_ty::arguments_from_signature(signature, ctx);

        let mut stmts = vec![];

        // If it's a constructor, we need to insert an extra parameter with a
        // variable called `__bindgen_tmp` we're going to create.
        if self.is_constructor() {
            let prefix = ctx.trait_prefix();
            exprs[0] = quote! {
                __bindgen_tmp.as_mut_ptr()
            };
            let tmp_variable_decl = quote! {
                let mut __bindgen_tmp = ::#prefix::mem::MaybeUninit::uninit()
            };
            stmts.push(tmp_variable_decl);
        } else if !self.is_static() {
            assert!(!exprs.is_empty());
            exprs[0] = quote! {
                self
            };
        }

        let call = quote! {
            #function_name (#( #exprs ),* )
        };

        stmts.push(call);

        if self.is_constructor() {
            stmts.push(quote! {
                    __bindgen_tmp.assume_init()
            });
        }

        let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*));

        let mut attrs = vec![attributes::inline()];

        if signature.must_use() {
            attrs.push(attributes::must_use());
        }

        let name = ctx.rust_ident(&name);
        methods.push(quote! {
            #(#attrs)*
            pub unsafe fn #name ( #( #args ),* ) #ret {
                #block
            }
        });
    }
}

/// A helper type that represents different enum variations.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
pub enum EnumVariation {
    /// The code for this enum will use a Rust enum. Note that creating this in unsafe code
    /// (including FFI) with an invalid value will invoke undefined behaviour, whether or not
    /// its marked as `#[non_exhaustive]`.
    Rust {
        /// Indicates whether the generated struct should be `#[non_exhaustive]`
        non_exhaustive: bool,
    },
    /// The code for this enum will use a newtype
    NewType {
        /// Indicates whether the newtype will have bitwise operators
        is_bitfield: bool,
        /// Indicates whether the variants will be represented as global constants
        is_global: bool,
    },
    /// The code for this enum will use consts
    #[default]
    Consts,
    /// The code for this enum will use a module containing consts
    ModuleConsts,
}

impl EnumVariation {
    fn is_rust(self) -> bool {
        matches!(self, EnumVariation::Rust { .. })
    }

    /// Both the `Const` and `ModuleConsts` variants will cause this to return
    /// true.
    fn is_const(self) -> bool {
        matches!(self, EnumVariation::Consts | EnumVariation::ModuleConsts)
    }
}

impl fmt::Display for EnumVariation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::Rust {
                non_exhaustive: false,
            } => "rust",
            Self::Rust {
                non_exhaustive: true,
            } => "rust_non_exhaustive",
            Self::NewType {
                is_bitfield: true, ..
            } => "bitfield",
            Self::NewType {
                is_bitfield: false,
                is_global,
            } => {
                if *is_global {
                    "newtype_global"
                } else {
                    "newtype"
                }
            }
            Self::Consts => "consts",
            Self::ModuleConsts => "moduleconsts",
        };
        s.fmt(f)
    }
}

impl FromStr for EnumVariation {
    type Err = std::io::Error;

    /// Create a `EnumVariation` from a string.
    fn from_str(s: &str) -> Result<SelfSelf::Err> {
        match s {
            "rust" => Ok(EnumVariation::Rust {
                non_exhaustive: false,
            }),
            "rust_non_exhaustive" => Ok(EnumVariation::Rust {
                non_exhaustive: true,
            }),
            "bitfield" => Ok(EnumVariation::NewType {
                is_bitfield: true,
                is_global: false,
            }),
            "consts" => Ok(EnumVariation::Consts),
            "moduleconsts" => Ok(EnumVariation::ModuleConsts),
            "newtype" => Ok(EnumVariation::NewType {
                is_bitfield: false,
                is_global: false,
            }),
            "newtype_global" => Ok(EnumVariation::NewType {
                is_bitfield: false,
                is_global: true,
            }),
            _ => Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                concat!(
                    "Got an invalid EnumVariation. Accepted values ",
                    "are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',",
                    "'moduleconsts', 'newtype' and 'newtype_global'."
                ),
            )),
        }
    }
}

struct EnumBuilder {
    /// Type identifier of the enum.
    ///
    /// This is the base name, i.e. for `ModuleConst` enums, this does not include the module name.
    enum_type: Ident,
    /// Attributes applying to the enum type
    attrs: Vec<proc_macro2::TokenStream>,
    /// The representation of the enum, e.g. `u32`.
    repr: syn::Type,
    /// The enum kind we are generating
    kind: EnumBuilderKind,
    /// A list of all variants this enum has.
    enum_variants: Vec<EnumVariantInfo>,
}

/// A helper type to construct different enum variations.
enum EnumBuilderKind {
    Rust {
        non_exhaustive: bool,
    },
    NewType {
        is_bitfield: bool,
        is_global: bool,
        /// if the enum is named or not.
        is_anonymous: bool,
    },
    Consts {
        needs_typedef: bool,
    },
    ModuleConsts {
        module_name: Ident,
    },
}

impl EnumBuilder {
    /// Returns true if the builder is for a rustified enum.
    fn is_rust_enum(&self) -> bool {
        matches!(self.kind, EnumBuilderKind::Rust { .. })
    }

    /// Create a new enum given an item builder, a canonical name, a name for
    /// the representation, and which variation it should be generated as.
    fn new(
        name: &str,
        attrs: Vec<proc_macro2::TokenStream>,
        repr: &syn::Type,
        enum_variation: EnumVariation,
        has_typedef: bool,
        enum_is_anonymous: bool,
    ) -> Self {
        let ident = Ident::new(name, Span::call_site());
        // For most variants this is the same
        let mut enum_ty = ident.clone();

        let kind = match enum_variation {
            EnumVariation::NewType {
                is_bitfield,
                is_global,
            } => EnumBuilderKind::NewType {
                is_bitfield,
                is_global,
                is_anonymous: enum_is_anonymous,
            },

            EnumVariation::Rust { non_exhaustive } => {
                EnumBuilderKind::Rust { non_exhaustive }
            }

            EnumVariation::Consts => EnumBuilderKind::Consts {
                needs_typedef: !has_typedef,
            },

            EnumVariation::ModuleConsts => {
                enum_ty = Ident::new(
                    CONSTIFIED_ENUM_MODULE_REPR_NAME,
                    Span::call_site(),
                );

                EnumBuilderKind::ModuleConsts {
                    module_name: ident.clone(),
                }
            }
        };
        EnumBuilder {
            enum_type: enum_ty,
            attrs,
            repr: repr.clone(),
            kind,
            enum_variants: vec![],
        }
    }

    /// Add a variant to this enum.
    fn with_variant(
        mut self,
        ctx: &BindgenContext,
        variant: &EnumVariant,
        variant_doc: proc_macro2::TokenStream,
        mangling_prefix: Option<&str>,
        rust_ty: &syn::Type,
        is_ty_named: bool,
    ) -> Self {
        let variant_name = ctx.rust_mangle(variant.name());
        let is_rust_enum = self.is_rust_enum();
        let expr = match variant.val() {
            EnumVariantValue::Boolean(v) if is_rust_enum => {
                helpers::ast_ty::uint_expr(u64::from(v))
            }
            EnumVariantValue::Boolean(v) => quote!(#v),
            EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
            EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
        };

        match self.kind {
            EnumBuilderKind::Rust { .. } => {
                let name = ctx.rust_ident(variant_name);
                self.enum_variants.push(EnumVariantInfo {
                    variant_name: name,
                    variant_doc,
                    value: expr,
                });
                self
            }

            EnumBuilderKind::NewType { is_global, .. } => {
                let variant_ident = if is_ty_named && !is_global {
                    ctx.rust_ident(variant_name)
                } else {
                    ctx.rust_ident(match mangling_prefix {
                        Some(prefix) => {
                            Cow::Owned(format!("{prefix}_{variant_name}"))
                        }
                        None => variant_name,
                    })
                };
                self.enum_variants.push(EnumVariantInfo {
                    variant_name: variant_ident,
                    variant_doc,
                    value: quote! { #rust_ty ( #expr )},
                });

                self
            }

            EnumBuilderKind::Consts { .. } => {
                let constant_name = match mangling_prefix {
                    Some(prefix) => {
                        Cow::Owned(format!("{prefix}_{variant_name}"))
                    }
                    None => variant_name,
                };

                let ident = ctx.rust_ident(constant_name);
                self.enum_variants.push(EnumVariantInfo {
                    variant_name: ident,
                    variant_doc,
                    value: quote! { #expr },
                });

                self
            }
            EnumBuilderKind::ModuleConsts { .. } => {
                let name = ctx.rust_ident(variant_name);
                self.enum_variants.push(EnumVariantInfo {
                    variant_name: name,
                    variant_doc,
                    value: quote! { #expr },
                });
                self
            }
        }
    }

    fn newtype_bitfield_impl(
        prefix: &Ident,
        rust_ty: &syn::Type,
    ) -> proc_macro2::TokenStream {
        let rust_ty_name = &rust_ty;
        quote! {
            impl ::#prefix::ops::BitOr<#rust_tyfor #rust_ty {
                type Output = Self;

                #[inline]
                fn bitor(self, other: Self) -> Self {
                    #rust_ty_name(self.0 | other.0)
                }
            }
            impl ::#prefix::ops::BitOrAssign for #rust_ty {
                #[inline]
                fn bitor_assign(&mut self, rhs: #rust_ty) {
                    self.0 |= rhs.0;
                }
            }
            impl ::#prefix::ops::BitAnd<#rust_tyfor #rust_ty {
                type Output = Self;

                #[inline]
                fn bitand(self, other: Self) -> Self {
                    #rust_ty_name(self.0 & other.0)
                }
            }
            impl ::#prefix::ops::BitAndAssign for #rust_ty {
                #[inline]
                fn bitand_assign(&mut self, rhs: #rust_ty) {
                    self.0 &= rhs.0;
                }
            }
        }
    }

    fn build(
        self,
        ctx: &BindgenContext,
        rust_ty: &syn::Type,
    ) -> proc_macro2::TokenStream {
        let enum_ident = self.enum_type;

        // 1. Construct a list of the enum variants
        let variants = match self.kind {
            EnumBuilderKind::Rust { .. } => {
                let mut variants = vec![];

                for v in self.enum_variants {
                    let variant_doc = &v.variant_doc;
                    let variant_ident = &v.variant_name;
                    let variant_value = &v.value;

                    variants.push(quote! {
                        #variant_doc
                        #variant_ident = #variant_value,
                    });
                }

                if variants.is_empty() {
                    variants.push(
                        quote! {__bindgen_cannot_repr_c_on_empty_enum = 0,},
                    );
                }
                variants
            }
            EnumBuilderKind::NewType { .. } => {
                let mut variants = vec![];

                for v in self.enum_variants {
                    let variant_doc = &v.variant_doc;
                    let variant_ident = &v.variant_name;
                    let variant_value = &v.value;

                    variants.push(quote! {
                        #variant_doc
                        pub const #variant_ident#enum_ident = #variant_value;
                    });
                }
                variants
            }
            EnumBuilderKind::Consts { .. } |
            EnumBuilderKind::ModuleConsts { .. } => {
                let mut variants = vec![];

                for v in self.enum_variants {
                    let variant_doc = &v.variant_doc;
                    let variant_ident = &v.variant_name;
                    let variant_value = &v.value;

                    variants.push(quote! {
                        #variant_doc
                        pub const #variant_ident#enum_ident = #variant_value;
                    });
                }
                variants
            }
        };
        let attrs = self.attrs;
        let enum_repr = &self.repr;

        // 2. Generate the enum representation
        match self.kind {
            EnumBuilderKind::Rust { non_exhaustive } => {
                let non_exhaustive_opt =
                    non_exhaustive.then(attributes::non_exhaustive);

                quote! {
                    // Note: repr is on top of attrs to keep the test expectations diff small.
                    // a future commit could move it further down.
                    #[repr(#enum_repr)]
                    #non_exhaustive_opt
                    #( #attrs )*
                    pub enum #enum_ident {
                        #( #variants )*
                    }
                }
            }
            EnumBuilderKind::NewType {
                is_bitfield,
                is_global,
                is_anonymous,
            } => {
                // There doesn't seem to be a technical reason why we generate
                // anon enum variants as global constants.
                // We keep this behavior to avoid breaking changes in the bindings.
                let impl_variants = if is_anonymous || is_global {
                    quote! {
                        #( #variants )*
                    }
                } else {
                    quote! {
                        impl #enum_ident {
                            #( #variants )*
                        }
                    }
                };

                let prefix = ctx.trait_prefix();
                let bitfield_impl_opt = is_bitfield
                    .then(|| Self::newtype_bitfield_impl(&prefix, rust_ty));

                quote! {
                    // Previously variant impls where before the enum definition.
                    // lets keep this as is for now, to reduce the diff in generated bindings.
                    #impl_variants

                    #bitfield_impl_opt

                    #[repr(transparent)]
                    #( #attrs )*
                    pub struct #enum_ident (pub #enum_repr);
                }
            }
            EnumBuilderKind::Consts { needs_typedef } => {
                let typedef_opt = needs_typedef.then(|| {
                    quote! {
                        #( #attrs )*
                        pub type #enum_ident = #enum_repr;
                    }
                });
                quote! {
                    #( #variants )*

                    #typedef_opt
                }
            }
            EnumBuilderKind::ModuleConsts { module_name, .. } => {
                quote! {
                    // todo: Probably some attributes, e.g. `cfg` should apply to the `mod`.
                    pub mod #module_name {
                        #( #attrs )*
                        pub type #enum_ident = #enum_repr;

                        #( #variants )*
                    }
                }
            }
        }
    }
}

impl CodeGenerator for Enum {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        debug!("<Enum as CodeGenerator>::codegen: item = {item:?}");
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let name = item.canonical_name(ctx);
        let ident = ctx.rust_ident(&name);
        let enum_ty = item.expect_type();
        let layout = enum_ty.layout(ctx);
        let variation = self.computed_enum_variation(ctx, item);

        let repr_translated;
        let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) {
            Some(repr)
                if !ctx.options().translate_enum_integer_types &&
                    !variation.is_rust() =>
            {
                repr
            }
            repr => {
                // An enum's integer type is translated to a native Rust
                // integer type in 3 cases:
                // * the enum is Rustified and we need a translated type for
                //   the repr attribute
                // * the representation couldn't be determined from the C source
                // * it was explicitly requested as a bindgen option

                let kind = if let Some(repr) = repr {
                    match *repr.canonical_type(ctx).kind() {
                        TypeKind::Int(int_kind) => int_kind,
                        _ => panic!("Unexpected type as enum repr"),
                    }
                } else {
                    warn!(
                        "Guessing type of enum! Forward declarations of enums \
                         shouldn't be legal!"
                    );
                    IntKind::Int
                };

                let signed = kind.is_signed();
                let size = layout
                    .map(|l| l.size)
                    .or_else(|| kind.known_size())
                    .unwrap_or(0);

                let translated = match (signed, size) {
                    (true1) => IntKind::I8,
                    (false1) => IntKind::U8,
                    (true2) => IntKind::I16,
                    (false2) => IntKind::U16,
                    (true4) => IntKind::I32,
                    (false4) => IntKind::U32,
                    (true8) => IntKind::I64,
                    (false8) => IntKind::U64,
                    _ => {
                        warn!(
                            "invalid enum decl: signed: {signed}, size: {size}"
                        );
                        IntKind::I32
                    }
                };

                repr_translated =
                    Type::new(None, None, TypeKind::Int(translated), false);
                &repr_translated
            }
        };

        let mut attrs = vec![];

        if let Some(comment) = item.comment(ctx) {
            attrs.push(attributes::doc(&comment));
        }

        if item.must_use(ctx) {
            attrs.push(attributes::must_use());
        }

        if !variation.is_const() {
            let packed = false// Enums can't be packed in Rust.
            let mut derives = derives_of_item(item, ctx, packed);
            // For backwards compat, enums always derive
            // Clone/Eq/PartialEq/Hash, even if we don't generate those by
            // default.
            derives.insert(
                DerivableTraits::CLONE |
                    DerivableTraits::HASH |
                    DerivableTraits::PARTIAL_EQ |
                    DerivableTraits::EQ,
            );
            let mut derives: Vec<_> = derives.into();
            for derive in item.annotations().derives() {
                if !derives.contains(&derive.as_str()) {
                    derives.push(derive);
                }
            }

            // The custom derives callback may return a list of derive attributes;
            // add them to the end of the list.
            let custom_derives = ctx.options().all_callbacks(|cb| {
                cb.add_derives(&DeriveInfo {
                    name: &name,
                    kind: DeriveTypeKind::Enum,
                })
            });
            // In most cases this will be a no-op, since custom_derives will be empty.
            derives.extend(custom_derives.iter().map(|s| s.as_str()));

            attrs.extend(
                item.annotations()
                    .attributes()
                    .iter()
                    .map(|s| s.parse().unwrap()),
            );

            // The custom attribute callback may return a list of attributes;
            // add them to the end of the list.
            let custom_attributes = ctx.options().all_callbacks(|cb| {
                cb.add_attributes(&AttributeInfo {
                    name: &name,
                    kind: DeriveTypeKind::Enum,
                })
            });
            attrs.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));

            attrs.push(attributes::derives(&derives));
        }

        fn add_constant(
            ctx: &BindgenContext,
            enum_: &Type,
            // Only to avoid recomputing every time.
            enum_canonical_name: &Ident,
            // May be the same as "variant" if it's because the
            // enum is unnamed and we still haven't seen the
            // value.
            variant_name: &Ident,
            referenced_name: &Ident,
            enum_rust_ty: &syn::Type,
            result: &mut CodegenResult<'_>,
        ) {
            let constant_name = if enum_.name().is_some() {
                if ctx.options().prepend_enum_name {
                    format!("{enum_canonical_name}_{variant_name}")
                } else {
                    format!("{variant_name}")
                }
            } else {
                format!("{variant_name}")
            };
            let constant_name = ctx.rust_ident(constant_name);

            result.push(quote! {
                pub const #constant_name : #enum_rust_ty =
                    #enum_canonical_name :: #referenced_name ;
            });
        }

        let repr = repr.to_rust_ty_or_opaque(ctx, item);
        let has_typedef = ctx.is_enum_typedef_combo(item.id());

        utils::call_discovered_item_callback(ctx, item, || {
            DiscoveredItem::Enum {
                final_name: name.clone(),
            }
        });

        let mut builder = EnumBuilder::new(
            &name,
            attrs,
            &repr,
            variation,
            has_typedef,
            enum_ty.name().is_none(),
        );

        // A map where we keep a value -> variant relation.
        let mut seen_values = HashMap::<_, Ident>::default();
        let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &());
        let is_toplevel = item.is_toplevel(ctx);

        // Used to mangle the constants we generate in the unnamed-enum case.
        let parent_canonical_name = if is_toplevel {
            None
        } else {
            Some(item.parent_id().canonical_name(ctx))
        };

        let constant_mangling_prefix = if ctx.options().prepend_enum_name {
            if enum_ty.name().is_none() {
                parent_canonical_name.as_deref()
            } else {
                Some(&*name)
            }
        } else {
            None
        };

        // NB: We defer the creation of constified variants, in case we find
        // another variant with the same value (which is the common thing to
        // do).
        let mut constified_variants = VecDeque::new();

        let mut iter = self.variants().iter().peekable();
        while let Some(variant) =
            iter.next().or_else(|| constified_variants.pop_front())
        {
            if variant.hidden() {
                continue;
            }

            if variant.force_constification() && iter.peek().is_some() {
                constified_variants.push_back(variant);
                continue;
            }

            let mut variant_doc = quote! {};
            if ctx.options().generate_comments {
                if let Some(raw_comment) = variant.comment() {
                    let processed_comment =
                        ctx.options().process_comment(raw_comment);
                    variant_doc = attributes::doc(&processed_comment);
                }
            }

            match seen_values.entry(variant.val()) {
                Entry::Occupied(ref entry) => {
                    if variation.is_rust() {
                        let variant_name = ctx.rust_mangle(variant.name());
                        let mangled_name = if is_toplevel ||
                            enum_ty.name().is_some()
                        {
                            variant_name
                        } else {
                            let parent_name =
                                parent_canonical_name.as_ref().unwrap();

                            Cow::Owned(format!("{parent_name}_{variant_name}"))
                        };

                        let existing_variant_name = entry.get();
                        // Use associated constants for named enums.
                        if enum_ty.name().is_some() {
                            let enum_canonical_name = &ident;
                            let variant_name =
                                ctx.rust_ident_raw(&*mangled_name);
                            result.push(quote! {
                                impl #enum_rust_ty {
                                    pub const #variant_name : #enum_rust_ty =
                                        #enum_canonical_name :: #existing_variant_name ;
                                }
                            });
                        } else {
                            add_constant(
                                ctx,
                                enum_ty,
                                &ident,
                                &Ident::new(&mangled_name, Span::call_site()),
                                existing_variant_name,
                                &enum_rust_ty,
                                result,
                            );
                        }
                    } else {
                        builder = builder.with_variant(
                            ctx,
                            variant,
                            variant_doc,
                            constant_mangling_prefix,
                            &enum_rust_ty,
                            enum_ty.name().is_some(),
                        );
                    }
                }
                Entry::Vacant(entry) => {
                    builder = builder.with_variant(
                        ctx,
                        variant,
                        variant_doc,
                        constant_mangling_prefix,
                        &enum_rust_ty,
                        enum_ty.name().is_some(),
                    );

                    let variant_name = ctx.rust_ident(variant.name());

                    // If it's an unnamed enum, or constification is enforced,
                    // we also generate a constant so it can be properly
                    // accessed.
                    if (variation.is_rust() && enum_ty.name().is_none()) ||
                        variant.force_constification()
                    {
                        let mangled_name = if is_toplevel {
                            variant_name.clone()
                        } else {
                            let parent_name =
                                parent_canonical_name.as_ref().unwrap();

                            Ident::new(
                                &format!("{parent_name}_{variant_name}"),
                                Span::call_site(),
                            )
                        };

                        add_constant(
                            ctx,
                            enum_ty,
                            &ident,
                            &mangled_name,
                            &variant_name,
                            &enum_rust_ty,
                            result,
                        );
                    }

                    entry.insert(variant_name);
                }
            }
        }

        let item = builder.build(ctx, &enum_rust_ty);
        result.push(item);
    }
}

struct EnumVariantInfo {
    variant_name: Ident,
    variant_doc: proc_macro2::TokenStream,
    value: proc_macro2::TokenStream,
}

/// Enum for the default type of macro constants.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
pub enum MacroTypeVariation {
    /// Use i32 or i64
    Signed,
    /// Use u32 or u64
    #[default]
    Unsigned,
}

impl fmt::Display for MacroTypeVariation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::Signed => "signed",
            Self::Unsigned => "unsigned",
        };
        s.fmt(f)
    }
}

impl FromStr for MacroTypeVariation {
    type Err = std::io::Error;

    /// Create a `MacroTypeVariation` from a string.
    fn from_str(s: &str) -> Result<SelfSelf::Err> {
        match s {
            "signed" => Ok(MacroTypeVariation::Signed),
            "unsigned" => Ok(MacroTypeVariation::Unsigned),
            _ => Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                concat!(
                    "Got an invalid MacroTypeVariation. Accepted values ",
                    "are 'signed' and 'unsigned'"
                ),
            )),
        }
    }
}

/// Enum for how aliases should be translated.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
pub enum AliasVariation {
    /// Convert to regular Rust alias
    #[default]
    TypeAlias,
    /// Create a new type by wrapping the old type in a struct and using #[repr(transparent)]
    NewType,
    /// Same as `NewType` but also impl Deref to be able to use the methods of the wrapped type
    NewTypeDeref,
}

impl fmt::Display for AliasVariation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::TypeAlias => "type_alias",
            Self::NewType => "new_type",
            Self::NewTypeDeref => "new_type_deref",
        };

        s.fmt(f)
    }
}

impl FromStr for AliasVariation {
    type Err = std::io::Error;

    /// Create an `AliasVariation` from a string.
    fn from_str(s: &str) -> Result<SelfSelf::Err> {
        match s {
            "type_alias" => Ok(AliasVariation::TypeAlias),
            "new_type" => Ok(AliasVariation::NewType),
            "new_type_deref" => Ok(AliasVariation::NewTypeDeref),
            _ => Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                concat!(
                    "Got an invalid AliasVariation. Accepted values ",
                    "are 'type_alias', 'new_type', and 'new_type_deref'"
                ),
            )),
        }
    }
}

/// Enum for how non-`Copy` `union`s should be translated.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum NonCopyUnionStyle {
    /// Wrap members in a type generated by `bindgen`.
    BindgenWrapper,
    /// Wrap members in [`::core::mem::ManuallyDrop`].
    ///
    /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your
    /// MSRV is lower.
    ManuallyDrop,
}

impl fmt::Display for NonCopyUnionStyle {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            Self::BindgenWrapper => "bindgen_wrapper",
            Self::ManuallyDrop => "manually_drop",
        };

        s.fmt(f)
    }
}

impl Default for NonCopyUnionStyle {
    fn default() -> Self {
        Self::BindgenWrapper
    }
}

impl FromStr for NonCopyUnionStyle {
    type Err = std::io::Error;

    fn from_str(s: &str) -> Result<SelfSelf::Err> {
        match s {
            "bindgen_wrapper" => Ok(Self::BindgenWrapper),
            "manually_drop" => Ok(Self::ManuallyDrop),
            _ => Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                concat!(
                    "Got an invalid NonCopyUnionStyle. Accepted values ",
                    "are 'bindgen_wrapper' and 'manually_drop'"
                ),
            )),
        }
    }
}

/// Fallible conversion to an opaque blob.
///
/// Implementors of this trait should provide the `try_get_layout` method to
/// fallibly get this thing's layout, which the provided `try_to_opaque` trait
/// method will use to convert the `Layout` into an opaque blob Rust type.
pub(cratetrait TryToOpaque {
    type Extra;

    /// Get the layout for this thing, if one is available.
    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> error::Result<Layout>;

    /// Do not override this provided trait method.
    fn try_to_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> error::Result<syn::Type> {
        self.try_get_layout(ctx, extra)
            .map(|layout| helpers::blob(ctx, layout, true))
    }
}

/// Infallible conversion of an IR thing to an opaque blob.
///
/// The resulting layout is best effort, and is unfortunately not guaranteed to
/// be correct. When all else fails, we fall back to a single byte layout as a
/// last resort, because C++ does not permit zero-sized types. See the note in
/// the `ToRustTyOrOpaque` doc comment about fallible versus infallible traits
/// and when each is appropriate.
///
/// Don't implement this directly. Instead implement `TryToOpaque`, and then
/// leverage the blanket impl for this trait.
pub(cratetrait ToOpaque: TryToOpaque {
    fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
        self.try_get_layout(ctx, extra)
            .unwrap_or_else(|_| Layout::for_size(ctx, 1))
    }

    fn to_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> syn::Type {
        let layout = self.get_layout(ctx, extra);
        helpers::blob(ctx, layout, true)
    }
}

impl<T> ToOpaque for T where T: TryToOpaque {}

/// Fallible conversion from an IR thing to an *equivalent* Rust type.
///
/// If the C/C++ construct represented by the IR thing cannot (currently) be
/// represented in Rust (for example, instantiations of templates with
/// const-value generic parameters) then the impl should return an `Err`. It
/// should *not* attempt to return an opaque blob with the correct size and
/// alignment. That is the responsibility of the `TryToOpaque` trait.
pub(cratetrait TryToRustTy {
    type Extra;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        extra: &Self::Extra,
    ) -> error::Result<syn::Type>;
}

/// Fallible conversion to a Rust type or an opaque blob with the correct size
/// and alignment.
///
/// Don't implement this directly. Instead implement `TryToRustTy` and
/// `TryToOpaque`, and then leverage the blanket impl for this trait below.
pub(cratetrait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque {
    type Extra;

    fn try_to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &<Self as TryToRustTyOrOpaque>::Extra,
    ) -> error::Result<syn::Type>;
}

impl<E, T> TryToRustTyOrOpaque for T
where
    T: TryToRustTy<Extra = E> + TryToOpaque<Extra = E>,
{
    type Extra = E;

    fn try_to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &E,
    ) -> error::Result<syn::Type> {
        self.try_to_rust_ty(ctx, extra).or_else(|_| {
            if let Ok(layout) = self.try_get_layout(ctx, extra) {
                Ok(helpers::blob(ctx, layout, true))
            } else {
                Err(Error::NoLayoutForOpaqueBlob)
            }
        })
    }
}

/// Infallible conversion to a Rust type, or an opaque blob with a best effort
/// of correct size and alignment.
///
/// Don't implement this directly. Instead implement `TryToRustTy` and
/// `TryToOpaque`, and then leverage the blanket impl for this trait below.
///
/// ### Fallible vs. Infallible Conversions to Rust Types
///
/// When should one use this infallible `ToRustTyOrOpaque` trait versus the
/// fallible `TryTo{RustTy, Opaque, RustTyOrOpaque}` traits? All fallible trait
/// implementations that need to convert another thing into a Rust type or
/// opaque blob in a nested manner should also use fallible trait methods and
/// propagate failure up the stack. Only infallible functions and methods like
/// `CodeGenerator` implementations should use the infallible
/// `ToRustTyOrOpaque`. The further out we push error recovery, the more likely
/// we are to get a usable `Layout` even if we can't generate an equivalent Rust
/// type for a C++ construct.
pub(cratetrait ToRustTyOrOpaque: TryToRustTy + ToOpaque {
    type Extra;

    fn to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &<Self as ToRustTyOrOpaque>::Extra,
    ) -> syn::Type;
}

impl<E, T> ToRustTyOrOpaque for T
where
    T: TryToRustTy<Extra = E> + ToOpaque<Extra = E>,
{
    type Extra = E;

    fn to_rust_ty_or_opaque(
        &self,
        ctx: &BindgenContext,
        extra: &E,
    ) -> syn::Type {
        self.try_to_rust_ty(ctx, extra)
            .unwrap_or_else(|_| self.to_opaque(ctx, extra))
    }
}

impl<T> TryToOpaque for T
where
    T: Copy + Into<ItemId>,
{
    type Extra = ();

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<Layout> {
        ctx.resolve_item((*self).into()).try_get_layout(ctx, &())
    }
}

impl<T> TryToRustTy for T
where
    T: Copy + Into<ItemId>,
{
    type Extra = ();

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<syn::Type> {
        ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &())
    }
}

impl TryToOpaque for Item {
    type Extra = ();

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<Layout> {
        self.kind().expect_type().try_get_layout(ctx, self)
    }
}

impl TryToRustTy for Item {
    type Extra = ();

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        _: &(),
    ) -> error::Result<syn::Type> {
        self.kind().expect_type().try_to_rust_ty(ctx, self)
    }
}

impl TryToOpaque for Type {
    type Extra = Item;

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        _: &Item,
    ) -> error::Result<Layout> {
        self.layout(ctx).ok_or(Error::NoLayoutForOpaqueBlob)
    }
}

impl TryToRustTy for Type {
    type Extra = Item;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<syn::Type> {
        use self::helpers::ast_ty::*;

        match *self.kind() {
            TypeKind::Void => Ok(c_void(ctx)),
            // TODO: we should do something smart with nullptr, or maybe *const
            // c_void is enough?
            TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)),
            TypeKind::Int(ik) => {
                Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
            }
            TypeKind::Float(fk) => {
                Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
            }
            TypeKind::Complex(fk) => {
                let float_path =
                    float_kind_rust_type(ctx, fk, self.layout(ctx));

                ctx.generated_bindgen_complex();
                Ok(if ctx.options().enable_cxx_namespaces {
                    syn::parse_quote! { root::__BindgenComplex<#float_path> }
                } else {
                    syn::parse_quote! { __BindgenComplex<#float_path> }
                })
            }
            TypeKind::Function(ref signature) => {
                // We can't rely on the sizeof(Option<NonZero<_>>) ==
                // sizeof(NonZero<_>) optimization with opaque blobs (because
                // they aren't NonZero), so don't *ever* use an or_opaque
                // variant here.
                let ty = signature.try_to_rust_ty(ctx, item)?;

                let prefix = ctx.trait_prefix();
                Ok(syn::parse_quote! { ::#prefix::option::Option<#ty> })
            }
            TypeKind::Array(item, len) | TypeKind::Vector(item, len) => {
                let ty = item.try_to_rust_ty(ctx, &())?;
                Ok(syn::parse_quote! { [ #ty ; #len ] })
            }
            TypeKind::Enum(..) => {
                let path = item.namespace_aware_canonical_path(ctx);
                let path = proc_macro2::TokenStream::from_str(&path.join("::"))
                    .unwrap();
                Ok(syn::parse_quote!(#path))
            }
            TypeKind::TemplateInstantiation(ref inst) => {
                inst.try_to_rust_ty(ctx, item)
            }
            TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
            TypeKind::TemplateAlias(..) |
            TypeKind::Alias(..) |
            TypeKind::BlockPointer(..) => {
                if self.is_block_pointer() && !ctx.options().generate_block {
                    let void = c_void(ctx);
                    return Ok(void.to_ptr(/* is_const = */ false));
                }

                if item.is_opaque(ctx, &()) &&
                    item.used_template_params(ctx)
                        .into_iter()
                        .any(|param| param.is_template_param(ctx, &()))
                {
                    self.try_to_opaque(ctx, item)
                } else if let Some(ty) = self
                    .name()
                    .and_then(|name| utils::type_from_named(ctx, name))
                {
                    Ok(ty)
                } else {
                    utils::build_path(item, ctx)
                }
            }
            TypeKind::Comp(ref info) => {
                let template_params = item.all_template_params(ctx);
                if info.has_non_type_template_params() ||
                    (item.is_opaque(ctx, &()) && !template_params.is_empty())
                {
                    return self.try_to_opaque(ctx, item);
                }

                utils::build_path(item, ctx)
            }
            TypeKind::Opaque => self.try_to_opaque(ctx, item),
            TypeKind::Pointer(inner) | TypeKind::Reference(inner) => {
                // Check that this type has the same size as the target's pointer type.
                let size = self.get_layout(ctx, item).size;
                if size != ctx.target_pointer_size() {
                    return Err(Error::InvalidPointerSize {
                        ty_name: self.name().unwrap_or("unknown").into(),
                        ty_size: size,
                        ptr_size: ctx.target_pointer_size(),
                    });
                }

                let is_const = ctx.resolve_type(inner).is_const();

                let inner =
                    inner.into_resolver().through_type_refs().resolve(ctx);
                let inner_ty = inner.expect_type();

                let is_objc_pointer =
                    matches!(inner_ty.kind(), TypeKind::ObjCInterface(..));

                // Regardless if we can properly represent the inner type, we
                // should always generate a proper pointer here, so use
                // infallible conversion of the inner type.
                let ty = inner
                    .to_rust_ty_or_opaque(ctx, &())
                    .with_implicit_template_params(ctx, inner);

                // Avoid the first function pointer level, since it's already
                // represented in Rust.
                if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer
                {
                    Ok(ty)
                } else {
                    Ok(ty.to_ptr(is_const))
                }
            }
            TypeKind::TypeParam => {
                let name = item.canonical_name(ctx);
                let ident = ctx.rust_ident(name);
                Ok(syn::parse_quote! { #ident })
            }
            TypeKind::ObjCSel => Ok(syn::parse_quote! { objc::runtime::Sel }),
            TypeKind::ObjCId => Ok(syn::parse_quote! { id }),
            TypeKind::ObjCInterface(ref interface) => {
                let name = ctx.rust_ident(interface.name());
                Ok(syn::parse_quote! { #name })
            }
            ref u @ TypeKind::UnresolvedTypeRef(..) => {
                unreachable!("Should have been resolved after parsing {u:?}!")
            }
        }
    }
}

impl TryToOpaque for TemplateInstantiation {
    type Extra = Item;

    fn try_get_layout(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<Layout> {
        item.expect_type()
            .layout(ctx)
            .ok_or(Error::NoLayoutForOpaqueBlob)
    }
}

impl TryToRustTy for TemplateInstantiation {
    type Extra = Item;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<syn::Type> {
        if self.is_opaque(ctx, item) {
            return Err(Error::InstantiationOfOpaqueType);
        }

        let def = self
            .template_definition()
            .into_resolver()
            .through_type_refs()
            .resolve(ctx);

        let mut ty = quote! {};
        let def_path = def.namespace_aware_canonical_path(ctx);
        ty.append_separated(
            def_path.into_iter().map(|p| ctx.rust_ident(p)),
            quote!(::),
        );

        let def_params = def.self_template_params(ctx);
        if def_params.is_empty() {
            // This can happen if we generated an opaque type for a partial
            // template specialization, and we've hit an instantiation of
            // that partial specialization.
            extra_assert!(def.is_opaque(ctx, &()));
            return Err(Error::InstantiationOfOpaqueType);
        }

        // TODO: If the definition type is a template class/struct
        // definition's member template definition, it could rely on
        // generic template parameters from its outer template
        // class/struct. When we emit bindings for it, it could require
        // *more* type arguments than we have here, and we will need to
        // reconstruct them somehow. We don't have any means of doing
        // that reconstruction at this time.

        let template_args = self
            .template_arguments()
            .iter()
            .zip(def_params.iter())
            // Only pass type arguments for the type parameters that
            // the def uses.
            .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param))
            .map(|(arg, _)| {
                let arg = arg.into_resolver().through_type_refs().resolve(ctx);
                let ty = arg
                    .try_to_rust_ty(ctx, &())?
                    .with_implicit_template_params(ctx, arg);
                Ok(ty)
            })
            .collect::<error::Result<Vec<_>>>()?;

        Ok(if template_args.is_empty() {
            syn::parse_quote! { #ty }
        } else {
            syn::parse_quote! { #ty<#(#template_args),*> }
        })
    }
}

impl TryToRustTy for FunctionSig {
    type Extra = Item;

    fn try_to_rust_ty(
        &self,
        ctx: &BindgenContext,
        item: &Item,
    ) -> error::Result<syn::Type> {
        // TODO: we might want to consider ignoring the reference return value.
        let ret = utils::fnsig_return_ty(ctx, self);
        let arguments = utils::fnsig_arguments(ctx, self);

        match self.abi(ctx, None) {
            Ok(abi) => Ok(
                syn::parse_quote! { unsafe extern #abi fn ( #( #arguments ),* ) #ret },
            ),
            Err(err) => {
                if matches!(err, Error::UnsupportedAbi(_)) {
                    unsupported_abi_diagnostic(
                        self.name(),
                        self.is_variadic(),
                        item.location(),
                        ctx,
                        &err,
                    );
                }

                Err(err)
            }
        }
    }
}

impl CodeGenerator for Function {
    type Extra = Item;

    /// If we've actually generated the symbol, the number of times we've seen
    /// it.
    type Return = Option<u32>;

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) -> Self::Return {
        debug!("<Function as CodeGenerator>::codegen: item = {item:?}");
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let is_internal = matches!(self.linkage(), Linkage::Internal);

        let signature_item = ctx.resolve_item(self.signature());
        let signature = signature_item.kind().expect_type().canonical_type(ctx);
        let TypeKind::Function(ref signature) = *signature.kind() else {
            panic!("Signature kind is not a Function: {signature:?}")
        };

        if is_internal {
            if !ctx.options().wrap_static_fns {
                // We cannot do anything with internal functions if we are not wrapping them so
                // just avoid generating anything for them.
                return None;
            }

            if signature.is_variadic() {
                // We cannot generate wrappers for variadic static functions so we avoid
                // generating any code for them.
                variadic_fn_diagnostic(self.name(), item.location(), ctx);
                return None;
            }
        }

        let is_pure_virtual = match self.kind() {
            FunctionKind::Method(ref method_kind) => {
                method_kind.is_pure_virtual()
            }
            FunctionKind::Function => false,
        };
        if is_pure_virtual && !ctx.options().generate_pure_virtual_functions {
            // Pure virtual methods have no actual symbol, so we can't generate
            // something meaningful for them. Downstream code postprocessors
            // might want to find out about them.
            return None;
        }

        let is_dynamic_function = match self.kind() {
            FunctionKind::Function => {
                ctx.options().dynamic_library_name.is_some()
            }
            FunctionKind::Method(_) => false,
        };

        // Similar to static member variables in a class template, we can't
        // generate bindings to template functions, because the set of
        // instantiations is open ended and we have no way of knowing which
        // monomorphizations actually exist.
        if !item.all_template_params(ctx).is_empty() {
            return None;
        }

        let name = self.name();
        let mut canonical_name = item.canonical_name(ctx);
        let mangled_name = self.mangled_name();

        {
            let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);

            // TODO: Maybe warn here if there's a type/argument mismatch, or
            // something?
            if result.seen_function(seen_symbol_name) {
                return None;
            }
            result.saw_function(seen_symbol_name);
        }

        let mut attributes = vec![];

        if true {
            let must_use = signature.must_use() || {
                let ret_ty = signature
                    .return_type()
                    .into_resolver()
                    .through_type_refs()
                    .resolve(ctx);
                ret_ty.must_use(ctx)
            };

            if must_use {
                attributes.push(attributes::must_use());
            }
        }

        if let Some(comment) = item.comment(ctx) {
            attributes.push(attributes::doc(&comment));
        }

        let abi = match signature.abi(ctx, Some(name)) {
            Err(err) => {
                if matches!(err, Error::UnsupportedAbi(_)) {
                    unsupported_abi_diagnostic(
                        name,
                        signature.is_variadic(),
                        item.location(),
                        ctx,
                        &err,
                    );
                }

                return None;
            }
            Ok(ClangAbi::Unknown(unknown_abi)) => {
                panic!(
                    "Invalid or unknown abi {unknown_abi:?} for function {canonical_name:?} ({self:?})"
                );
            }
            Ok(abi) => abi,
        };

        // Handle overloaded functions by giving each overload its own unique
        // suffix.
        let times_seen = result.overload_number(&canonical_name);
        if times_seen > 0 {
            write!(&mut canonical_name, "{times_seen}").unwrap();
        }
        utils::call_discovered_item_callback(ctx, item, || {
            DiscoveredItem::Function {
                final_name: canonical_name.clone(),
            }
        });

        let link_name_attr = self.link_name().or_else(|| {
            let mangled_name = mangled_name.unwrap_or(name);
            (!utils::names_will_be_identical_after_mangling(
                &canonical_name,
                mangled_name,
                Some(abi),
            ))
            .then_some(mangled_name)
        });

        if let Some(link_name) = link_name_attr {
            if !is_dynamic_function {
                attributes.push(attributes::link_name::<false>(link_name));
            }
        }

        // Unfortunately this can't piggyback on the `attributes` list because
        // the #[link(wasm_import_module)] needs to happen before the `extern
        // "C"` block. It doesn't get picked up properly otherwise
        let wasm_link_attribute =
            ctx.options().wasm_import_module_name.as_ref().map(|name| {
                quote! { #[link(wasm_import_module = #name)] }
            });

        let should_wrap = is_internal &&
            ctx.options().wrap_static_fns &&
            link_name_attr.is_none();

        if should_wrap {
            let name = canonical_name.clone() + ctx.wrap_static_fns_suffix();
            attributes.push(attributes::link_name::<true>(&name));
        }

        let wrap_as_variadic = if should_wrap && !signature.is_variadic() {
            utils::wrap_as_variadic_fn(ctx, signature, name)
        } else {
            None
        };

        let (ident, args) = if let Some(WrapAsVariadic {
            idx_of_va_list_arg,
            new_name,
        }) = &wrap_as_variadic
        {
            (
                new_name,
                utils::fnsig_arguments_iter(
                    ctx,
                    // Prune argument at index (idx_of_va_list_arg)
                    signature.argument_types().iter().enumerate().filter_map(
                        |(idx, t)| {
                            if idx == *idx_of_va_list_arg {
                                None
                            } else {
                                Some(t)
                            }
                        },
                    ),
                    // and replace it by a `...` (variadic symbol and the end of the signature)
                    true,
                ),
            )
        } else {
            (&canonical_name, utils::fnsig_arguments(ctx, signature))
        };
        let ret = utils::fnsig_return_ty(ctx, signature);

        let ident = ctx.rust_ident(ident);

        let safety = ctx
            .options()
            .rust_features
            .unsafe_extern_blocks
            .then(|| quote!(unsafe));

        let tokens = quote! {
            #wasm_link_attribute
            #safety extern #abi {
                #(#attributes)*
                pub fn #ident ( #( #args ),* ) #ret;
            }
        };

        // Add the item to the serialization list if necessary
        if should_wrap {
            result
                .items_to_serialize
                .push((item.id(), wrap_as_variadic));
        }

        // If we're doing dynamic binding generation, add to the dynamic items.
        if is_dynamic_function {
            let ident_str = ident.to_string();
            let symbol = link_name_attr.unwrap_or(&ident_str);
            let args_identifiers =
                utils::fnsig_argument_identifiers(ctx, signature);
            let ret_ty = utils::fnsig_return_ty(ctx, signature);
            result.dynamic_items().push_func(
                &ident,
                symbol,
                abi,
                signature.is_variadic(),
                ctx.options().dynamic_link_require_all,
                &args,
                &args_identifiers,
                &ret,
                &ret_ty,
                &attributes,
                ctx,
            );
        } else {
            result.push(tokens);
        }
        Some(times_seen)
    }
}

#[cfg_attr(not(feature = "experimental"), allow(unused_variables))]
fn unsupported_abi_diagnostic(
    fn_name: &str,
    variadic: bool,
    location: Option<&crate::clang::SourceLocation>,
    ctx: &BindgenContext,
    error: &Error,
) {
    warn!(
        "Skipping {}function `{fn_name}` because the {error}",
        if variadic { "variadic " } else { "" },
    );

    #[cfg(feature = "experimental")]
    if ctx.options().emit_diagnostics {
        use crate::diagnostics::{get_line, Diagnostic, Level, Slice};

        let mut diag = Diagnostic::default();
        diag.with_title(
            format!(
                "Skipping {}function `{fn_name}` because the {error}",
                if variadic { "variadic " } else { "" },
            ),
            Level::Warning,
        )
        .add_annotation(
            "No code will be generated for this function.",
            Level::Warning,
        )
        .add_annotation(
            format!(
                "The configured Rust version is {}.",
                ctx.options().rust_target
            ),
            Level::Note,
        );

        if let Some(loc) = location {
            let (file, line, col, _) = loc.location();

            if let Some(filename) = file.name() {
                if let Ok(Some(source)) = get_line(&filename, line) {
                    let mut slice = Slice::default();
                    slice
                        .with_source(source)
                        .with_location(filename, line, col);
                    diag.add_slice(slice);
                }
            }
        }

        diag.display();
    }
}

fn variadic_fn_diagnostic(
    fn_name: &str,
    _location: Option<&crate::clang::SourceLocation>,
    _ctx: &BindgenContext,
) {
    warn!(
        "Cannot generate wrapper for the static variadic function `{fn_name}`."
    );

    #[cfg(feature = "experimental")]
    if _ctx.options().emit_diagnostics {
        use crate::diagnostics::{get_line, Diagnostic, Level, Slice};

        let mut diag = Diagnostic::default();

        diag.with_title(format!("Cannot generate wrapper for the static function `{fn_name}`."), Level::Warning)
            .add_annotation("The `--wrap-static-fns` feature does not support variadic functions."Level::Note)
            .add_annotation("No code will be generated for this function.", Level::Note);

        if let Some(loc) = _location {
            let (file, line, col, _) = loc.location();

            if let Some(filename) = file.name() {
                if let Ok(Some(source)) = get_line(&filename, line) {
                    let mut slice = Slice::default();
                    slice
                        .with_source(source)
                        .with_location(filename, line, col);
                    diag.add_slice(slice);
                }
            }
        }

        diag.display();
    }
}

fn objc_method_codegen(
    ctx: &BindgenContext,
    method: &ObjCMethod,
    methods: &mut Vec<proc_macro2::TokenStream>,
    class_name: Option<&str>,
    rust_class_name: &str,
    prefix: &str,
) {
    // This would ideally resolve the method into an Item, and use
    // Item::process_before_codegen; however, ObjC methods are not currently
    // made into function items.
    let name = format!("{rust_class_name}::{prefix}{}", method.rust_name());
    if ctx.options().blocklisted_items.matches(name) {
        return;
    }

    let signature = method.signature();
    let fn_args = utils::fnsig_arguments(ctx, signature);
    let fn_ret = utils::fnsig_return_ty(ctx, signature);

    let sig = if method.is_class_method() {
        quote! {
            ( #( #fn_args ),* ) #fn_ret
        }
    } else {
        let self_arr = [quote! { &self }];
        let args = self_arr.iter().chain(fn_args.iter());
        quote! {
            ( #( #args ),* ) #fn_ret
        }
    };

    let methods_and_args = method.format_method_call(&fn_args);

    let body = {
        let body = if method.is_class_method() {
            let class_name = ctx.rust_ident(
                class_name
                    .expect("Generating a class method without class name?"),
            );
            quote!(msg_send!(class!(#class_name), #methods_and_args))
        } else {
            quote!(msg_send!(*self#methods_and_args))
        };

        ctx.wrap_unsafe_ops(body)
    };

    let method_name = ctx.rust_ident(format!("{prefix}{}", method.rust_name()));

    methods.push(quote! {
        unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
            #body
        }
    });
}

impl CodeGenerator for ObjCInterface {
    type Extra = Item;
    type Return = ();

    fn codegen(
        &self,
        ctx: &BindgenContext,
        result: &mut CodegenResult<'_>,
        item: &Item,
    ) {
        debug_assert!(item.is_enabled_for_codegen(ctx));

        let mut impl_items = vec![];
        let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::");

        for method in self.methods() {
            objc_method_codegen(
                ctx,
                method,
                &mut impl_items,
                None,
                &rust_class_name,
                "",
            );
        }

        for class_method in self.class_methods() {
            let ambiquity = self
                .methods()
                .iter()
                .map(|m| m.rust_name())
                .any(|x| x == class_method.rust_name());
            let prefix = if ambiquity { "class_" } else { "" };
            objc_method_codegen(
                ctx,
                class_method,
                &mut impl_items,
                Some(self.name()),
                &rust_class_name,
                prefix,
            );
        }

        let trait_name = ctx.rust_ident(self.rust_name());
        let trait_constraints = quote! {
            Sized + std::ops::Deref
        };
        let trait_block = if self.is_template() {
            let template_names: Vec<Ident> = self
                .template_names
                .iter()
                .map(|g| ctx.rust_ident(g))
                .collect();

            quote! {
                pub trait #trait_name <#(#template_names:'static),*> : #trait_constraints {
                    #( #impl_items )*
                }
            }
        } else {
            quote! {
                pub trait #trait_name : #trait_constraints {
                    #( #impl_items )*
                }
            }
        };

        let class_name = ctx.rust_ident(self.name());
        if !self.is_category() && !self.is_protocol() {
            let struct_block = quote! {
                #[repr(transparent)]
                #[derive(Debug, Copy, Clone)]
                pub struct #class_name(pub id);
                impl std::ops::Deref for #class_name {
                    type Target = objc::runtime::Object;
                    fn deref(&self) -> &Self::Target {
                        unsafe {
                            &*self.0
                        }
                    }
                }
                unsafe impl objc::Message for #class_name { }
                impl #class_name {
                    pub fn alloc() -> Self {
                        Self(unsafe {
                            msg_send!(class!(#class_name), alloc)
                        })
                    }
                }
            };
            result.push(struct_block);
            let mut protocol_set: HashSet<ItemId> = Default::default();
            for protocol_id in &self.conforms_to {
                protocol_set.insert(*protocol_id);
                let protocol_name = ctx.rust_ident(
                    ctx.resolve_type(protocol_id.expect_type_id(ctx))
                        .name()
                        .unwrap(),
                );
                let impl_trait = quote! {
                    impl #protocol_name for #class_name { }
                };
                result.push(impl_trait);
            }
            let mut parent_class = self.parent_class;
            while let Some(parent_id) = parent_class {
                let parent = parent_id
                    .expect_type_id(ctx)
                    .into_resolver()
                    .through_type_refs()
                    .resolve(ctx)
                    .expect_type()
                    .kind();

                let TypeKind::ObjCInterface(parent) = parent else {
                    break;
                };
                parent_class = parent.parent_class;

                let parent_name = ctx.rust_ident(parent.rust_name());
                let impl_trait = if parent.is_template() {
                    let template_names: Vec<Ident> = parent
                        .template_names
                        .iter()
                        .map(|g| ctx.rust_ident(g))
                        .collect();
                    quote! {
                        impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name {
                        }
                    }
                } else {
                    quote! {
                        impl #parent_name for #class_name { }
                    }
                };
                result.push(impl_trait);
                for protocol_id in &parent.conforms_to {
                    if protocol_set.insert(*protocol_id) {
                        let protocol_name = ctx.rust_ident(
                            ctx.resolve_type(protocol_id.expect_type_id(ctx))
                                .name()
                                .unwrap(),
                        );
                        let impl_trait = quote! {
                            impl #protocol_name for #class_name { }
                        };
                        result.push(impl_trait);
                    }
                }
                if !parent.is_template() {
                    let parent_struct_name = parent.name();
                    let child_struct_name = self.name();
                    let parent_struct = ctx.rust_ident(parent_struct_name);
                    let from_block = quote! {
                        impl From<#class_namefor #parent_struct {
                            fn from(child: #class_name) -> #parent_struct {
                                #parent_struct(child.0)
                            }
                        }
                    };
                    result.push(from_block);

                    let error_msg = format!(
                        "This {parent_struct_name} cannot be downcasted to {child_struct_name}"
                    );
                    let try_into_block = quote! {
                        impl std::convert::TryFrom<#parent_structfor #class_name {
                            type Error = &'static str;
                            fn try_from(parent: #parent_struct) -> Result<#class_nameSelf::Error> {
                                let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))};
                                if is_kind_of {
                                    Ok(#class_name(parent.0))
                                } else {
                                    Err(#error_msg)
                                }
                            }
                        }
                    };
                    result.push(try_into_block);
                }
            }
        }

        if !self.is_protocol() {
            let impl_block = if self.is_template() {
                let template_names: Vec<Ident> = self
                    .template_names
                    .iter()
                    .map(|g| ctx.rust_ident(g))
                    .collect();
                quote! {
                    impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #class_name {
                    }
                }
            } else {
                quote! {
                    impl #trait_name for #class_name {
                    }
                }
            };
            result.push(impl_block);
        }

        result.push(trait_block);
        result.saw_objc();
    }
}

pub(cratefn codegen(
    context: BindgenContext,
) -> Result<(proc_macro2::TokenStream, BindgenOptions), CodegenError> {
    context.gen(|context| {
        let _t = context.timer("codegen");
        let counter = Cell::new(0);
        let mut result = CodegenResult::new(&counter);

        debug!("codegen: {:?}", context.options());

        if context.options().emit_ir {
            let codegen_items = context.codegen_items();
            for (id, item) in context.items() {
                if codegen_items.contains(&id) {
                    println!("ir: {id:?} = {item:#?}");
                }
            }
        }

        if let Some(path) = context.options().emit_ir_graphviz.as_ref() {
            match dot::write_dot_file(context, path) {
                Ok(()) => info!(
                    "Your dot file was generated successfully into: {path}"
                ),
                Err(e) => warn!("{e}"),
            }
        }

        if let Some(spec) = context.options().depfile.as_ref() {
            match spec.write(context.deps()) {
                Ok(()) => info!(
                    "Your depfile was generated successfully into: {}",
                    spec.depfile_path.display()
                ),
                Err(e) => warn!("{e}"),
            }
        }

        context.resolve_item(context.root_module()).codegen(
            context,
            &mut result,
            &(),
        );

        if let Some(ref lib_name) = context.options().dynamic_library_name {
            let lib_ident = context.rust_ident(lib_name);
            let dynamic_items_tokens =
                result.dynamic_items().get_tokens(&lib_ident, context);
            result.push(dynamic_items_tokens);
        }

        utils::serialize_items(&result, context)?;

        Ok(postprocessing::postprocessing(
            result.items,
            context.options(),
        ))
    })
}

pub(cratemod utils {
    use super::helpers::BITFIELD_UNIT;
    use super::serialize::CSerialize;
    use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
    use crate::callbacks::DiscoveredItemId;
    use crate::ir::context::BindgenContext;
    use crate::ir::context::TypeId;
    use crate::ir::function::{Abi, ClangAbi, FunctionSig};
    use crate::ir::item::{Item, ItemCanonicalPath};
    use crate::ir::ty::TypeKind;
    use crate::{args_are_cpp, file_is_cpp};
    use std::borrow::Cow;
    use std::io::Write;
    use std::mem;
    use std::path::PathBuf;
    use std::str::FromStr;

    pub(superfn serialize_items(
        result: &CodegenResult,
        context: &BindgenContext,
    ) -> Result<(), CodegenError> {
        if result.items_to_serialize.is_empty() {
            return Ok(());
        }

        let path = context.options().wrap_static_fns_path.as_ref().map_or_else(
            || std::env::temp_dir().join("bindgen").join("extern"),
            PathBuf::from,
        );

        let dir = path.parent().unwrap();

        if !dir.exists() {
            std::fs::create_dir_all(dir)?;
        }

        let is_cpp = args_are_cpp(&context.options().clang_args) ||
            context
                .options()
                .input_headers
                .iter()
                .any(|h| file_is_cpp(h));

        let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" });

        let mut code = Vec::new();

        if !context.options().input_headers.is_empty() {
            for header in &context.options().input_headers {
                writeln!(code, "#include \"{header}\"")?;
            }

            writeln!(code)?;
        }

        if !context.options().input_header_contents.is_empty() {
            for (name, contents) in &context.options().input_header_contents {
                writeln!(code, "// {name}\n{contents}")?;
            }

            writeln!(code)?;
        }

        writeln!(code, "// Static wrappers\n")?;

        for (id, wrap_as_variadic) in &result.items_to_serialize {
            let item = context.resolve_item(*id);
            item.serialize(context, wrap_as_variadic, &mut vec![], &yle='color:red'>mut code)?;
        }

        std::fs::write(source_path, code)?;

        Ok(())
    }

    pub(superfn wrap_as_variadic_fn(
        ctx: &BindgenContext,
        signature: &FunctionSig,
        name: &str,
    ) -> Option<super::WrapAsVariadic> {
        // Fast path, exclude because:
        //  - with 0 args: no va_list possible, so no point searching for one
        //  - with 1 args: cannot have a `va_list` and another arg (required by va_start)
        if signature.argument_types().len() <= 1 {
            return None;
        }

        let mut it = signature.argument_types().iter().enumerate().filter_map(
            |(idx, (_name, mut type_id))| {
                // Hand rolled visitor that checks for the presence of `va_list`
                loop {
                    let ty = ctx.resolve_type(type_id);
                    if Some("__builtin_va_list") == ty.name() {
                        return Some(idx);
                    }
                    match ty.kind() {
                        TypeKind::Alias(type_id_alias) => {
                            type_id = *type_id_alias;
                        }
                        TypeKind::ResolvedTypeRef(type_id_typedef) => {
                            type_id = *type_id_typedef;
                        }
                        _ => break,
                    }
                }
                None
            },
        );

        // Return THE idx (by checking that there is no idx after)
        // This is done since we cannot handle multiple `va_list`
        it.next().filter(|_| it.next().is_none()).and_then(|idx| {
            // Call the `wrap_as_variadic_fn` callback
            #[cfg(feature = "experimental")]
            {
                ctx.options()
                    .last_callback(|c| c.wrap_as_variadic_fn(name))
                    .map(|new_name| super::WrapAsVariadic {
                        new_name,
                        idx_of_va_list_arg: idx,
                    })
            }
            #[cfg(not(feature = "experimental"))]
            {
                let _ = name;
                let _ = idx;
                None
            }
        })
    }

    pub(cratefn prepend_bitfield_unit_type(
        ctx: &BindgenContext,
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        if ctx.options().blocklisted_items.matches(BITFIELD_UNIT) ||
            ctx.options().blocklisted_types.matches(BITFIELD_UNIT)
        {
            return;
        }

        let bitfield_unit_src = include_str!("./bitfield_unit.rs");
        let bitfield_unit_src = if true {
            Cow::Borrowed(bitfield_unit_src)
        } else {
            Cow::Owned(bitfield_unit_src.replace("const fn ""fn "))
        };
        let bitfield_unit_type =
            proc_macro2::TokenStream::from_str(&bitfield_unit_src).unwrap();
        let bitfield_unit_type = quote!(#bitfield_unit_type);

        let items = vec![bitfield_unit_type];
        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_objc_header(
        ctx: &BindgenContext,
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let use_objc = if ctx.options().objc_extern_crate {
            quote! {
                #[macro_use]
                extern crate objc;
            }
        } else {
            quote! {
                use objc::{self, msg_send, sel, sel_impl, class};
            }
        };

        let id_type = quote! {
            #[allow(non_camel_case_types)]
            pub type id = *mut objc::runtime::Object;
        };

        let items = vec![use_objc, id_type];
        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_block_header(
        ctx: &BindgenContext,
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let use_block = if ctx.options().block_extern_crate {
            quote! {
                extern crate block;
            }
        } else {
            quote! {
                use block;
            }
        };

        let items = vec![use_block];
        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_union_types(
        ctx: &BindgenContext,
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let prefix = ctx.trait_prefix();

        // If the target supports `const fn`, declare eligible functions
        // as `const fn` else just `fn`.
        let const_fn = if true {
            quote! { const fn }
        } else {
            quote! { fn }
        };

        // TODO(emilio): The fmt::Debug impl could be way nicer with
        // std::intrinsics::type_name, but...
        let union_field_decl = quote! {
            #[repr(C)]
            pub struct __BindgenUnionField<T>(::#prefix::marker::PhantomData<T>);
        };

        let transmute =
            ctx.wrap_unsafe_ops(quote!(::#prefix::mem::transmute(self)));

        let union_field_impl = quote! {
            impl<T> __BindgenUnionField<T> {
                #[inline]
                pub #const_fn new() -> Self {
                    __BindgenUnionField(::#prefix::marker::PhantomData)
                }

                #[inline]
                pub unsafe fn as_ref(&self) -> &T {
                    #transmute
                }

                #[inline]
                pub unsafe fn as_mut(&mut self) -> &mut T {
                    #transmute
                }
            }
        };

        let union_field_default_impl = quote! {
            impl<T> ::#prefix::default::Default for __BindgenUnionField<T> {
                #[inline]
                fn default() -> Self {
                    Self::new()
                }
            }
        };

        let union_field_clone_impl = quote! {
            impl<T> ::#prefix::clone::Clone for __BindgenUnionField<T> {
                #[inline]
                fn clone(&self) -> Self {
                    *self
                }
            }
        };

        let union_field_copy_impl = quote! {
            impl<T> ::#prefix::marker::Copy for __BindgenUnionField<T> {}
        };

        let union_field_debug_impl = quote! {
            impl<T> ::#prefix::fmt::Debug for __BindgenUnionField<T> {
                fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
                       -> ::#prefix::fmt::Result {
                    fmt.write_str("__BindgenUnionField")
                }
            }
        };

        // The actual memory of the filed will be hashed, so that's why these
        // field doesn't do anything with the hash.
        let union_field_hash_impl = quote! {
            impl<T> ::#prefix::hash::Hash for __BindgenUnionField<T> {
                fn hash<H: ::#prefix::hash::Hasher>(&self, _state: &mut H) {
                }
            }
        };

        let union_field_partialeq_impl = quote! {
            impl<T> ::#prefix::cmp::PartialEq for __BindgenUnionField<T> {
               fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
                   true
               }
           }
        };

        let union_field_eq_impl = quote! {
           impl<T> ::#prefix::cmp::Eq for __BindgenUnionField<T> {
           }
        };

        let items = vec![
            union_field_decl,
            union_field_impl,
            union_field_default_impl,
            union_field_clone_impl,
            union_field_copy_impl,
            union_field_debug_impl,
            union_field_hash_impl,
            union_field_partialeq_impl,
            union_field_eq_impl,
        ];

        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_incomplete_array_types(
        ctx: &BindgenContext,
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let prefix = ctx.trait_prefix();

        // If the target supports `const fn`, declare eligible functions
        // as `const fn` else just `fn`.
        let const_fn = if true {
            quote! { const fn }
        } else {
            quote! { fn }
        };

        let incomplete_array_decl = quote! {
            #[repr(C)]
            #[derive(Default)]
            pub struct __IncompleteArrayField<T>(
                ::#prefix::marker::PhantomData<T>, [T; 0]);
        };

        let from_raw_parts = ctx.wrap_unsafe_ops(quote! (
            ::#prefix::slice::from_raw_parts(self.as_ptr(), len)
        ));
        let from_raw_parts_mut = ctx.wrap_unsafe_ops(quote! (
            ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
        ));

        let incomplete_array_impl = quote! {
            impl<T> __IncompleteArrayField<T> {
                #[inline]
                pub #const_fn new() -> Self {
                    __IncompleteArrayField(::#prefix::marker::PhantomData, [])
                }

                #[inline]
                pub fn as_ptr(&self) -> *const T {
                    self as *const _ as *const T
                }

                #[inline]
                pub fn as_mut_ptr(&mut self) -> *mut T {
                    self as *mut _ as *mut T
                }

                #[inline]
                pub unsafe fn as_slice(&self, len: usize) -> &[T] {
                    #from_raw_parts
                }

                #[inline]
                pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
                    #from_raw_parts_mut
                }
            }
        };

        let incomplete_array_debug_impl = quote! {
            impl<T> ::#prefix::fmt::Debug for __IncompleteArrayField<T> {
                fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
                       -> ::#prefix::fmt::Result {
                    fmt.write_str("__IncompleteArrayField")
                }
            }
        };

        let items = vec![
            incomplete_array_decl,
            incomplete_array_impl,
            incomplete_array_debug_impl,
        ];

        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_float16_type(
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let float16_type = quote! {
            #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
            #[repr(transparent)]
            pub struct __BindgenFloat16(pub u16);
        };

        let items = vec![float16_type];
        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_complex_type(
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let complex_type = quote! {
            #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
            #[repr(C)]
            pub struct __BindgenComplex<T> {
                pub re: T,
                pub im: T
            }
        };

        let items = vec![complex_type];
        let old_items = mem::replace(result, items);
        result.extend(old_items);
    }

    pub(cratefn prepend_opaque_array_types(
        ctx: &BindgenContext,
        result: &mut Vec<proc_macro2::TokenStream>,
    ) {
        let mut tys = vec![];
        // If Bindgen could only determine the size and alignment of a type, it is represented like
        // this.
        for align in ctx.opaque_array_types_needed() {
            let ident = if align == 1 {
                format_ident!("__BindgenOpaqueArray")
            } else {
                format_ident!("__BindgenOpaqueArray{}", align)
            };
            let repr = if align <= 1 {
                quote! { #[repr(C)] }
            } else {
                let explicit = super::helpers::ast_ty::int_expr(align as i64);
                quote! { #[repr(C, align(#explicit))] }
            };
            tys.push(quote! {
                #[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
                #repr
                pub struct #ident<T>(pub T);
                impl<T: Copy + Default, const N: usize> Default for #ident<[T; N]> {
                    fn default() -> Self {
                        Self([<T as Default>::default(); N])
                    }
                }
            });
        }
        result.splice(0..0, tys);
    }

    pub(cratefn build_path(
        item: &Item,
        ctx: &BindgenContext,
    ) -> error::Result<syn::Type> {
        let path = item.namespace_aware_canonical_path(ctx);
        let tokens =
            proc_macro2::TokenStream::from_str(&path.join("::")).unwrap();

        Ok(syn::parse_quote! { #tokens })
    }

    fn primitive_ty(ctx: &BindgenContext, name: &str) -> syn::Type {
        let ident = ctx.rust_ident_raw(name);
        syn::parse_quote! { #ident }
    }

    pub(cratefn type_from_named(
        ctx: &BindgenContext,
        name: &str,
    ) -> Option<syn::Type> {
        // FIXME: We could use the inner item to check this is really a
        // primitive type but, who the heck overrides these anyway?
        Some(match name {
            "int8_t" => primitive_ty(ctx, "i8"),
            "uint8_t" => primitive_ty(ctx, "u8"),
            "int16_t" => primitive_ty(ctx, "i16"),
            "uint16_t" => primitive_ty(ctx, "u16"),
            "int32_t" => primitive_ty(ctx, "i32"),
            "uint32_t" => primitive_ty(ctx, "u32"),
            "int64_t" => primitive_ty(ctx, "i64"),
            "uint64_t" => primitive_ty(ctx, "u64"),

            "size_t" if ctx.options().size_t_is_usize => {
                primitive_ty(ctx, "usize")
            }
            "uintptr_t" => primitive_ty(ctx, "usize"),

            "ssize_t" if ctx.options().size_t_is_usize => {
                primitive_ty(ctx, "isize")
            }
            "intptr_t" | "ptrdiff_t" => primitive_ty(ctx, "isize"),
            _ => return None,
        })
    }

    fn fnsig_return_ty_internal(
        ctx: &BindgenContext,
        sig: &FunctionSig,
    ) -> syn::Type {
        if sig.is_divergent() {
            return syn::parse_quote! { ! };
        }

        let canonical_type_kind = sig
            .return_type()
            .into_resolver()
            .through_type_refs()
            .through_type_aliases()
            .resolve(ctx)
            .kind()
            .expect_type()
            .kind();

        match canonical_type_kind {
            TypeKind::Void => syn::parse_quote! { () },
            _ => sig.return_type().to_rust_ty_or_opaque(ctx, &()),
        }
    }

    pub(cratefn fnsig_return_ty(
        ctx: &BindgenContext,
        sig: &FunctionSig,
    ) -> proc_macro2::TokenStream {
        match fnsig_return_ty_internal(ctx, sig) {
            syn::Type::Tuple(syn::TypeTuple { elems, .. })
                if elems.is_empty() =>
            {
                quote! {}
            }
            ty => quote! { -> #ty },
        }
    }

    pub(cratefn fnsig_argument_type(
        ctx: &BindgenContext,
        ty: TypeId,
    ) -> syn::Type {
        use super::ToPtr;

        let arg_item = ctx.resolve_item(ty);
        let arg_ty = arg_item.kind().expect_type();

        // From the C90 standard[1]:
        //
        //     A declaration of a parameter as "array of type" shall be
        //     adjusted to "qualified pointer to type", where the type
        //     qualifiers (if any) are those specified within the [ and ] of
        //     the array type derivation.
        //
        // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
        match *arg_ty.canonical_type(ctx).kind() {
            TypeKind::Array(t, _) => {
                let stream = if ctx.options().array_pointers_in_arguments {
                    arg_ty.to_rust_ty_or_opaque(ctx, arg_item)
                } else {
                    t.to_rust_ty_or_opaque(ctx, &())
                };
                stream
                    .to_ptr(ctx.resolve_type(t).is_const() || arg_ty.is_const())
            }
            TypeKind::Pointer(inner) => {
                let inner = ctx.resolve_item(inner);
                let inner_ty = inner.expect_type();
                if let TypeKind::ObjCInterface(ref interface) =
                    *inner_ty.canonical_type(ctx).kind()
                {
                    let name = ctx.rust_ident(interface.name());
                    syn::parse_quote! { #name }
                } else {
                    arg_item.to_rust_ty_or_opaque(ctx, &())
                }
            }
            _ => arg_item.to_rust_ty_or_opaque(ctx, &()),
        }
    }

    pub(cratefn fnsig_arguments_iter<
        'a,
        I: Iterator<Item = &'a (Option<String>, TypeId)>,
    >(
        ctx: &BindgenContext,
        args_iter: I,
        is_variadic: bool,
    ) -> Vec<proc_macro2::TokenStream> {
        let mut unnamed_arguments = 0;
        let mut args = args_iter
            .map(|(name, ty)| {
                let arg_ty = fnsig_argument_type(ctx, *ty);

                let arg_name = if let Some(ref name) = *name {
                    ctx.rust_mangle(name).into_owned()
                } else {
                    unnamed_arguments += 1;
                    format!("arg{unnamed_arguments}")
                };

                assert!(!arg_name.is_empty());
                letjava.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 56

       {
                    #arg_name : #arg_ty
                }
            })
            .collect::<Vec<_>>();

if{
            args.push(quote! { ... });
        }

        args
    }

    pubstruct Idx Ord +Copy+ Default> {
         &java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
        sig.and_then(||{
    )> {
        java.lang.StringIndexOutOfBoundsException: Range [16, 10) out of bounds for length 17
            ctx,
            .argument_types().iter(,
            sigNone
        )
}

    pub(cratefn .insert(elf.first_index, old_start.drain_range..start)java.lang.StringIndexOutOfBoundsException: Index 81 out of bounds for length 81
        ctx:&BindgenContext,
        sig: &FunctionSiglast_range.tart  .rain_range.end;
    ) -> Vec<proc_macro2::TokenStream> {
        let mut unnamed_arguments = 0;
        let args = sig
            .argument_types(java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
            .iter(java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
            .map
                let arg_name = if let Some(ref
                    ctx.java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 7
                } else {
                    unnamed_arguments += 1;
                    format// Would need to keep iterating for more
                };

                .is_empty()java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
                letjava.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 61

                quote {
                    java.lang.StringIndexOutOfBoundsException: Range [35, 32) out of bounds for length 65
                java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 79
            })
            .collect::<Vec<_>>();

        args
    }

    pubjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ctxjava.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
        ,
    ) -> trackerdrain0.);
        ()|(_, ) java.lang.StringIndexOutOfBoundsException: Range [63, 64) out of bounds for length 63
            assert_eqt..22),Some(.);

.0.)
        )

        !drain.19.(,);
        
    #test]
        }
    }

    / Returns true if `canonical_name` will end up as `mangled_name` at the
    // machine code level, i.e. after LLVM has applied any target specific
    assert_eq!(tracker.check(5..6), Some(5..6));
    pub(
        java.lang.StringIndexOutOfBoundsException: Range [24, 22) out of bounds for length 29
         str,
        call_conv: Option<l tracker= :new()
    )java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
        // If the mangled name and the canonical name are the same then no
        // mangling can have happened between the two versions.
        if canonical_name == mangled_name {
            return true;
        }

        // Working with &[u8] makes indexing simpler than with &str
        let canonical_name = canonical_name.as_bytes();
        let mangled_name = mangled_name.as_bytes();

        let (mangling_prefix, expect_suffix) = match call_conv {
            Some(ClangAbi::Known(Abi::C | Abi::CUnwind)) |
            // None is the case for global variables
            None => {
                (b'_'false)
            }
            Some(ClangAbi::Known(Abi::Stdcall)) => (b'_'true),
            Some(ClangAbi::Known(Abi::Fastcall)) => (b'@'true),

            // This is something we don't recognize, stay on the safe side
            // by emitting the `#[link_name]` attribute
            Some(_) => return false,
        };

        // Check that the mangled name is long enough to at least contain the
        // canonical name plus the expected prefix.
        if mangled_name.len() < canonical_name.len() + 1 {
            return false;
        }

        // Return if the mangled name does not start with the prefix expected
        // for the given calling convention.
        if mangled_name[0] != mangling_prefix {
            return false;
        }

        // Check that the mangled name contains the canonical name after the
        // prefix
        if &mangled_name[1..=canonical_name.len()] != canonical_name {
            return false;
        }

        // If the given calling convention also prescribes a suffix, check that
        // it exists too
        if expect_suffix {
            let suffix = &mangled_name[canonical_name.len() + 1..];

            // The shortest suffix is "@0"
            if suffix.len() < 2 {
                return false;
            }

            // Check that the suffix starts with '@' and is all ASCII decimals
            // after that.
            if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit)
            {
                return false;
            }
        } else if mangled_name.len() != canonical_name.len() + 1 {
            // If we don't expect a prefix but there is one, we need the
            // #[link_name] attribute
            return false;
        }

        true
    }

    pub(superfn call_discovered_item_callback(
        ctx: &BindgenContext,
        item: &Item,
        discovered_item_creator: impl Fn() -> crate::callbacks::DiscoveredItem,
    ) {
        let source_location = item.location().map(|clang_location| {
            let (file, line, col, byte_offset) = clang_location.location();
            let file_name = file.name();
            crate::callbacks::SourceLocation {
                line,
                col,
                byte_offset,
                file_name,
            }
        });
        ctx.options().for_each_callback(|cb| {
            cb.new_item_found(
                DiscoveredItemId::new(item.id().as_usize()),
                discovered_item_creator(),
                source_location.as_ref(),
            );
        });
    }
}

Messung V0.5 in Prozent
C=78 H=96 G=87

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.187Bemerkung:  (vorverarbeitet am  2026-08-27) ¤

*Bot Zugriff






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.