|  | mod dyngen; | 
|  | pub(crate) mod error; | 
|  |  | 
|  | mod helpers; | 
|  | mod impl_debug; | 
|  | mod impl_partialeq; | 
|  | mod postprocessing; | 
|  | mod serialize; | 
|  | pub(crate) mod struct_layout; | 
|  |  | 
|  | #[cfg(test)] | 
|  | #[allow(warnings)] | 
|  | pub(crate) mod 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(crate) static 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 | 
|  | } | 
|  |  | 
|  | /// Appends the contents of the `custom_derives` slice to the `derives` vector, | 
|  | /// ignoring duplicates and preserving order. | 
|  | fn append_custom_derives<'a>( | 
|  | derives: &mut Vec<&'a str>, | 
|  | custom_derives: &'a [String], | 
|  | ) { | 
|  | for custom_derive in custom_derives.iter().map(|s| s.as_str()) { | 
|  | if !derives.contains(&custom_derive) { | 
|  | derives.push(custom_derive); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | 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() { | 
|  | utils::call_discovered_item_callback(ctx, item, || { | 
|  | DiscoveredItem::Constant { | 
|  | final_name: canonical_name.clone(), | 
|  | } | 
|  | }); | 
|  |  | 
|  | let const_expr = match *val { | 
|  | VarType::Bool(val) => Some(val.to_token_stream()), | 
|  | 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 _) | 
|  | }; | 
|  | Some(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 ; | 
|  | }); | 
|  | } | 
|  | None | 
|  | } | 
|  | VarType::Float(f) => helpers::ast_ty::float_expr(f).ok(), | 
|  | VarType::Char(c) => Some(c.to_token_stream()), | 
|  | }; | 
|  |  | 
|  | if let Some(mut val) = const_expr { | 
|  | let var_ty_item = ctx.resolve_item(var_ty); | 
|  | if matches!( | 
|  | var_ty_item.alias_style(ctx), | 
|  | AliasVariation::NewType | AliasVariation::NewTypeDeref | 
|  | ) { | 
|  | val = quote! { #ty(#val) }; | 
|  | } | 
|  | result.push(quote! { | 
|  | #(#attrs)* | 
|  | pub const #canonical_ident : #ty = #val ; | 
|  | }); | 
|  | } | 
|  | } else { | 
|  | utils::call_discovered_item_callback(ctx, item, || { | 
|  | DiscoveredItem::Variable { | 
|  | final_name: canonical_name.clone(), | 
|  | } | 
|  | }); | 
|  |  | 
|  | 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 = item.alias_style(ctx); | 
|  |  | 
|  | // 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. | 
|  | append_custom_derives(&mut derives, &custom_derives); | 
|  | 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) { | 
|  | (true, true) => { | 
|  | // declared as public, cxx specs are respected | 
|  | FieldVisibilityKind::Public | 
|  | } | 
|  | (false, true) => { | 
|  | // 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, | 
|  | ) { | 
|  | (true, true) => FieldVisibilityKind::Public, | 
|  | (false, true) => 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(1, 1); | 
|  | 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 = [ #inner; 0 ] }), | 
|  | 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! { [ #ty; 0 ] }), | 
|  | Some(quote! { FAM: ?Sized = [ #ty; 0 ] }), | 
|  | ), | 
|  | }; | 
|  |  | 
|  | ( | 
|  | 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_ty; 0], | 
|  | }; | 
|  | 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. | 
|  | append_custom_derives(&mut derives, &custom_derives); | 
|  |  | 
|  | 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_name) as 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(), 0, 1); | 
|  | 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_ty; 0 ] > | 
|  | }; | 
|  |  | 
|  | 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<Self, Self::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_ty> for #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_ty> for #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 { | 
|  | #[allow(unused_imports)] | 
|  | use super::*; | 
|  |  | 
|  | #( #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) { | 
|  | (true, 1) => IntKind::I8, | 
|  | (false, 1) => IntKind::U8, | 
|  | (true, 2) => IntKind::I16, | 
|  | (false, 2) => IntKind::U16, | 
|  | (true, 4) => IntKind::I32, | 
|  | (false, 4) => IntKind::U32, | 
|  | (true, 8) => IntKind::I64, | 
|  | (false, 8) => 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. | 
|  | append_custom_derives(&mut derives, &custom_derives); | 
|  |  | 
|  | 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<Self, Self::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<Self, Self::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<Self, Self::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(crate) trait 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(crate) trait 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(crate) trait 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(crate) trait 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(crate) trait 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 if ctx.options().generate_cxx_nonnull_references && | 
|  | matches!(self.kind(), TypeKind::Reference(_)) | 
|  | { | 
|  | // It's UB to pass null values in place of C++ references | 
|  | let prefix = ctx.trait_prefix(); | 
|  | Ok(syn::parse_quote! { ::#prefix::ptr::NonNull<#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)); | 
|  | } | 
|  | } | 
|  |  | 
|  | let mut block_attributes = quote! {}; | 
|  | for attr in &ctx.options().extern_fn_block_attrs { | 
|  | let parsed_attr = proc_macro2::TokenStream::from_str(attr).unwrap_or_else( | 
|  | |err| { | 
|  | panic!( | 
|  | "Error parsing extern fn block attribute `{attr}`: {err}" | 
|  | ) | 
|  | }, | 
|  | ); | 
|  | block_attributes.extend(quote! { | 
|  | #parsed_attr | 
|  | }); | 
|  | } | 
|  |  | 
|  | 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! { | 
|  | #block_attributes | 
|  | #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_name> for #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_struct> for #class_name { | 
|  | type Error = &'static str; | 
|  | fn try_from(parent: #parent_struct) -> Result<#class_name, Self::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(crate) fn 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(crate) mod 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(super) fn 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![], &mut code)?; | 
|  | } | 
|  |  | 
|  | std::fs::write(source_path, code)?; | 
|  |  | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | pub(super) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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(crate) fn 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()); | 
|  | let arg_name = ctx.rust_ident(arg_name); | 
|  |  | 
|  | quote! { | 
|  | #arg_name : #arg_ty | 
|  | } | 
|  | }) | 
|  | .collect::<Vec<_>>(); | 
|  |  | 
|  | if is_variadic { | 
|  | args.push(quote! { ... }); | 
|  | } | 
|  |  | 
|  | args | 
|  | } | 
|  |  | 
|  | pub(crate) fn fnsig_arguments( | 
|  | ctx: &BindgenContext, | 
|  | sig: &FunctionSig, | 
|  | ) -> Vec<proc_macro2::TokenStream> { | 
|  | fnsig_arguments_iter( | 
|  | ctx, | 
|  | sig.argument_types().iter(), | 
|  | sig.is_variadic(), | 
|  | ) | 
|  | } | 
|  |  | 
|  | pub(crate) fn fnsig_argument_identifiers( | 
|  | ctx: &BindgenContext, | 
|  | sig: &FunctionSig, | 
|  | ) -> Vec<proc_macro2::TokenStream> { | 
|  | let mut unnamed_arguments = 0; | 
|  | let args = sig | 
|  | .argument_types() | 
|  | .iter() | 
|  | .map(|&(ref name, _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()); | 
|  | let arg_name = ctx.rust_ident(arg_name); | 
|  |  | 
|  | quote! { | 
|  | #arg_name | 
|  | } | 
|  | }) | 
|  | .collect::<Vec<_>>(); | 
|  |  | 
|  | args | 
|  | } | 
|  |  | 
|  | pub(crate) fn fnsig_block( | 
|  | ctx: &BindgenContext, | 
|  | sig: &FunctionSig, | 
|  | ) -> proc_macro2::TokenStream { | 
|  | let args = sig.argument_types().iter().map(|&(_, ty)| { | 
|  | let arg_item = ctx.resolve_item(ty); | 
|  |  | 
|  | arg_item.to_rust_ty_or_opaque(ctx, &()) | 
|  | }); | 
|  |  | 
|  | let ret_ty = fnsig_return_ty_internal(ctx, sig); | 
|  | quote! { | 
|  | *const ::block::Block<(#(#args,)*), #ret_ty> | 
|  | } | 
|  | } | 
|  |  | 
|  | // 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 | 
|  | // mangling. | 
|  | pub(crate) fn names_will_be_identical_after_mangling( | 
|  | canonical_name: &str, | 
|  | mangled_name: &str, | 
|  | call_conv: Option<ClangAbi>, | 
|  | ) -> bool { | 
|  | // 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(super) fn 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(), | 
|  | ); | 
|  | }); | 
|  | } | 
|  | } |