diff options
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 5050 |
1 files changed, 0 insertions, 5050 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs deleted file mode 100644 index 7e0d7aa0..00000000 --- a/src/codegen/mod.rs +++ /dev/null @@ -1,5050 +0,0 @@ -mod dyngen; -mod error; -mod helpers; -mod impl_debug; -mod impl_partialeq; -mod postprocessing; -pub 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::ir::analysis::{HasVtable, Sizedness}; -use crate::ir::annotations::FieldAccessorKind; -use crate::ir::comment; -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::{Abi, 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::{self, Ident, Span}; -use quote::TokenStreamExt; - -use crate::{Entry, HashMap, HashSet}; -use std::borrow::Cow; -use std::cell::Cell; -use std::collections::VecDeque; -use std::fmt::Write; -use std::iter; -use std::ops; -use std::str::FromStr; - -// Name of type defined in constified enum module -pub 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! { - 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(); - - let all_template_params = item.all_template_params(ctx); - - if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { - derivable_traits |= DerivableTraits::COPY; - - if ctx.options().rust_features().builtin_clone_impls || - !all_template_params.is_empty() - { - // FIXME: This requires extra logic if you have a big array in a - // templated struct. The reason for this is that the magic: - // fn clone(&self) -> Self { *self } - // doesn't work for templates. - // - // It's not hard to fix though. - derivable_traits |= DerivableTraits::CLONE; - } - } else if packed { - // If the struct or union is packed, deriving from Copy is required for - // deriving from any other trait. - return derivable_traits; - } - - if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() { - derivable_traits |= DerivableTraits::DEBUG; - } - - if item.can_derive_default(ctx) && !item.annotations().disallow_default() { - derivable_traits |= DerivableTraits::DEFAULT; - } - - if item.can_derive_hash(ctx) { - derivable_traits |= DerivableTraits::HASH; - } - - if item.can_derive_partialord(ctx) { - derivable_traits |= DerivableTraits::PARTIAL_ORD; - } - - if item.can_derive_ord(ctx) { - derivable_traits |= DerivableTraits::ORD; - } - - if item.can_derive_partialeq(ctx) { - derivable_traits |= DerivableTraits::PARTIAL_EQ; - } - - if item.can_derive_eq(ctx) { - derivable_traits |= DerivableTraits::EQ; - } - - derivable_traits -} - -impl From<DerivableTraits> for Vec<&'static str> { - fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> { - [ - (DerivableTraits::DEBUG, "Debug"), - (DerivableTraits::DEFAULT, "Default"), - (DerivableTraits::COPY, "Copy"), - (DerivableTraits::CLONE, "Clone"), - (DerivableTraits::HASH, "Hash"), - (DerivableTraits::PARTIAL_ORD, "PartialOrd"), - (DerivableTraits::ORD, "Ord"), - (DerivableTraits::PARTIAL_EQ, "PartialEq"), - (DerivableTraits::EQ, "Eq"), - ] - .iter() - .filter_map(|&(flag, derive)| { - Some(derive).filter(|_| derivable_traits.contains(flag)) - }) - .collect() - } -} - -struct 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>, -} - -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(), - } - } - - 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<'a> ops::Deref for CodegenResult<'a> { - type Target = Vec<proc_macro2::TokenStream>; - - fn deref(&self) -> &Self::Target { - &self.items - } -} - -impl<'a> ops::DerefMut for CodegenResult<'a> { - 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) -> proc_macro2::TokenStream; -} - -impl ToPtr for proc_macro2::TokenStream { - fn to_ptr(self, is_const: bool) -> proc_macro2::TokenStream { - if is_const { - quote! { *const #self } - } else { - quote! { *mut #self } - } - } -} - -/// An extension trait for `proc_macro2::TokenStream` that lets us append any implicit -/// template parameters that exist for some type, if necessary. -trait AppendImplicitTemplateParams { - fn append_implicit_template_params( - &mut self, - ctx: &BindgenContext, - item: &Item, - ); -} - -impl AppendImplicitTemplateParams for proc_macro2::TokenStream { - fn append_implicit_template_params( - &mut self, - ctx: &BindgenContext, - item: &Item, - ) { - let item = item.id().into_resolver().through_type_refs().resolve(ctx); - - 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(..) => return, - _ => {} - } - - let params: Vec<_> = item - .used_template_params(ctx) - .iter() - .map(|p| { - p.try_to_rust_ty(ctx, &()) - .expect("template params cannot fail to be a rust type") - }) - .collect(); - if !params.is_empty() { - self.append_all(quote! { - < #( #params ),* > - }); - } - } -} - -trait CodeGenerator { - /// Extra information from the caller. - type Extra; - - /// Extra information returned to the caller. - type Return; - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - _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<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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_complex_type() { - utils::prepend_complex_type(&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("::"); - 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<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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 ty = self.ty().to_rust_ty_or_opaque(ctx, &()); - - if let Some(val) = self.val() { - match *val { - VarType::Bool(val) => { - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : #ty = #val ; - }); - } - VarType::Int(val) => { - let int_kind = self - .ty() - .into_resolver() - .through_type_aliases() - .through_type_refs() - .resolve(ctx) - .expect_type() - .as_integer() - .unwrap(); - let val = if int_kind.is_signed() { - helpers::ast_ty::int_expr(val) - } else { - helpers::ast_ty::uint_expr(val as _) - }; - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : #ty = #val ; - }); - } - VarType::String(ref bytes) => { - // Account the trailing zero. - // - // TODO: Here we ignore the type we just made up, probably - // we should refactor how the variable type and ty id work. - let len = bytes.len() + 1; - let ty = quote! { - [u8; #len] - }; - - match String::from_utf8(bytes.clone()) { - Ok(string) => { - let cstr = helpers::ast_ty::cstr_expr(string); - if ctx - .options() - .rust_features - .static_lifetime_elision - { - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : &#ty = #cstr ; - }); - } else { - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : &'static #ty = #cstr ; - }); - } - } - Err(..) => { - let bytes = helpers::ast_ty::byte_array_expr(bytes); - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : #ty = #bytes ; - }); - } - } - } - VarType::Float(f) => { - if let Ok(expr) = helpers::ast_ty::float_expr(ctx, f) { - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : #ty = #expr ; - }); - } - } - VarType::Char(c) => { - result.push(quote! { - #(#attrs)* - pub const #canonical_ident : #ty = #c ; - }); - } - } - } else { - // If necessary, apply a `#[link_name]` attribute - let link_name = self.mangled_name().unwrap_or_else(|| self.name()); - if !utils::names_will_be_identical_after_mangling( - &canonical_name, - link_name, - None, - ) { - attrs.push(attributes::link_name(link_name)); - } - - let maybe_mut = if self.is_const() { - quote! {} - } else { - quote! { mut } - }; - - let tokens = quote!( - extern "C" { - #(#attrs)* - pub static #maybe_mut #canonical_ident: #ty; - } - ); - - result.push(tokens); - } - } -} - -impl CodeGenerator for Type { - type Extra = Item; - type Return = (); - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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 `{}` ({}) does not match the target pointer size ({})", - spelling, - 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 `{}` ({}) does not match the target pointer size ({})", - spelling, - 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. - let mut inner_ty = inner_item - .try_to_rust_ty_or_opaque(ctx, &()) - .unwrap_or_else(|_| self.to_opaque(ctx, item)); - inner_ty.append_implicit_template_params(ctx, inner_item); - inner_ty - }; - - { - // 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); - - let mut tokens = if let Some(comment) = item.comment(ctx) { - attributes::doc(comment) - } else { - quote! {} - }; - - let alias_style = if ctx.options().type_alias.matches(&name) { - AliasVariation::TypeAlias - } else if ctx.options().new_type_alias.matches(&name) { - AliasVariation::NewType - } else if ctx.options().new_type_alias_deref.matches(&name) { - AliasVariation::NewTypeDeref - } else { - ctx.options().default_alias_style - }; - - // We prefer using `pub use` over `pub type` because of: - // https://github.com/rust-lang/rust/issues/26264 - // These are the only characters allowed in simple - // paths, eg `good::dogs::Bront`. - if inner_rust_type.to_string().chars().all(|c| matches!(c, 'A'..='Z' | 'a'..='z' | '0'..='9' | ':' | '_' | ' ')) && 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 => { - assert!( - ctx.options().rust_features().repr_transparent, - "repr_transparent feature is required to use {:?}", - alias_style - ); - - 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); - if !derivable_traits.is_empty() { - let derives: Vec<_> = derivable_traits.into(); - attributes.push(attributes::derives(&derives)) - } - - 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 => { - quote! { - (pub #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<'a> CodeGenerator for Vtable<'a> { - type Extra = Item; - type Return = (); - - fn codegen<'b>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'b>, - 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 signature = match signature_item.expect_type().kind() { - TypeKind::Function(ref sig) => sig, - _ => 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<'a> ItemCanonicalName for Vtable<'a> { - fn canonical_name(&self, ctx: &BindgenContext) -> String { - format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx)) - } -} - -impl<'a> TryToRustTy for Vtable<'a> { - type Extra = (); - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result<proc_macro2::TokenStream> { - let name = ctx.rust_ident(self.canonical_name(ctx)); - Ok(quote! { - #name - }) - } -} - -impl CodeGenerator for TemplateInstantiation { - type Extra = Item; - type Return = (); - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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; - } - - // 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 mut fn_name = - format!("__bindgen_test_layout_{}_instantiation", name); - let times_seen = result.overload_number(&fn_name); - if times_seen > 0 { - write!(&mut fn_name, "_{}", times_seen).unwrap(); - } - - let fn_name = 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 item = quote! { - #[test] - fn #fn_name() { - assert_eq!(#size_of_expr, #size, - concat!("Size of template specialization: ", - stringify!(#ident))); - assert_eq!(#align_of_expr, #align, - concat!("Alignment of template specialization: ", - stringify!(#ident))); - } - }; - - result.push(item); - } - } -} - -/// 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, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - 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<'a> FieldCodegen<'a> for Field { - type Extra = (); - - fn codegen<F, M>( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - 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, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - result, - struct_layout, - fields, - methods, - (), - ); - } - Field::Bitfields(ref unit) => { - unit.codegen( - ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - result, - struct_layout, - fields, - methods, - (), - ); - } - } - } -} - -fn wrap_union_field_if_needed( - ctx: &BindgenContext, - struct_layout: &StructLayoutTracker, - ty: proc_macro2::TokenStream, - result: &mut CodegenResult, -) -> proc_macro2::TokenStream { - if struct_layout.is_rust_union() { - if struct_layout.can_copy_union_fields() { - ty - } else { - let prefix = ctx.trait_prefix(); - quote! { - ::#prefix::mem::ManuallyDrop<#ty> - } - } - } else { - result.saw_bindgen_union(); - if ctx.options().enable_cxx_namespaces { - quote! { - root::__BindgenUnionField<#ty> - } - } else { - quote! { - __BindgenUnionField<#ty> - } - } - } -} - -impl<'a> FieldCodegen<'a> for FieldData { - type Extra = (); - - fn codegen<F, M>( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - 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 mut ty = self.ty().to_rust_ty_or_opaque(ctx, &()); - ty.append_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) { - result.saw_incomplete_array(); - - let inner = item.to_rust_ty_or_opaque(ctx, &()); - - if ctx.options().enable_cxx_namespaces { - quote! { - root::__IncompleteArrayField<#inner> - } - } else { - quote! { - __IncompleteArrayField<#inner> - } - } - } else { - ty - }; - - let mut field = quote! {}; - if ctx.options().generate_comments { - if let Some(raw_comment) = self.comment() { - let comment = - comment::preprocess(raw_comment, codegen_depth + 1); - 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_ident = ctx.rust_ident_raw(field_name.as_str()); - - if let Some(padding_field) = - struct_layout.saw_field(&field_name, field_ty, self.offset()) - { - fields.extend(Some(padding_field)); - } - - let is_private = (!self.is_public() && - ctx.options().respect_cxx_access_specs) || - self.annotations() - .private_fields() - .unwrap_or(fields_should_be_private); - - let accessor_kind = - self.annotations().accessor_kind().unwrap_or(accessor_kind); - - if is_private { - field.append_all(quote! { - #field_ident : #ty , - }); - } else { - 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_{}_mut", field_name)); - let field_name = ctx.rust_ident_raw(field_name); - - methods.extend(Some(match accessor_kind { - FieldAccessorKind::None => unreachable!(), - FieldAccessorKind::Regular => { - quote! { - #[inline] - pub fn #getter_name(&self) -> & #ty { - &self.#field_name - } - - #[inline] - pub fn #mutable_getter_name(&mut self) -> &mut #ty { - &mut self.#field_name - } - } - } - FieldAccessorKind::Unsafe => { - quote! { - #[inline] - pub unsafe fn #getter_name(&self) -> & #ty { - &self.#field_name - } - - #[inline] - pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty { - &mut self.#field_name - } - } - } - FieldAccessorKind::Immutable => { - quote! { - #[inline] - pub fn #getter_name(&self) -> & #ty { - &self.#field_name - } - } - } - })); - } -} - -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(ctx, 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( - ctx: &BindgenContext, - is_pub: bool, -) -> proc_macro2::TokenStream { - if is_pub || !ctx.options().respect_cxx_access_specs { - quote! { pub } - } else { - quote! {} - } -} - -impl<'a> FieldCodegen<'a> for BitfieldUnit { - type Extra = (); - - fn codegen<F, M>( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - codegen_depth: usize, - accessor_kind: FieldAccessorKind, - parent: &CompInfo, - 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 = if parent.is_union() { - wrap_union_field_if_needed( - ctx, - struct_layout, - unit_field_ty.clone(), - result, - ) - } else { - unit_field_ty.clone() - }; - - { - let align_field_name = format!("_bitfield_align_{}", self.nth()); - let align_field_ident = ctx.rust_ident(&align_field_name); - let align_ty = match self.layout().align { - n if n >= 8 => quote! { u64 }, - 4 => quote! { u32 }, - 2 => quote! { u16 }, - _ => quote! { u8 }, - }; - let align_field = quote! { - pub #align_field_ident: [#align_ty; 0], - }; - fields.extend(Some(align_field)); - } - - 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 access_spec = !fields_should_be_private; - for bf in self.bitfields() { - // Codegen not allowed for anonymous bitfields - if bf.name().is_none() { - continue; - } - - if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT && - !ctx.options().rust_features().larger_arrays - { - continue; - } - - access_spec &= bf.is_public(); - let mut bitfield_representable_as_int = true; - - bf.codegen( - ctx, - fields_should_be_private, - codegen_depth, - accessor_kind, - parent, - result, - struct_layout, - fields, - methods, - (&unit_field_name, &mut bitfield_representable_as_int), - ); - - // 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, param_name, ctor_impl); - } - - let access_spec = access_specifier(ctx, access_spec); - - 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_setter_name( - ctx: &BindgenContext, - bitfield: &Bitfield, -) -> proc_macro2::TokenStream { - let setter = bitfield.setter_name(); - let setter = ctx.rust_ident_raw(setter); - quote! { #setter } -} - -impl<'a> FieldCodegen<'a> for Bitfield { - type Extra = (&'a str, &'a mut bool); - - fn codegen<F, M>( - &self, - ctx: &BindgenContext, - fields_should_be_private: bool, - _codegen_depth: usize, - _accessor_kind: FieldAccessorKind, - parent: &CompInfo, - _result: &mut CodegenResult, - struct_layout: &mut StructLayoutTracker, - _fields: &mut F, - methods: &mut M, - (unit_field_name, bitfield_representable_as_int): (&'a str, &mut bool), - ) 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 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_layout = bitfield_ty - .layout(ctx) - .expect("Bitfield without layout? Gah!"); - let bitfield_int_ty = - match helpers::integer_type(ctx, bitfield_ty_layout) { - Some(int_ty) => { - *bitfield_representable_as_int = true; - int_ty - } - None => { - *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 access_spec = access_specifier( - ctx, - self.is_public() && !fields_should_be_private, - ); - - 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 - ) - } - } - })); - } 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 - ) - } - } - })); - } - } -} - -impl CodeGenerator for CompInfo { - type Extra = Item; - type Return = (); - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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 mut struct_layout = - StructLayoutTracker::new(ctx, self, ty, &canonical_name); - - 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 mut inner = inner_item.to_rust_ty_or_opaque(ctx, &()); - inner.append_implicit_template_params(ctx, inner_item); - let field_name = ctx.rust_ident(&base.field_name); - - struct_layout.saw_base(inner_item.expect_type()); - - let access_spec = access_specifier(ctx, base.is_public()); - fields.push(quote! { - #access_spec #field_name: #inner, - }); - } - } - - let mut methods = vec![]; - if !is_opaque { - let codegen_depth = item.codegen_depth(ctx); - let fields_should_be_private = - item.annotations().private_fields().unwrap_or(false); - let struct_accessor_kind = item - .annotations() - .accessor_kind() - .unwrap_or(FieldAccessorKind::None); - for field in self.fields() { - field.codegen( - ctx, - fields_should_be_private, - codegen_depth, - struct_accessor_kind, - self, - 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); - let ty = helpers::blob(ctx, Layout::new(1, 1)); - struct_layout.saw_field_with_layout( - "_address", - layout, - /* offset = */ Some(0), - ); - fields.push(quote! { - pub _address: #ty, - }); - } - } - - if is_opaque { - match layout { - Some(l) => { - explicit_align = Some(l.align); - - let ty = helpers::blob(ctx, l); - fields.push(quote! { - pub _bindgen_opaque_blob: #ty , - }); - } - None => { - 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); - if !ctx.options().rust_features.repr_align { - let ty = helpers::blob( - ctx, - Layout::new(0, layout.align), - ); - fields.push(quote! { - pub __bindgen_align: #ty , - }); - } - } - } - } - } else if is_union && !forward_decl { - // TODO(emilio): It'd be nice to unify this with the struct path - // above somehow. - let layout = layout.expect("Unable to get layout information?"); - if struct_layout.requires_explicit_align(layout) { - explicit_align = Some(layout.align); - } - - if !struct_layout.is_rust_union() { - let ty = helpers::blob(ctx, layout); - fields.push(quote! { - pub bindgen_union_field: #ty , - }) - } - } - - if forward_decl { - fields.push(quote! { - _unused: [u8; 0], - }); - } - - 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> - > , - }); - } - - let generics = if !generic_param_names.is_empty() { - let generic_param_names = generic_param_names.clone(); - quote! { - < #( #generic_param_names ),* > - } - } else { - 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; - if let Some(comment) = item.comment(ctx) { - attributes.push(attributes::doc(comment)); - } - if packed && !is_opaque { - let n = layout.map_or(1, |l| l.align); - assert!(ctx.options().rust_features().repr_packed_n || n == 1); - 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")); - } - - if ctx.options().rust_features().repr_align { - if let Some(explicit) = explicit_align { - // Ensure that the struct has the correct alignment even in - // presence of alignas. - 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)); - - // The custom derives callback may return a list of derive attributes; - // add them to the end of the list. - let custom_derives; - if let Some(cb) = &ctx.options().parse_callbacks { - custom_derives = cb.add_derives(&canonical_name); - // In most cases this will be a no-op, since custom_derives will be empty. - derives.extend(custom_derives.iter().map(|s| s.as_str())); - }; - - if !derives.is_empty() { - attributes.push(attributes::derives(&derives)) - } - - if item.must_use(ctx) { - attributes.push(attributes::must_use()); - } - - let mut tokens = if is_union && struct_layout.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 {} has an unknown attribute that may affect layout", - canonical_ident - ); - } - - 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 fn_name = - format!("bindgen_test_layout_{}", canonical_ident); - let fn_name = 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 check_struct_align = if align > - ctx.target_pointer_size() && - !ctx.options().rust_features().repr_align - { - None - } else { - Some(quote! { - assert_eq!(#align_of_expr, - #align, - concat!("Alignment of ", stringify!(#canonical_ident))); - - }) - }; - - // FIXME when [issue #465](https://github.com/rust-lang/rust-bindgen/issues/465) ready - let too_many_base_vtables = self - .base_members() - .iter() - .filter(|base| base.ty.has_vtable(ctx)) - .count() > - 1; - - let should_skip_field_offset_checks = - is_opaque || too_many_base_vtables; - - let check_field_offset = if should_skip_field_offset_checks - { - vec![] - } else { - self.fields() - .iter() - .filter_map(|field| match *field { - Field::DataMember(ref f) if f.name().is_some() => Some(f), - _ => None, - }) - .flat_map(|field| { - let name = field.name().unwrap(); - field.offset().map(|offset| { - let field_offset = offset / 8; - let field_name = ctx.rust_ident(name); - quote! { - assert_eq!( - unsafe { - ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize - }, - #field_offset, - concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name)) - ); - } - }) - }) - .collect() - }; - - let uninit_decl = if !check_field_offset.is_empty() { - // 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(); - }) - } else { - None - }; - - let item = quote! { - #[test] - fn #fn_name() { - #uninit_decl - assert_eq!(#size_of_expr, - #size, - concat!("Size of: ", stringify!(#canonical_ident))); - #check_struct_align - #( #check_field_offset )* - } - }; - result.push(item); - } - } - - let mut method_names = Default::default(); - if ctx.options().codegen_config.methods() { - for method in self.methods() { - assert!(method.kind() != MethodKind::Constructor); - method.codegen_method( - ctx, - &mut methods, - &mut method_names, - result, - self, - ); - } - } - - 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, - ); - } - } - - 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, - ); - } - } - } - - // 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 #generics - }; - - if needs_clone_impl { - result.push(quote! { - impl #generics Clone for #ty_for_impl { - fn clone(&self) -> Self { *self } - } - }); - } - - if needs_default_impl { - let prefix = ctx.trait_prefix(); - let body = if ctx.options().rust_features().maybe_uninit { - quote! { - let mut s = ::#prefix::mem::MaybeUninit::<Self>::uninit(); - unsafe { - ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 0, 1); - s.assume_init() - } - } - } else { - quote! { - unsafe { - let mut s: Self = ::#prefix::mem::uninitialized(); - ::#prefix::ptr::write_bytes(&mut s, 0, 1); - s - } - } - }; - // 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 compatability is - // involved. - result.push(quote! { - impl #generics 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 #generics ::#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() { - let bounds = generic_param_names.iter().map(|t| { - quote! { #t: PartialEq } - }); - quote! { where #( #bounds ),* } - } else { - quote! {} - }; - - let prefix = ctx.trait_prefix(); - result.push(quote! { - impl #generics ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds { - #impl_ - } - }); - } - } - - if !methods.is_empty() { - result.push(quote! { - impl #generics #ty_for_impl { - #( #methods )* - } - }); - } - } -} - -trait MethodCodegen { - fn codegen_method<'a>( - &self, - ctx: &BindgenContext, - methods: &mut Vec<proc_macro2::TokenStream>, - method_names: &mut HashMap<String, usize>, - result: &mut CodegenResult<'a>, - parent: &CompInfo, - ); -} - -impl MethodCodegen for Method { - fn codegen_method<'a>( - &self, - ctx: &BindgenContext, - methods: &mut Vec<proc_macro2::TokenStream>, - method_names: &mut HashMap<String, usize>, - result: &mut CodegenResult<'a>, - _parent: &CompInfo, - ) { - assert!({ - let cc = &ctx.options().codegen_config; - match self.kind() { - MethodKind::Constructor => cc.constructors(), - MethodKind::Destructor => cc.destructors(), - 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 times_seen = match times_seen { - Some(seen) => seen, - None => 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 signature = match *signature_item.expect_type().kind() { - TypeKind::Function(ref sig) => sig, - _ => panic!("How in the world?"), - }; - - let supported_abi = match signature.abi() { - Abi::ThisCall => ctx.options().rust_features().thiscall_abi, - Abi::Vectorcall => ctx.options().rust_features().vectorcall_abi, - _ => true, - }; - - 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; - } - - let count = { - let count = method_names.entry(name.clone()).or_insert(0); - *count += 1; - *count - 1 - }; - - if count != 0 { - name.push_str(&count.to_string()); - } - - 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(); - let tmp_variable_decl = if ctx - .options() - .rust_features() - .maybe_uninit - { - exprs[0] = quote! { - __bindgen_tmp.as_mut_ptr() - }; - quote! { - let mut __bindgen_tmp = ::#prefix::mem::MaybeUninit::uninit() - } - } else { - exprs[0] = quote! { - &mut __bindgen_tmp - }; - quote! { - let mut __bindgen_tmp = ::#prefix::mem::uninitialized() - } - }; - 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(if ctx.options().rust_features().maybe_uninit { - quote! { - __bindgen_tmp.assume_init() - } - } else { - quote! { - __bindgen_tmp - } - }) - } - - let block = quote! { - #( #stmts );* - }; - - let mut attrs = vec![attributes::inline()]; - - if signature.must_use() && - ctx.options().rust_features().must_use_function - { - 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)] -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 - 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 Default for EnumVariation { - fn default() -> EnumVariation { - EnumVariation::Consts - } -} - -impl std::str::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'." - ), - )), - } - } -} - -/// A helper type to construct different enum variations. -enum EnumBuilder<'a> { - Rust { - codegen_depth: usize, - attrs: Vec<proc_macro2::TokenStream>, - ident: Ident, - tokens: proc_macro2::TokenStream, - emitted_any_variants: bool, - }, - NewType { - codegen_depth: usize, - canonical_name: &'a str, - tokens: proc_macro2::TokenStream, - is_bitfield: bool, - is_global: bool, - }, - Consts { - variants: Vec<proc_macro2::TokenStream>, - codegen_depth: usize, - }, - ModuleConsts { - codegen_depth: usize, - module_name: &'a str, - module_items: Vec<proc_macro2::TokenStream>, - }, -} - -impl<'a> EnumBuilder<'a> { - /// Returns the depth of the code generation for a variant of this enum. - fn codegen_depth(&self) -> usize { - match *self { - EnumBuilder::Rust { codegen_depth, .. } | - EnumBuilder::NewType { codegen_depth, .. } | - EnumBuilder::ModuleConsts { codegen_depth, .. } | - EnumBuilder::Consts { codegen_depth, .. } => codegen_depth, - } - } - - /// Returns true if the builder is for a rustified enum. - fn is_rust_enum(&self) -> bool { - matches!(*self, EnumBuilder::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: &'a str, - mut attrs: Vec<proc_macro2::TokenStream>, - repr: proc_macro2::TokenStream, - enum_variation: EnumVariation, - enum_codegen_depth: usize, - ) -> Self { - let ident = Ident::new(name, Span::call_site()); - - match enum_variation { - EnumVariation::NewType { - is_bitfield, - is_global, - } => EnumBuilder::NewType { - codegen_depth: enum_codegen_depth, - canonical_name: name, - tokens: quote! { - #( #attrs )* - pub struct #ident (pub #repr); - }, - is_bitfield, - is_global, - }, - - EnumVariation::Rust { .. } => { - // `repr` is guaranteed to be Rustified in Enum::codegen - attrs.insert(0, quote! { #[repr( #repr )] }); - let tokens = quote!(); - EnumBuilder::Rust { - codegen_depth: enum_codegen_depth + 1, - attrs, - ident, - tokens, - emitted_any_variants: false, - } - } - - EnumVariation::Consts => { - let mut variants = Vec::new(); - - variants.push(quote! { - #( #attrs )* - pub type #ident = #repr; - }); - - EnumBuilder::Consts { - variants, - codegen_depth: enum_codegen_depth, - } - } - - EnumVariation::ModuleConsts => { - let ident = Ident::new( - CONSTIFIED_ENUM_MODULE_REPR_NAME, - Span::call_site(), - ); - let type_definition = quote! { - #( #attrs )* - pub type #ident = #repr; - }; - - EnumBuilder::ModuleConsts { - codegen_depth: enum_codegen_depth + 1, - module_name: name, - module_items: vec![type_definition], - } - } - } - } - - /// Add a variant to this enum. - fn with_variant<'b>( - self, - ctx: &BindgenContext, - variant: &EnumVariant, - mangling_prefix: Option<&str>, - rust_ty: proc_macro2::TokenStream, - result: &mut CodegenResult<'b>, - 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(v as u64) - } - EnumVariantValue::Boolean(v) => quote!(#v), - EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v), - EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v), - }; - - let mut doc = quote! {}; - if ctx.options().generate_comments { - if let Some(raw_comment) = variant.comment() { - let comment = - comment::preprocess(raw_comment, self.codegen_depth()); - doc = attributes::doc(comment); - } - } - - match self { - EnumBuilder::Rust { - attrs, - ident, - tokens, - emitted_any_variants: _, - codegen_depth, - } => { - let name = ctx.rust_ident(variant_name); - EnumBuilder::Rust { - attrs, - ident, - codegen_depth, - tokens: quote! { - #tokens - #doc - #name = #expr, - }, - emitted_any_variants: true, - } - } - - EnumBuilder::NewType { - canonical_name, - is_global, - .. - } => { - if ctx.options().rust_features().associated_const && - is_ty_named && - !is_global - { - let enum_ident = ctx.rust_ident(canonical_name); - let variant_ident = ctx.rust_ident(variant_name); - - result.push(quote! { - impl #enum_ident { - #doc - pub const #variant_ident : #rust_ty = #rust_ty ( #expr ); - } - }); - } else { - let ident = ctx.rust_ident(match mangling_prefix { - Some(prefix) => { - Cow::Owned(format!("{}_{}", prefix, variant_name)) - } - None => variant_name, - }); - result.push(quote! { - #doc - pub const #ident : #rust_ty = #rust_ty ( #expr ); - }); - } - - self - } - - EnumBuilder::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); - result.push(quote! { - #doc - pub const #ident : #rust_ty = #expr ; - }); - - self - } - EnumBuilder::ModuleConsts { - codegen_depth, - module_name, - mut module_items, - } => { - let name = ctx.rust_ident(variant_name); - let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME); - module_items.push(quote! { - #doc - pub const #name : #ty = #expr ; - }); - - EnumBuilder::ModuleConsts { - module_name, - module_items, - codegen_depth, - } - } - } - } - - fn build<'b>( - self, - ctx: &BindgenContext, - rust_ty: proc_macro2::TokenStream, - result: &mut CodegenResult<'b>, - ) -> proc_macro2::TokenStream { - match self { - EnumBuilder::Rust { - attrs, - ident, - tokens, - emitted_any_variants, - .. - } => { - let variants = if !emitted_any_variants { - quote!(__bindgen_cannot_repr_c_on_empty_enum = 0) - } else { - tokens - }; - - quote! { - #( #attrs )* - pub enum #ident { - #variants - } - } - } - EnumBuilder::NewType { - canonical_name, - tokens, - is_bitfield, - .. - } => { - if !is_bitfield { - return tokens; - } - - let rust_ty_name = ctx.rust_ident_raw(canonical_name); - let prefix = ctx.trait_prefix(); - - result.push(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) - } - } - }); - - result.push(quote! { - impl ::#prefix::ops::BitOrAssign for #rust_ty { - #[inline] - fn bitor_assign(&mut self, rhs: #rust_ty) { - self.0 |= rhs.0; - } - } - }); - - result.push(quote! { - 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) - } - } - }); - - result.push(quote! { - impl ::#prefix::ops::BitAndAssign for #rust_ty { - #[inline] - fn bitand_assign(&mut self, rhs: #rust_ty) { - self.0 &= rhs.0; - } - } - }); - - tokens - } - EnumBuilder::Consts { variants, .. } => quote! { #( #variants )* }, - EnumBuilder::ModuleConsts { - module_items, - module_name, - .. - } => { - let ident = ctx.rust_ident(module_name); - quote! { - pub mod #ident { - #( #module_items )* - } - } - } - } - } -} - -impl CodeGenerator for Enum { - type Extra = Item; - type Return = (); - - fn codegen<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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 = match repr { - Some(repr) => match *repr.canonical_type(ctx).kind() { - TypeKind::Int(int_kind) => int_kind, - _ => panic!("Unexpected type as enum repr"), - }, - None => { - 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: {}, size: {}", - signed, size - ); - IntKind::I32 - } - }; - - repr_translated = - Type::new(None, None, TypeKind::Int(translated), false); - &repr_translated - } - }; - - let mut attrs = vec![]; - - // TODO(emilio): Delegate this to the builders? - match variation { - EnumVariation::Rust { non_exhaustive } => { - if non_exhaustive && - ctx.options().rust_features().non_exhaustive - { - attrs.push(attributes::non_exhaustive()); - } else if non_exhaustive && - !ctx.options().rust_features().non_exhaustive - { - panic!("The rust target you're using doesn't seem to support non_exhaustive enums"); - } - } - EnumVariation::NewType { .. } => { - if ctx.options().rust_features.repr_transparent { - attrs.push(attributes::repr("transparent")); - } else { - attrs.push(attributes::repr("C")); - } - } - _ => {} - }; - - 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().iter() { - 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; - if let Some(cb) = &ctx.options().parse_callbacks { - custom_derives = cb.add_derives(&name); - // In most cases this will be a no-op, since custom_derives will be empty. - derives.extend(custom_derives.iter().map(|s| s.as_str())); - }; - - attrs.push(attributes::derives(&derives)); - } - - fn add_constant<'a>( - 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: proc_macro2::TokenStream, - result: &mut CodegenResult<'a>, - ) { - 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 mut builder = EnumBuilder::new( - &name, - attrs, - repr, - variation, - item.codegen_depth(ctx), - ); - - // 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; - } - - 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() && - ctx.options().rust_features().associated_const - { - 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.clone(), - result, - ); - } - } else { - builder = builder.with_variant( - ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result, - enum_ty.name().is_some(), - ); - } - } - Entry::Vacant(entry) => { - builder = builder.with_variant( - ctx, - variant, - constant_mangling_prefix, - enum_rust_ty.clone(), - result, - 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.clone(), - result, - ); - } - - entry.insert(variant_name); - } - } - } - - let item = builder.build(ctx, enum_rust_ty, result); - result.push(item); - } -} - -/// Enum for the default type of macro constants. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum MacroTypeVariation { - /// Use i32 or i64 - Signed, - /// Use u32 or u64 - Unsigned, -} - -impl MacroTypeVariation { - /// Convert a `MacroTypeVariation` to its str representation. - pub fn as_str(&self) -> &str { - match self { - MacroTypeVariation::Signed => "signed", - MacroTypeVariation::Unsigned => "unsigned", - } - } -} - -impl Default for MacroTypeVariation { - fn default() -> MacroTypeVariation { - MacroTypeVariation::Unsigned - } -} - -impl std::str::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)] -pub enum AliasVariation { - /// Convert to regular Rust alias - TypeAlias, - /// Create a new type by wrapping the old type in a struct and using #[repr(transparent)] - NewType, - /// Same as NewStruct but also impl Deref to be able to use the methods of the wrapped type - NewTypeDeref, -} - -impl AliasVariation { - /// Convert an `AliasVariation` to its str representation. - pub fn as_str(&self) -> &str { - match self { - AliasVariation::TypeAlias => "type_alias", - AliasVariation::NewType => "new_type", - AliasVariation::NewTypeDeref => "new_type_deref", - } - } -} - -impl Default for AliasVariation { - fn default() -> AliasVariation { - AliasVariation::TypeAlias - } -} - -impl std::str::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 unions 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 NonCopyUnionStyle { - /// Convert an `NonCopyUnionStyle` to its str representation. - pub fn as_str(&self) -> &'static str { - match self { - Self::BindgenWrapper => "bindgen_wrapper", - Self::ManuallyDrop => "manually_drop", - } - } -} - -impl Default for NonCopyUnionStyle { - fn default() -> Self { - Self::BindgenWrapper - } -} - -impl std::str::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. -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<proc_macro2::TokenStream> { - self.try_get_layout(ctx, extra) - .map(|layout| helpers::blob(ctx, layout)) - } -} - -/// 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. -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, - ) -> proc_macro2::TokenStream { - let layout = self.get_layout(ctx, extra); - helpers::blob(ctx, layout) - } -} - -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. -trait TryToRustTy { - type Extra; - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - extra: &Self::Extra, - ) -> error::Result<proc_macro2::TokenStream>; -} - -/// 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. -trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque { - type Extra; - - fn try_to_rust_ty_or_opaque( - &self, - ctx: &BindgenContext, - extra: &<Self as TryToRustTyOrOpaque>::Extra, - ) -> error::Result<proc_macro2::TokenStream>; -} - -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<proc_macro2::TokenStream> { - self.try_to_rust_ty(ctx, extra).or_else(|_| { - if let Ok(layout) = self.try_get_layout(ctx, extra) { - Ok(helpers::blob(ctx, layout)) - } else { - Err(error::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}` triats? 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. -trait ToRustTyOrOpaque: TryToRustTy + ToOpaque { - type Extra; - - fn to_rust_ty_or_opaque( - &self, - ctx: &BindgenContext, - extra: &<Self as ToRustTyOrOpaque>::Extra, - ) -> proc_macro2::TokenStream; -} - -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, - ) -> proc_macro2::TokenStream { - 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<proc_macro2::TokenStream> { - 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<proc_macro2::TokenStream> { - 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::Error::NoLayoutForOpaqueBlob) - } -} - -impl TryToRustTy for Type { - type Extra = Item; - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> error::Result<proc_macro2::TokenStream> { - 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) => { - match ik { - IntKind::Bool => Ok(quote! { bool }), - IntKind::Char { .. } => Ok(raw_type(ctx, "c_char")), - IntKind::SChar => Ok(raw_type(ctx, "c_schar")), - IntKind::UChar => Ok(raw_type(ctx, "c_uchar")), - IntKind::Short => Ok(raw_type(ctx, "c_short")), - IntKind::UShort => Ok(raw_type(ctx, "c_ushort")), - IntKind::Int => Ok(raw_type(ctx, "c_int")), - IntKind::UInt => Ok(raw_type(ctx, "c_uint")), - IntKind::Long => Ok(raw_type(ctx, "c_long")), - IntKind::ULong => Ok(raw_type(ctx, "c_ulong")), - IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")), - IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")), - IntKind::WChar => { - let layout = self - .layout(ctx) - .expect("Couldn't compute wchar_t's layout?"); - let ty = Layout::known_type_for_size(ctx, layout.size) - .expect("Non-representable wchar_t?"); - let ident = ctx.rust_ident_raw(ty); - Ok(quote! { #ident }) - } - - IntKind::I8 => Ok(quote! { i8 }), - IntKind::U8 => Ok(quote! { u8 }), - IntKind::I16 => Ok(quote! { i16 }), - IntKind::U16 => Ok(quote! { u16 }), - IntKind::I32 => Ok(quote! { i32 }), - IntKind::U32 => Ok(quote! { u32 }), - IntKind::I64 => Ok(quote! { i64 }), - IntKind::U64 => Ok(quote! { u64 }), - IntKind::Custom { name, .. } => { - Ok(proc_macro2::TokenStream::from_str(name).unwrap()) - } - IntKind::U128 => { - Ok(if ctx.options().rust_features.i128_and_u128 { - quote! { u128 } - } else { - // Best effort thing, but wrong alignment - // unfortunately. - quote! { [u64; 2] } - }) - } - IntKind::I128 => { - Ok(if ctx.options().rust_features.i128_and_u128 { - quote! { i128 } - } else { - quote! { [u64; 2] } - }) - } - } - } - 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 { - quote! { - root::__BindgenComplex<#float_path> - } - } else { - quote! { - __BindgenComplex<#float_path> - } - }) - } - TypeKind::Function(ref fs) => { - // 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 = fs.try_to_rust_ty(ctx, &())?; - - let prefix = ctx.trait_prefix(); - Ok(quote! { - ::#prefix::option::Option<#ty> - }) - } - TypeKind::Array(item, len) | TypeKind::Vector(item, len) => { - let ty = item.try_to_rust_ty(ctx, &())?; - Ok(quote! { - [ #ty ; #len ] - }) - } - TypeKind::Enum(..) => { - let path = item.namespace_aware_canonical_path(ctx); - let path = proc_macro2::TokenStream::from_str(&path.join("::")) - .unwrap(); - Ok(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) => { - 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 mut ty = inner.to_rust_ty_or_opaque(ctx, &()); - ty.append_implicit_template_params(ctx, inner); - - // Avoid the first function pointer level, since it's already - // represented in Rust. - if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer - { - Ok(ty) - } else { - Ok(ty.to_ptr(is_const)) - } - } - TypeKind::TypeParam => { - let name = item.canonical_name(ctx); - let ident = ctx.rust_ident(&name); - Ok(quote! { - #ident - }) - } - TypeKind::ObjCSel => Ok(quote! { - objc::runtime::Sel - }), - TypeKind::ObjCId => Ok(quote! { - id - }), - TypeKind::ObjCInterface(ref interface) => { - let name = ctx.rust_ident(interface.name()); - Ok(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::Error::NoLayoutForOpaqueBlob) - } -} - -impl TryToRustTy for TemplateInstantiation { - type Extra = Item; - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - item: &Item, - ) -> error::Result<proc_macro2::TokenStream> { - if self.is_opaque(ctx, item) { - return Err(error::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::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 mut ty = arg.try_to_rust_ty(ctx, &())?; - ty.append_implicit_template_params(ctx, arg); - Ok(ty) - }) - .collect::<error::Result<Vec<_>>>()?; - - if template_args.is_empty() { - return Ok(ty); - } - - Ok(quote! { - #ty < #( #template_args ),* > - }) - } -} - -impl TryToRustTy for FunctionSig { - type Extra = (); - - fn try_to_rust_ty( - &self, - ctx: &BindgenContext, - _: &(), - ) -> error::Result<proc_macro2::TokenStream> { - // 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); - let abi = self.abi(); - - match abi { - Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => { - warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target"); - Ok(proc_macro2::TokenStream::new()) - } - Abi::Vectorcall - if !ctx.options().rust_features().vectorcall_abi => - { - warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target"); - Ok(proc_macro2::TokenStream::new()) - } - _ => Ok(quote! { - unsafe extern #abi fn ( #( #arguments ),* ) #ret - }), - } - } -} - -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<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - item: &Item, - ) -> Self::Return { - debug!("<Function as CodeGenerator>::codegen: item = {:?}", item); - debug_assert!(item.is_enabled_for_codegen(ctx)); - - // We can't currently do anything with Internal functions so just - // avoid generating anything for them. - match self.linkage() { - Linkage::Internal => return None, - Linkage::External => {} - } - - // Pure virtual methods have no actual symbol, so we can't generate - // something meaningful for them. - let is_dynamic_function = match self.kind() { - FunctionKind::Method(ref method_kind) - if method_kind.is_pure_virtual() => - { - return None; - } - FunctionKind::Function => { - ctx.options().dynamic_library_name.is_some() - } - _ => 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 signature_item = ctx.resolve_item(self.signature()); - let signature = signature_item.kind().expect_type().canonical_type(ctx); - let signature = match *signature.kind() { - TypeKind::Function(ref sig) => sig, - _ => panic!("Signature kind is not a Function: {:?}", signature), - }; - - let args = utils::fnsig_arguments(ctx, signature); - let ret = utils::fnsig_return_ty(ctx, signature); - - let mut attributes = vec![]; - - if ctx.options().rust_features().must_use_function { - 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() { - Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => { - warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target"); - return None; - } - Abi::Vectorcall - if !ctx.options().rust_features().vectorcall_abi => - { - warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target"); - return None; - } - Abi::Win64 if signature.is_variadic() => { - warn!("Skipping variadic function with Win64 ABI that isn't supported"); - return None; - } - Abi::Unknown(unknown_abi) => { - panic!( - "Invalid or unknown abi {:?} for function {:?} ({:?})", - unknown_abi, canonical_name, self - ); - } - 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(); - } - - let link_name = mangled_name.unwrap_or(name); - if !is_dynamic_function && - !utils::names_will_be_identical_after_mangling( - &canonical_name, - link_name, - Some(abi), - ) - { - attributes.push(attributes::link_name(link_name)); - } - - // Unfortunately this can't piggyback on the `attributes` list because - // the #[link(wasm_import_module)] needs to happen before the `extern - // "C"` block. It doesn't get picked up properly otherwise - let wasm_link_attribute = - ctx.options().wasm_import_module_name.as_ref().map(|name| { - quote! { #[link(wasm_import_module = #name)] } - }); - - let ident = ctx.rust_ident(canonical_name); - let tokens = quote! { - #wasm_link_attribute - extern #abi { - #(#attributes)* - pub fn #ident ( #( #args ),* ) #ret; - } - }; - - // If we're doing dynamic binding generation, add to the dynamic items. - if is_dynamic_function { - let args_identifiers = - utils::fnsig_argument_identifiers(ctx, signature); - let return_item = ctx.resolve_item(signature.return_type()); - let ret_ty = match *return_item.kind().expect_type().kind() { - TypeKind::Void => quote! {()}, - _ => return_item.to_rust_ty_or_opaque(ctx, &()), - }; - result.dynamic_items().push( - ident, - abi, - signature.is_variadic(), - ctx.options().dynamic_link_require_all, - args, - args_identifiers, - ret, - ret_ty, - attributes, - ); - } else { - result.push(tokens); - } - Some(times_seen) - } -} - -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() { - let fn_args = fn_args.clone(); - quote! { - ( #( #fn_args ),* ) #fn_ret - } - } else { - let fn_args = fn_args.clone(); - let args = iter::once(quote! { &self }).chain(fn_args.into_iter()); - quote! { - ( #( #args ),* ) #fn_ret - } - }; - - let methods_and_args = method.format_method_call(&fn_args); - - 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) - } - }; - - 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<'a>( - &self, - ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - 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.iter() { - 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 parent = match parent { - TypeKind::ObjCInterface(ref parent) => parent, - _ => 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.iter() { - 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 {} cannot be downcasted to {}", - parent_struct_name, 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, -) -> (proc_macro2::TokenStream, BindgenOptions, Vec<String>) { - 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); - result.push(dynamic_items_tokens); - } - - postprocessing::postprocessing(result.items, context.options()) - }) -} - -pub mod utils { - use super::{error, ToRustTyOrOpaque}; - use crate::ir::context::BindgenContext; - use crate::ir::function::{Abi, FunctionSig}; - use crate::ir::item::{Item, ItemCanonicalPath}; - use crate::ir::ty::TypeKind; - use proc_macro2; - use std::borrow::Cow; - use std::mem; - use std::str::FromStr; - - pub fn prepend_bitfield_unit_type( - ctx: &BindgenContext, - result: &mut Vec<proc_macro2::TokenStream>, - ) { - let bitfield_unit_src = include_str!("./bitfield_unit.rs"); - let bitfield_unit_src = if ctx.options().rust_features().min_const_fn { - 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 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.into_iter()); - } - - pub 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.into_iter()); - } - - pub 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 ctx.options().rust_features().min_const_fn { - 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 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 { - ::#prefix::mem::transmute(self) - } - - #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { - ::#prefix::mem::transmute(self) - } - } - }; - - 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::new() - } - } - }; - - 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.into_iter()); - } - - pub 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 ctx.options().rust_features().min_const_fn { - 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 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] { - ::#prefix::slice::from_raw_parts(self.as_ptr(), len) - } - - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } - } - }; - - 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.into_iter()); - } - - pub 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.into_iter()); - } - - pub fn build_path( - item: &Item, - ctx: &BindgenContext, - ) -> error::Result<proc_macro2::TokenStream> { - let path = item.namespace_aware_canonical_path(ctx); - let tokens = - proc_macro2::TokenStream::from_str(&path.join("::")).unwrap(); - - Ok(tokens) - } - - fn primitive_ty( - ctx: &BindgenContext, - name: &str, - ) -> proc_macro2::TokenStream { - let ident = ctx.rust_ident_raw(name); - quote! { - #ident - } - } - - pub fn type_from_named( - ctx: &BindgenContext, - name: &str, - ) -> Option<proc_macro2::TokenStream> { - // 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, - }) - } - - pub fn fnsig_return_ty( - ctx: &BindgenContext, - sig: &FunctionSig, - ) -> proc_macro2::TokenStream { - if sig.is_divergent() { - return quote! { -> ! }; - } - - let return_item = ctx.resolve_item(sig.return_type()); - if let TypeKind::Void = *return_item.kind().expect_type().kind() { - quote! {} - } else { - let ret_ty = return_item.to_rust_ty_or_opaque(ctx, &()); - quote! { - -> #ret_ty - } - } - } - - pub fn fnsig_arguments( - ctx: &BindgenContext, - sig: &FunctionSig, - ) -> Vec<proc_macro2::TokenStream> { - use super::ToPtr; - - let mut unnamed_arguments = 0; - let mut args = sig - .argument_types() - .iter() - .map(|&(ref name, ty)| { - 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 - let arg_ty = 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()) - } - 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()); - quote! { - #name - } - } else { - arg_item.to_rust_ty_or_opaque(ctx, &()) - } - } - _ => arg_item.to_rust_ty_or_opaque(ctx, &()), - }; - - let arg_name = match *name { - Some(ref name) => ctx.rust_mangle(name).into_owned(), - None => { - 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 sig.is_variadic() { - args.push(quote! { ... }) - } - - args - } - - pub 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 = match *name { - Some(ref name) => ctx.rust_mangle(name).into_owned(), - None => { - 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 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 return_item = ctx.resolve_item(sig.return_type()); - let ret_ty = - if let TypeKind::Void = *return_item.kind().expect_type().kind() { - quote! { () } - } else { - return_item.to_rust_ty_or_opaque(ctx, &()) - }; - - 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 fn names_will_be_identical_after_mangling( - canonical_name: &str, - mangled_name: &str, - call_conv: Option<Abi>, - ) -> 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(Abi::C) | - // None is the case for global variables - None => { - (b'_', false) - } - Some(Abi::Stdcall) => (b'_', true), - Some(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() + 1] != 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 - } -} |