1mod dyngen;
2pub(crate) mod error;
3
4mod helpers;
5mod impl_debug;
6mod impl_partialeq;
7mod postprocessing;
8mod serialize;
9pub(crate) mod struct_layout;
10
11#[cfg(test)]
12#[allow(warnings)]
13pub(crate) mod bitfield_unit;
14#[cfg(all(test, target_endian = "little"))]
15mod bitfield_unit_tests;
16
17use self::dyngen::DynamicItems;
18use self::helpers::attributes;
19use self::struct_layout::StructLayoutTracker;
20
21use super::BindgenOptions;
22
23use crate::callbacks::{
24 AttributeInfo, DeriveInfo, DiscoveredItem, DiscoveredItemId,
25 FieldAttributeInfo, FieldInfo, TypeKind as DeriveTypeKind,
26};
27use crate::codegen::error::Error;
28use crate::ir::analysis::{HasVtable, Sizedness};
29use crate::ir::annotations::{
30 Annotations, FieldAccessorKind, FieldVisibilityKind,
31};
32use crate::ir::comp::{
33 Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods,
34 Method, MethodKind,
35};
36use crate::ir::context::{BindgenContext, ItemId};
37use crate::ir::derive::{
38 CanDerive, CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq,
39 CanDeriveHash, CanDeriveOrd, CanDerivePartialEq, CanDerivePartialOrd,
40};
41use crate::ir::dot;
42use crate::ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
43use crate::ir::function::{
44 ClangAbi, Function, FunctionKind, FunctionSig, Linkage,
45};
46use crate::ir::int::IntKind;
47use crate::ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
48use crate::ir::item_kind::ItemKind;
49use crate::ir::layout::Layout;
50use crate::ir::module::Module;
51use crate::ir::objc::{ObjCInterface, ObjCMethod};
52use crate::ir::template::{
53 AsTemplateParam, TemplateInstantiation, TemplateParameters,
54};
55use crate::ir::ty::{Type, TypeKind};
56use crate::ir::var::Var;
57
58use proc_macro2::{Ident, Span};
59use quote::{ToTokens, TokenStreamExt};
60
61use crate::{Entry, HashMap, HashSet};
62use std::borrow::Cow;
63use std::cell::Cell;
64use std::collections::VecDeque;
65use std::ffi::CStr;
66use std::fmt::{self, Write};
67use std::ops;
68use std::str::{self, FromStr};
69
70#[derive(Debug, Clone, PartialEq, Eq, Hash)]
71pub enum CodegenError {
72 Serialize { msg: String, loc: String },
73 Io(String),
74}
75
76impl From<std::io::Error> for CodegenError {
77 fn from(err: std::io::Error) -> Self {
78 Self::Io(err.to_string())
79 }
80}
81
82impl fmt::Display for CodegenError {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 match self {
85 Self::Serialize { msg, loc } => {
86 write!(f, "serialization error at {loc}: {msg}")
87 }
88 Self::Io(err) => err.fmt(f),
89 }
90 }
91}
92
93pub(crate) static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type";
95
96fn top_level_path(
97 ctx: &BindgenContext,
98 item: &Item,
99) -> Vec<proc_macro2::TokenStream> {
100 let mut path = vec![quote! { self }];
101
102 if ctx.options().enable_cxx_namespaces {
103 for _ in 0..item.codegen_depth(ctx) {
104 path.push(quote! { super });
105 }
106 }
107
108 path
109}
110
111fn root_import(
112 ctx: &BindgenContext,
113 module: &Item,
114) -> proc_macro2::TokenStream {
115 assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up");
116 assert!(module.is_module());
117
118 let mut path = top_level_path(ctx, module);
119
120 let root = ctx.root_module().canonical_name(ctx);
121 let root_ident = ctx.rust_ident(root);
122 path.push(quote! { #root_ident });
123
124 let mut tokens = quote! {};
125 tokens.append_separated(path, quote!(::));
126
127 quote! {
128 #[allow(unused_imports)]
129 use #tokens ;
130 }
131}
132
133bitflags! {
134 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
135 struct DerivableTraits: u16 {
136 const DEBUG = 1 << 0;
137 const DEFAULT = 1 << 1;
138 const COPY = 1 << 2;
139 const CLONE = 1 << 3;
140 const HASH = 1 << 4;
141 const PARTIAL_ORD = 1 << 5;
142 const ORD = 1 << 6;
143 const PARTIAL_EQ = 1 << 7;
144 const EQ = 1 << 8;
145 }
146}
147
148fn derives_of_item(
149 item: &Item,
150 ctx: &BindgenContext,
151 packed: bool,
152) -> DerivableTraits {
153 let mut derivable_traits = DerivableTraits::empty();
154
155 if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
156 derivable_traits |= DerivableTraits::COPY;
157
158 derivable_traits |= DerivableTraits::CLONE;
165 } else if packed {
166 return derivable_traits;
169 }
170
171 if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() {
172 derivable_traits |= DerivableTraits::DEBUG;
173 }
174
175 if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
176 derivable_traits |= DerivableTraits::DEFAULT;
177 }
178
179 if item.can_derive_hash(ctx) {
180 derivable_traits |= DerivableTraits::HASH;
181 }
182
183 if item.can_derive_partialord(ctx) {
184 derivable_traits |= DerivableTraits::PARTIAL_ORD;
185 }
186
187 if item.can_derive_ord(ctx) {
188 derivable_traits |= DerivableTraits::ORD;
189 }
190
191 if item.can_derive_partialeq(ctx) {
192 derivable_traits |= DerivableTraits::PARTIAL_EQ;
193 }
194
195 if item.can_derive_eq(ctx) {
196 derivable_traits |= DerivableTraits::EQ;
197 }
198
199 derivable_traits
200}
201
202fn append_custom_derives<'a>(
205 derives: &mut Vec<&'a str>,
206 custom_derives: &'a [String],
207) {
208 for custom_derive in custom_derives.iter().map(|s| s.as_str()) {
209 if !derives.contains(&custom_derive) {
210 derives.push(custom_derive);
211 }
212 }
213}
214
215fn collect_field_attributes(
217 ctx: &BindgenContext,
218 annotations: &Annotations,
219 type_name: &str,
220 type_kind: DeriveTypeKind,
221 field_name: &str,
222 field_type_name: Option<&str>,
223) -> Vec<String> {
224 let mut all_field_attributes = Vec::new();
225
226 all_field_attributes.extend(annotations.attributes().iter().cloned());
228
229 all_field_attributes.extend(ctx.options().all_callbacks(|cb| {
231 cb.field_attributes(&FieldAttributeInfo {
232 type_name,
233 type_kind,
234 field_name,
235 field_type_name,
236 })
237 }));
238
239 for (type_pat, field_pat, attr) in &ctx.options().field_attr_patterns {
241 if type_pat.as_ref() == type_name && field_pat.as_ref() == field_name {
242 all_field_attributes.push(attr.to_string());
243 }
244 }
245
246 all_field_attributes
247}
248
249impl From<DerivableTraits> for Vec<&'static str> {
250 fn from(derivable_traits: DerivableTraits) -> Vec<&'static str> {
251 [
252 (DerivableTraits::DEBUG, "Debug"),
253 (DerivableTraits::DEFAULT, "Default"),
254 (DerivableTraits::COPY, "Copy"),
255 (DerivableTraits::CLONE, "Clone"),
256 (DerivableTraits::HASH, "Hash"),
257 (DerivableTraits::PARTIAL_ORD, "PartialOrd"),
258 (DerivableTraits::ORD, "Ord"),
259 (DerivableTraits::PARTIAL_EQ, "PartialEq"),
260 (DerivableTraits::EQ, "Eq"),
261 ]
262 .iter()
263 .filter_map(|&(flag, derive)| {
264 Some(derive).filter(|_| derivable_traits.contains(flag))
265 })
266 .collect()
267 }
268}
269
270struct WrapAsVariadic {
271 new_name: String,
272 idx_of_va_list_arg: usize,
273}
274
275struct CodegenResult<'a> {
276 items: Vec<proc_macro2::TokenStream>,
277 dynamic_items: DynamicItems,
278
279 codegen_id: &'a Cell<usize>,
282
283 saw_bindgen_union: bool,
285
286 saw_incomplete_array: bool,
288
289 saw_objc: bool,
291
292 saw_block: bool,
294
295 saw_bitfield_unit: bool,
297
298 items_seen: HashSet<ItemId>,
299 functions_seen: HashSet<String>,
316 vars_seen: HashSet<String>,
317
318 overload_counters: HashMap<String, u32>,
322
323 items_to_serialize: Vec<(ItemId, Option<WrapAsVariadic>)>,
326}
327
328impl<'a> CodegenResult<'a> {
329 fn new(codegen_id: &'a Cell<usize>) -> Self {
330 CodegenResult {
331 items: vec![],
332 dynamic_items: DynamicItems::new(),
333 saw_bindgen_union: false,
334 saw_incomplete_array: false,
335 saw_objc: false,
336 saw_block: false,
337 saw_bitfield_unit: false,
338 codegen_id,
339 items_seen: Default::default(),
340 functions_seen: Default::default(),
341 vars_seen: Default::default(),
342 overload_counters: Default::default(),
343 items_to_serialize: Default::default(),
344 }
345 }
346
347 fn dynamic_items(&mut self) -> &mut DynamicItems {
348 &mut self.dynamic_items
349 }
350
351 fn saw_bindgen_union(&mut self) {
352 self.saw_bindgen_union = true;
353 }
354
355 fn saw_incomplete_array(&mut self) {
356 self.saw_incomplete_array = true;
357 }
358
359 fn saw_objc(&mut self) {
360 self.saw_objc = true;
361 }
362
363 fn saw_block(&mut self) {
364 self.saw_block = true;
365 }
366
367 fn saw_bitfield_unit(&mut self) {
368 self.saw_bitfield_unit = true;
369 }
370
371 fn seen<Id: Into<ItemId>>(&self, item: Id) -> bool {
372 self.items_seen.contains(&item.into())
373 }
374
375 fn set_seen<Id: Into<ItemId>>(&mut self, item: Id) {
376 self.items_seen.insert(item.into());
377 }
378
379 fn seen_function(&self, name: &str) -> bool {
380 self.functions_seen.contains(name)
381 }
382
383 fn saw_function(&mut self, name: &str) {
384 self.functions_seen.insert(name.into());
385 }
386
387 fn overload_number(&mut self, name: &str) -> u32 {
391 let counter = self.overload_counters.entry(name.into()).or_insert(0);
392 let number = *counter;
393 *counter += 1;
394 number
395 }
396
397 fn seen_var(&self, name: &str) -> bool {
398 self.vars_seen.contains(name)
399 }
400
401 fn saw_var(&mut self, name: &str) {
402 self.vars_seen.insert(name.into());
403 }
404
405 fn inner<F>(&mut self, cb: F) -> Vec<proc_macro2::TokenStream>
406 where
407 F: FnOnce(&mut Self),
408 {
409 let mut new = Self::new(self.codegen_id);
410
411 cb(&mut new);
412
413 self.saw_incomplete_array |= new.saw_incomplete_array;
414 self.saw_objc |= new.saw_objc;
415 self.saw_block |= new.saw_block;
416 self.saw_bitfield_unit |= new.saw_bitfield_unit;
417 self.saw_bindgen_union |= new.saw_bindgen_union;
418
419 new.items
420 }
421}
422
423impl ops::Deref for CodegenResult<'_> {
424 type Target = Vec<proc_macro2::TokenStream>;
425
426 fn deref(&self) -> &Self::Target {
427 &self.items
428 }
429}
430
431impl ops::DerefMut for CodegenResult<'_> {
432 fn deref_mut(&mut self) -> &mut Self::Target {
433 &mut self.items
434 }
435}
436
437trait ToPtr {
440 fn to_ptr(self, is_const: bool) -> syn::Type;
441}
442
443impl ToPtr for syn::Type {
444 fn to_ptr(self, is_const: bool) -> syn::Type {
445 if is_const {
446 syn::parse_quote! { *const #self }
447 } else {
448 syn::parse_quote! { *mut #self }
449 }
450 }
451}
452
453trait WithImplicitTemplateParams {
456 fn with_implicit_template_params(
457 self,
458 ctx: &BindgenContext,
459 item: &Item,
460 ) -> Self;
461}
462
463impl WithImplicitTemplateParams for syn::Type {
464 fn with_implicit_template_params(
465 self,
466 ctx: &BindgenContext,
467 item: &Item,
468 ) -> Self {
469 let item = item.id().into_resolver().through_type_refs().resolve(ctx);
470
471 let params = match *item.expect_type().kind() {
472 TypeKind::UnresolvedTypeRef(..) => {
473 unreachable!("already resolved unresolved type refs")
474 }
475 TypeKind::ResolvedTypeRef(..) => {
476 unreachable!("we resolved item through type refs")
477 }
478 TypeKind::Void |
480 TypeKind::NullPtr |
481 TypeKind::Pointer(..) |
482 TypeKind::Reference(..) |
483 TypeKind::Int(..) |
484 TypeKind::Float(..) |
485 TypeKind::Complex(..) |
486 TypeKind::Array(..) |
487 TypeKind::TypeParam |
488 TypeKind::Opaque |
489 TypeKind::Function(..) |
490 TypeKind::Enum(..) |
491 TypeKind::ObjCId |
492 TypeKind::ObjCSel |
493 TypeKind::TemplateInstantiation(..) => None,
494 _ => {
495 let params = item.used_template_params(ctx);
496 if params.is_empty() {
497 None
498 } else {
499 Some(params.into_iter().map(|p| {
500 p.try_to_rust_ty(ctx, &()).expect(
501 "template params cannot fail to be a rust type",
502 )
503 }))
504 }
505 }
506 };
507
508 if let Some(params) = params {
509 syn::parse_quote! { #self<#(#params),*> }
510 } else {
511 self
512 }
513 }
514}
515
516trait CodeGenerator {
517 type Extra;
519
520 type Return;
522
523 fn codegen(
524 &self,
525 ctx: &BindgenContext,
526 result: &mut CodegenResult<'_>,
527 extra: &Self::Extra,
528 ) -> Self::Return;
529}
530
531impl Item {
532 fn process_before_codegen(
533 &self,
534 ctx: &BindgenContext,
535 result: &mut CodegenResult,
536 ) -> bool {
537 if !self.is_enabled_for_codegen(ctx) {
538 return false;
539 }
540
541 if self.is_blocklisted(ctx) || result.seen(self.id()) {
542 debug!(
543 "<Item as CodeGenerator>::process_before_codegen: Ignoring hidden or seen: \
544 self = {self:?}"
545 );
546 return false;
547 }
548
549 if !ctx.codegen_items().contains(&self.id()) {
550 warn!("Found non-allowlisted item in code generation: {self:?}");
554 }
555
556 result.set_seen(self.id());
557 true
558 }
559}
560
561impl CodeGenerator for Item {
562 type Extra = ();
563 type Return = ();
564
565 fn codegen(
566 &self,
567 ctx: &BindgenContext,
568 result: &mut CodegenResult<'_>,
569 _extra: &(),
570 ) {
571 debug!("<Item as CodeGenerator>::codegen: self = {self:?}");
572 if !self.process_before_codegen(ctx, result) {
573 return;
574 }
575
576 match *self.kind() {
577 ItemKind::Module(ref module) => {
578 module.codegen(ctx, result, self);
579 }
580 ItemKind::Function(ref fun) => {
581 fun.codegen(ctx, result, self);
582 }
583 ItemKind::Var(ref var) => {
584 var.codegen(ctx, result, self);
585 }
586 ItemKind::Type(ref ty) => {
587 ty.codegen(ctx, result, self);
588 }
589 }
590 }
591}
592
593impl CodeGenerator for Module {
594 type Extra = Item;
595 type Return = ();
596
597 fn codegen(
598 &self,
599 ctx: &BindgenContext,
600 result: &mut CodegenResult<'_>,
601 item: &Item,
602 ) {
603 debug!("<Module as CodeGenerator>::codegen: item = {item:?}");
604
605 let codegen_self = |result: &mut CodegenResult,
606 found_any: &mut bool| {
607 for child in self.children() {
608 if ctx.codegen_items().contains(child) {
609 *found_any = true;
610 ctx.resolve_item(*child).codegen(ctx, result, &());
611 }
612 }
613
614 if item.id() == ctx.root_module() {
615 if result.saw_block {
616 utils::prepend_block_header(ctx, &mut *result);
617 }
618 if result.saw_bindgen_union {
619 utils::prepend_union_types(ctx, &mut *result);
620 }
621 if result.saw_incomplete_array {
622 utils::prepend_incomplete_array_types(ctx, &mut *result);
623 }
624 if ctx.need_bindgen_float16_type() {
625 utils::prepend_float16_type(&mut *result);
626 }
627 if ctx.need_bindgen_complex_type() {
628 utils::prepend_complex_type(&mut *result);
629 }
630 utils::prepend_opaque_array_types(ctx, &mut *result);
631 if result.saw_objc {
632 utils::prepend_objc_header(ctx, &mut *result);
633 }
634 if result.saw_bitfield_unit {
635 utils::prepend_bitfield_unit_type(ctx, &mut *result);
636 }
637 }
638 };
639
640 if !ctx.options().enable_cxx_namespaces ||
641 (self.is_inline() &&
642 !ctx.options().conservative_inline_namespaces)
643 {
644 codegen_self(result, &mut false);
645 return;
646 }
647
648 let mut found_any = false;
649 let inner_items = result.inner(|result| {
650 result.push(root_import(ctx, item));
651
652 let path = item
653 .namespace_aware_canonical_path(ctx)
654 .join("::")
655 .into_boxed_str();
656 if let Some(raw_lines) = ctx.options().module_lines.get(&path) {
657 for raw_line in raw_lines {
658 found_any = true;
659 result.push(
660 proc_macro2::TokenStream::from_str(raw_line).unwrap(),
661 );
662 }
663 }
664
665 codegen_self(result, &mut found_any);
666 });
667
668 if !found_any {
670 return;
671 }
672
673 let name = item.canonical_name(ctx);
674 let ident = ctx.rust_ident(name);
675 result.push(if item.id() == ctx.root_module() {
676 quote! {
677 #[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
678 pub mod #ident {
679 #( #inner_items )*
680 }
681 }
682 } else {
683 quote! {
684 pub mod #ident {
685 #( #inner_items )*
686 }
687 }
688 });
689 }
690}
691
692impl CodeGenerator for Var {
693 type Extra = Item;
694 type Return = ();
695
696 fn codegen(
697 &self,
698 ctx: &BindgenContext,
699 result: &mut CodegenResult<'_>,
700 item: &Item,
701 ) {
702 use crate::ir::var::VarType;
703 debug!("<Var as CodeGenerator>::codegen: item = {item:?}");
704 debug_assert!(item.is_enabled_for_codegen(ctx));
705
706 let canonical_name = item.canonical_name(ctx);
707
708 if result.seen_var(&canonical_name) {
709 return;
710 }
711 result.saw_var(&canonical_name);
712
713 let canonical_ident = ctx.rust_ident(&canonical_name);
714
715 if !item.all_template_params(ctx).is_empty() {
719 return;
720 }
721
722 let mut attrs = vec![];
723 if let Some(comment) = item.comment(ctx) {
724 attrs.push(attributes::doc(&comment));
725 }
726
727 let var_ty = self.ty();
728 let ty = var_ty.to_rust_ty_or_opaque(ctx, &());
729
730 if let Some(val) = self.val() {
731 utils::call_discovered_item_callback(ctx, item, || {
732 DiscoveredItem::Constant {
733 final_name: canonical_name.clone(),
734 }
735 });
736
737 let const_expr = match *val {
738 VarType::Bool(val) => Some(val.to_token_stream()),
739 VarType::Int(val) => {
740 let int_kind = var_ty
741 .into_resolver()
742 .through_type_aliases()
743 .through_type_refs()
744 .resolve(ctx)
745 .expect_type()
746 .as_integer()
747 .unwrap();
748 let val = if int_kind.is_signed() {
749 helpers::ast_ty::int_expr(val)
750 } else {
751 helpers::ast_ty::uint_expr(val as _)
752 };
753 Some(val)
754 }
755 VarType::String(ref bytes) => {
756 let prefix = ctx.trait_prefix();
757
758 let options = ctx.options();
759 let rust_features = options.rust_features;
760
761 let mut cstr_bytes = bytes.clone();
762 cstr_bytes.push(0);
763 let len = proc_macro2::Literal::usize_unsuffixed(
764 cstr_bytes.len(),
765 );
766 let cstr =
767 if options.generate_cstr && rust_features.const_cstr {
768 CStr::from_bytes_with_nul(&cstr_bytes).ok()
769 } else {
770 None
771 };
772 if let Some(cstr) = cstr {
773 let cstr_ty = quote! { ::#prefix::ffi::CStr };
774 if rust_features.literal_cstr {
775 let cstr = proc_macro2::Literal::c_string(cstr);
776 result.push(quote! {
777 #(#attrs)*
778 pub const #canonical_ident: &#cstr_ty = #cstr;
779 });
780 } else {
781 let bytes =
782 proc_macro2::Literal::byte_string(&cstr_bytes);
783 result.push(quote! {
784 #(#attrs)*
785 #[allow(unsafe_code)]
786 pub const #canonical_ident: &#cstr_ty = unsafe {
787 #cstr_ty::from_bytes_with_nul_unchecked(#bytes)
788 };
789 });
790 }
791 } else {
792 let array_ty = quote! { [u8; #len] };
795 let bytes =
796 proc_macro2::Literal::byte_string(&cstr_bytes);
797 let lifetime =
798 if true { None } else { Some(quote! { 'static }) }
799 .into_iter();
800
801 result.push(quote! {
802 #(#attrs)*
803 pub const #canonical_ident: &#(#lifetime )*#array_ty = #bytes ;
804 });
805 }
806 None
807 }
808 VarType::Float(f) => helpers::ast_ty::float_expr(f).ok(),
809 VarType::Char(c) => Some(c.to_token_stream()),
810 };
811
812 if let Some(mut val) = const_expr {
813 let var_ty_item = ctx.resolve_item(var_ty);
814 if matches!(
815 var_ty_item.alias_style(ctx),
816 AliasVariation::NewType | AliasVariation::NewTypeDeref
817 ) {
818 val = quote! { #ty(#val) };
819 }
820 result.push(quote! {
821 #(#attrs)*
822 pub const #canonical_ident : #ty = #val ;
823 });
824 }
825 } else {
826 utils::call_discovered_item_callback(ctx, item, || {
827 DiscoveredItem::Variable {
828 final_name: canonical_name.clone(),
829 }
830 });
831
832 let symbol: &str = self.link_name().unwrap_or_else(|| {
833 let link_name =
834 self.mangled_name().unwrap_or_else(|| self.name());
835 if utils::names_will_be_identical_after_mangling(
836 &canonical_name,
837 link_name,
838 None,
839 ) {
840 canonical_name.as_str()
841 } else {
842 attrs.push(attributes::link_name::<false>(link_name));
843 link_name
844 }
845 });
846
847 let maybe_mut = if self.is_const() {
848 quote! {}
849 } else {
850 quote! { mut }
851 };
852
853 let safety = ctx
854 .options()
855 .rust_features
856 .unsafe_extern_blocks
857 .then(|| quote!(unsafe));
858
859 let tokens = quote!(
860 #safety extern "C" {
861 #(#attrs)*
862 pub static #maybe_mut #canonical_ident: #ty;
863 }
864 );
865
866 if ctx.options().dynamic_library_name.is_some() {
867 result.dynamic_items().push_var(
868 &canonical_ident,
869 symbol,
870 &self
871 .ty()
872 .to_rust_ty_or_opaque(ctx, &())
873 .into_token_stream(),
874 ctx.options().dynamic_link_require_all,
875 ctx.options().wrap_unsafe_ops,
876 );
877 } else {
878 result.push(tokens);
879 }
880 }
881 }
882}
883
884impl CodeGenerator for Type {
885 type Extra = Item;
886 type Return = ();
887
888 fn codegen(
889 &self,
890 ctx: &BindgenContext,
891 result: &mut CodegenResult<'_>,
892 item: &Item,
893 ) {
894 debug!("<Type as CodeGenerator>::codegen: item = {item:?}");
895 debug_assert!(item.is_enabled_for_codegen(ctx));
896
897 match *self.kind() {
898 TypeKind::Void |
899 TypeKind::NullPtr |
900 TypeKind::Int(..) |
901 TypeKind::Float(..) |
902 TypeKind::Complex(..) |
903 TypeKind::Array(..) |
904 TypeKind::Vector(..) |
905 TypeKind::Pointer(..) |
906 TypeKind::Reference(..) |
907 TypeKind::Function(..) |
908 TypeKind::ResolvedTypeRef(..) |
909 TypeKind::Opaque |
910 TypeKind::TypeParam => {
911 }
916 TypeKind::TemplateInstantiation(ref inst) => {
917 inst.codegen(ctx, result, item);
918 }
919 TypeKind::BlockPointer(inner) => {
920 if !ctx.options().generate_block {
921 return;
922 }
923
924 let inner_item =
925 inner.into_resolver().through_type_refs().resolve(ctx);
926 let name = item.canonical_name(ctx);
927
928 let inner_rust_type = {
929 if let TypeKind::Function(fnsig) =
930 inner_item.kind().expect_type().kind()
931 {
932 utils::fnsig_block(ctx, fnsig)
933 } else {
934 panic!("invalid block typedef: {inner_item:?}")
935 }
936 };
937
938 let rust_name = ctx.rust_ident(name);
939
940 let mut tokens = if let Some(comment) = item.comment(ctx) {
941 attributes::doc(&comment)
942 } else {
943 quote! {}
944 };
945
946 tokens.append_all(quote! {
947 pub type #rust_name = #inner_rust_type ;
948 });
949
950 result.push(tokens);
951 result.saw_block();
952 }
953 TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
954 TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => {
955 let inner_item =
956 inner.into_resolver().through_type_refs().resolve(ctx);
957 let name = item.canonical_name(ctx);
958 let path = item.canonical_path(ctx);
959
960 {
961 let through_type_aliases = inner
962 .into_resolver()
963 .through_type_refs()
964 .through_type_aliases()
965 .resolve(ctx);
966
967 if through_type_aliases.canonical_path(ctx) == path {
973 return;
974 }
975 }
976
977 let spelling = self.name().expect("Unnamed alias?");
982 if utils::type_from_named(ctx, spelling).is_some() {
983 if let "size_t" | "ssize_t" = spelling {
984 let layout = inner_item
985 .kind()
986 .expect_type()
987 .layout(ctx)
988 .expect("No layout?");
989 assert_eq!(
990 layout.size,
991 ctx.target_pointer_size(),
992 "Target platform requires `--no-size_t-is-usize`. The size of `{spelling}` ({}) does not match the target pointer size ({})",
993 layout.size,
994 ctx.target_pointer_size(),
995 );
996 }
997 return;
998 }
999
1000 let mut outer_params = item.used_template_params(ctx);
1001
1002 let is_opaque = item.is_opaque(ctx, &());
1003 let inner_rust_type = if is_opaque {
1004 outer_params = vec![];
1005 self.to_opaque(ctx, item)
1006 } else {
1007 inner_item
1011 .try_to_rust_ty_or_opaque(ctx, &())
1012 .unwrap_or_else(|_| self.to_opaque(ctx, item))
1013 .with_implicit_template_params(ctx, inner_item)
1014 };
1015
1016 {
1017 let inner_canon_type =
1028 inner_item.expect_type().canonical_type(ctx);
1029 if inner_canon_type.is_invalid_type_param() {
1030 warn!(
1031 "Item contained invalid named type, skipping: \
1032 {item:?}, {inner_item:?}"
1033 );
1034 return;
1035 }
1036 }
1037
1038 let rust_name = ctx.rust_ident(&name);
1039
1040 utils::call_discovered_item_callback(ctx, item, || {
1041 DiscoveredItem::Alias {
1042 alias_name: rust_name.to_string(),
1043 alias_for: DiscoveredItemId::new(
1044 inner_item.id().as_usize(),
1045 ),
1046 }
1047 });
1048
1049 let mut tokens = if let Some(comment) = item.comment(ctx) {
1050 attributes::doc(&comment)
1051 } else {
1052 quote! {}
1053 };
1054
1055 let alias_style = item.alias_style(ctx);
1056
1057 if matches!(inner_rust_type, syn::Type::Path(_)) &&
1060 outer_params.is_empty() &&
1061 !is_opaque &&
1062 alias_style == AliasVariation::TypeAlias &&
1063 inner_item.expect_type().canonical_type(ctx).is_enum()
1064 {
1065 tokens.append_all(quote! {
1066 pub use
1067 });
1068 let path = top_level_path(ctx, item);
1069 tokens.append_separated(path, quote!(::));
1070 tokens.append_all(quote! {
1071 :: #inner_rust_type as #rust_name ;
1072 });
1073 result.push(tokens);
1074 return;
1075 }
1076
1077 tokens.append_all(match alias_style {
1078 AliasVariation::TypeAlias => quote! {
1079 pub type #rust_name
1080 },
1081 AliasVariation::NewType | AliasVariation::NewTypeDeref => {
1082 let mut attributes =
1083 vec![attributes::repr("transparent")];
1084 let packed = false; let derivable_traits =
1086 derives_of_item(item, ctx, packed);
1087 let mut derives: Vec<_> = derivable_traits.into();
1088 let custom_derives =
1091 ctx.options().all_callbacks(|cb| {
1092 cb.add_derives(&DeriveInfo {
1093 name: &name,
1094 kind: DeriveTypeKind::Struct,
1095 })
1096 });
1097 append_custom_derives(&mut derives, &custom_derives);
1099 attributes.push(attributes::derives(&derives));
1100
1101 let custom_attributes =
1102 ctx.options().all_callbacks(|cb| {
1103 cb.add_attributes(&AttributeInfo {
1104 name: &name,
1105 kind: DeriveTypeKind::Struct,
1106 })
1107 });
1108 attributes.extend(
1109 custom_attributes
1110 .iter()
1111 .map(|s| s.parse().unwrap()),
1112 );
1113
1114 quote! {
1115 #( #attributes )*
1116 pub struct #rust_name
1117 }
1118 }
1119 });
1120
1121 let params: Vec<_> = outer_params
1122 .into_iter()
1123 .filter_map(|p| p.as_template_param(ctx, &()))
1124 .collect();
1125 if params
1126 .iter()
1127 .any(|p| ctx.resolve_type(*p).is_invalid_type_param())
1128 {
1129 warn!(
1130 "Item contained invalid template \
1131 parameter: {item:?}"
1132 );
1133 return;
1134 }
1135 let params: Vec<_> = params
1136 .iter()
1137 .map(|p| {
1138 p.try_to_rust_ty(ctx, &()).expect(
1139 "type parameters can always convert to rust ty OK",
1140 )
1141 })
1142 .collect();
1143
1144 if !params.is_empty() {
1145 tokens.append_all(quote! {
1146 < #( #params ),* >
1147 });
1148 }
1149
1150 tokens.append_all(match alias_style {
1151 AliasVariation::TypeAlias => quote! {
1152 = #inner_rust_type ;
1153 },
1154 AliasVariation::NewType | AliasVariation::NewTypeDeref => {
1155 let visibility = ctx
1156 .options()
1157 .last_callback(|cb| {
1158 cb.field_visibility(FieldInfo {
1159 type_name: &item.canonical_name(ctx),
1160 field_name: "0",
1161 field_type_name: inner_item
1162 .expect_type()
1163 .name(),
1164 })
1165 })
1166 .unwrap_or(ctx.options().default_visibility);
1167 let access_spec = access_specifier(visibility);
1168
1169 let type_name = item.canonical_name(ctx);
1171 let all_field_attributes = collect_field_attributes(
1172 ctx,
1173 item.annotations(),
1174 &type_name,
1175 DeriveTypeKind::Struct,
1176 "0",
1177 inner_item.expect_type().name(),
1178 );
1179
1180 let mut field_tokens = quote! {};
1182 for attr in &all_field_attributes {
1183 let attr_tokens: proc_macro2::TokenStream =
1184 attr.parse().expect("Invalid field attribute");
1185 field_tokens.append_all(quote! {
1186 #[#attr_tokens]
1187 });
1188 }
1189 field_tokens.append_all(quote! {
1190 #access_spec #inner_rust_type
1191 });
1192
1193 quote! {
1194 (#field_tokens) ;
1195 }
1196 }
1197 });
1198
1199 if alias_style == AliasVariation::NewTypeDeref {
1200 let prefix = ctx.trait_prefix();
1201 tokens.append_all(quote! {
1202 impl ::#prefix::ops::Deref for #rust_name {
1203 type Target = #inner_rust_type;
1204 #[inline]
1205 fn deref(&self) -> &Self::Target {
1206 &self.0
1207 }
1208 }
1209 impl ::#prefix::ops::DerefMut for #rust_name {
1210 #[inline]
1211 fn deref_mut(&mut self) -> &mut Self::Target {
1212 &mut self.0
1213 }
1214 }
1215 });
1216 }
1217
1218 result.push(tokens);
1219 }
1220 TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
1221 TypeKind::ObjCId | TypeKind::ObjCSel => {
1222 result.saw_objc();
1223 }
1224 TypeKind::ObjCInterface(ref interface) => {
1225 interface.codegen(ctx, result, item);
1226 }
1227 ref u @ TypeKind::UnresolvedTypeRef(..) => {
1228 unreachable!("Should have been resolved after parsing {u:?}!")
1229 }
1230 }
1231 }
1232}
1233
1234struct Vtable<'a> {
1235 item_id: ItemId,
1236 #[allow(dead_code)]
1238 comp_info: &'a CompInfo,
1239}
1240
1241impl<'a> Vtable<'a> {
1242 fn new(item_id: ItemId, comp_info: &'a CompInfo) -> Self {
1243 Vtable { item_id, comp_info }
1244 }
1245}
1246
1247impl CodeGenerator for Vtable<'_> {
1248 type Extra = Item;
1249 type Return = ();
1250
1251 fn codegen(
1252 &self,
1253 ctx: &BindgenContext,
1254 result: &mut CodegenResult<'_>,
1255 item: &Item,
1256 ) {
1257 assert_eq!(item.id(), self.item_id);
1258 debug_assert!(item.is_enabled_for_codegen(ctx));
1259 let name = ctx.rust_ident(self.canonical_name(ctx));
1260
1261 if ctx.options().vtable_generation &&
1265 self.comp_info.base_members().is_empty() &&
1266 self.comp_info.destructor().is_none()
1267 {
1268 let class_ident = ctx.rust_ident(self.item_id.canonical_name(ctx));
1269
1270 let methods = self
1271 .comp_info
1272 .methods()
1273 .iter()
1274 .filter_map(|m| {
1275 if !m.is_virtual() {
1276 return None;
1277 }
1278
1279 let function_item = ctx.resolve_item(m.signature());
1280 let function = function_item.expect_function();
1281 let signature_item = ctx.resolve_item(function.signature());
1282 let TypeKind::Function(ref signature) = signature_item.expect_type().kind() else { panic!("Function signature type mismatch") };
1283
1284 let function_name = function_item.canonical_name(ctx);
1286
1287 let function_name = ctx.rust_ident(function_name);
1289 let mut args = utils::fnsig_arguments(ctx, signature);
1290 let ret = utils::fnsig_return_ty(ctx, signature);
1291
1292 args[0] = if m.is_const() {
1293 quote! { this: *const #class_ident }
1294 } else {
1295 quote! { this: *mut #class_ident }
1296 };
1297
1298 Some(quote! {
1299 pub #function_name : unsafe extern "C" fn( #( #args ),* ) #ret
1300 })
1301 })
1302 .collect::<Vec<_>>();
1303
1304 result.push(quote! {
1305 #[repr(C)]
1306 pub struct #name {
1307 #( #methods ),*
1308 }
1309 });
1310 } else {
1311 let void = helpers::ast_ty::c_void(ctx);
1313
1314 result.push(quote! {
1315 #[repr(C)]
1316 pub struct #name ( #void );
1317 });
1318 }
1319 }
1320}
1321
1322impl ItemCanonicalName for Vtable<'_> {
1323 fn canonical_name(&self, ctx: &BindgenContext) -> String {
1324 format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx))
1325 }
1326}
1327
1328impl TryToRustTy for Vtable<'_> {
1329 type Extra = ();
1330
1331 fn try_to_rust_ty(
1332 &self,
1333 ctx: &BindgenContext,
1334 _: &(),
1335 ) -> error::Result<syn::Type> {
1336 let name = ctx.rust_ident(self.canonical_name(ctx));
1337 Ok(syn::parse_quote! { #name })
1338 }
1339}
1340
1341impl CodeGenerator for TemplateInstantiation {
1342 type Extra = Item;
1343 type Return = ();
1344
1345 fn codegen(
1346 &self,
1347 ctx: &BindgenContext,
1348 result: &mut CodegenResult<'_>,
1349 item: &Item,
1350 ) {
1351 debug_assert!(item.is_enabled_for_codegen(ctx));
1352
1353 if !ctx.options().layout_tests || self.is_opaque(ctx, item) {
1360 return;
1361 }
1362
1363 let compile_time = ctx.options().rust_features().offset_of;
1365
1366 if ctx.uses_any_template_parameters(item.id()) {
1370 return;
1371 }
1372
1373 let layout = item.kind().expect_type().layout(ctx);
1374
1375 if let Some(layout) = layout {
1376 let size = layout.size;
1377 let align = layout.align;
1378
1379 let name = item.full_disambiguated_name(ctx);
1380 let fn_name = if compile_time {
1381 None
1382 } else {
1383 let mut fn_name =
1384 format!("__bindgen_test_layout_{name}_instantiation");
1385 let times_seen = result.overload_number(&fn_name);
1386 if times_seen > 0 {
1387 write!(&mut fn_name, "_{times_seen}").unwrap();
1388 }
1389 Some(ctx.rust_ident_raw(fn_name))
1390 };
1391
1392 let prefix = ctx.trait_prefix();
1393 let ident = item.to_rust_ty_or_opaque(ctx, &());
1394 let size_of_expr = quote! {
1395 ::#prefix::mem::size_of::<#ident>()
1396 };
1397 let align_of_expr = quote! {
1398 ::#prefix::mem::align_of::<#ident>()
1399 };
1400 let size_of_err =
1401 format!("Size of template specialization: {name}");
1402 let align_of_err =
1403 format!("Align of template specialization: {name}");
1404
1405 if compile_time {
1406 result.push(quote! {
1412 #[allow(clippy::unnecessary_operation, clippy::identity_op)]
1413 const _: () = {
1414 [#size_of_err][#size_of_expr - #size];
1415 [#align_of_err][#align_of_expr - #align];
1416 };
1417 });
1418 } else {
1419 result.push(quote! {
1420 #[test]
1421 fn #fn_name() {
1422 assert_eq!(#size_of_expr, #size, #size_of_err);
1423 assert_eq!(#align_of_expr, #align, #align_of_err);
1424 }
1425 });
1426 }
1427 }
1428 }
1429}
1430
1431trait FieldCodegen<'a> {
1433 type Extra;
1434
1435 #[allow(clippy::too_many_arguments)]
1436 fn codegen<F, M>(
1437 &self,
1438 ctx: &BindgenContext,
1439 visibility_kind: FieldVisibilityKind,
1440 accessor_kind: FieldAccessorKind,
1441 parent: &CompInfo,
1442 parent_item: &Item,
1443 last_field: bool,
1444 result: &mut CodegenResult,
1445 struct_layout: &mut StructLayoutTracker,
1446 fields: &mut F,
1447 methods: &mut M,
1448 extra: Self::Extra,
1449 ) where
1450 F: Extend<proc_macro2::TokenStream>,
1451 M: Extend<proc_macro2::TokenStream>;
1452}
1453
1454impl FieldCodegen<'_> for Field {
1455 type Extra = ();
1456
1457 fn codegen<F, M>(
1458 &self,
1459 ctx: &BindgenContext,
1460 visibility_kind: FieldVisibilityKind,
1461 accessor_kind: FieldAccessorKind,
1462 parent: &CompInfo,
1463 parent_item: &Item,
1464 last_field: bool,
1465 result: &mut CodegenResult,
1466 struct_layout: &mut StructLayoutTracker,
1467 fields: &mut F,
1468 methods: &mut M,
1469 _: (),
1470 ) where
1471 F: Extend<proc_macro2::TokenStream>,
1472 M: Extend<proc_macro2::TokenStream>,
1473 {
1474 match *self {
1475 Field::DataMember(ref data) => {
1476 data.codegen(
1477 ctx,
1478 visibility_kind,
1479 accessor_kind,
1480 parent,
1481 parent_item,
1482 last_field,
1483 result,
1484 struct_layout,
1485 fields,
1486 methods,
1487 (),
1488 );
1489 }
1490 Field::Bitfields(ref unit) => {
1491 unit.codegen(
1492 ctx,
1493 visibility_kind,
1494 accessor_kind,
1495 parent,
1496 parent_item,
1497 last_field,
1498 result,
1499 struct_layout,
1500 fields,
1501 methods,
1502 (),
1503 );
1504 }
1505 }
1506 }
1507}
1508
1509fn wrap_union_field_if_needed(
1510 ctx: &BindgenContext,
1511 struct_layout: &StructLayoutTracker,
1512 ty: syn::Type,
1513 result: &mut CodegenResult,
1514) -> syn::Type {
1515 if struct_layout.is_rust_union() {
1516 if struct_layout.can_copy_union_fields() {
1517 ty
1518 } else {
1519 let prefix = ctx.trait_prefix();
1520 syn::parse_quote! { ::#prefix::mem::ManuallyDrop<#ty> }
1521 }
1522 } else {
1523 result.saw_bindgen_union();
1524 if ctx.options().enable_cxx_namespaces {
1525 syn::parse_quote! { root::__BindgenUnionField<#ty> }
1526 } else {
1527 syn::parse_quote! { __BindgenUnionField<#ty> }
1528 }
1529 }
1530}
1531
1532impl FieldCodegen<'_> for FieldData {
1533 type Extra = ();
1534
1535 fn codegen<F, M>(
1536 &self,
1537 ctx: &BindgenContext,
1538 parent_visibility_kind: FieldVisibilityKind,
1539 accessor_kind: FieldAccessorKind,
1540 parent: &CompInfo,
1541 parent_item: &Item,
1542 last_field: bool,
1543 result: &mut CodegenResult,
1544 struct_layout: &mut StructLayoutTracker,
1545 fields: &mut F,
1546 methods: &mut M,
1547 _: (),
1548 ) where
1549 F: Extend<proc_macro2::TokenStream>,
1550 M: Extend<proc_macro2::TokenStream>,
1551 {
1552 assert!(self.bitfield_width().is_none());
1555
1556 let field_item =
1557 self.ty().into_resolver().through_type_refs().resolve(ctx);
1558 let field_ty = field_item.expect_type();
1559 let ty = self
1560 .ty()
1561 .to_rust_ty_or_opaque(ctx, &())
1562 .with_implicit_template_params(ctx, field_item);
1563
1564 let ty = if parent.is_union() {
1566 wrap_union_field_if_needed(ctx, struct_layout, ty, result)
1567 } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
1568 if ctx.options().flexarray_dst && last_field {
1570 let layout = parent_item.expect_type().layout(ctx);
1572 let is_packed = parent.is_packed(ctx, layout.as_ref());
1573 struct_layout.saw_flexible_array();
1574
1575 if is_packed {
1579 let prefix = ctx.trait_prefix();
1580 syn::parse_quote! { ::#prefix::mem::ManuallyDrop<FAM> }
1581 } else {
1582 syn::parse_quote! { FAM }
1583 }
1584 } else {
1585 result.saw_incomplete_array();
1586
1587 let inner = item.to_rust_ty_or_opaque(ctx, &());
1588
1589 if ctx.options().enable_cxx_namespaces {
1590 syn::parse_quote! { root::__IncompleteArrayField<#inner> }
1591 } else {
1592 syn::parse_quote! { __IncompleteArrayField<#inner> }
1593 }
1594 }
1595 } else if let TypeKind::Comp(ref comp) = field_ty.kind() {
1596 if ctx.options().flexarray_dst &&
1599 last_field &&
1600 comp.flex_array_member(ctx).is_some()
1601 {
1602 let layout = parent_item.expect_type().layout(ctx);
1603 let is_packed = parent.is_packed(ctx, layout.as_ref());
1604 struct_layout.saw_flexible_array();
1605
1606 if is_packed {
1609 let prefix = ctx.trait_prefix();
1610 syn::parse_quote! { ::#prefix::mem::ManuallyDrop<#ty<FAM>> }
1611 } else {
1612 syn::parse_quote! { #ty<FAM> }
1613 }
1614 } else {
1615 ty
1616 }
1617 } else {
1618 ty
1619 };
1620
1621 let mut field = quote! {};
1622 if ctx.options().generate_comments {
1623 if let Some(raw_comment) = self.comment() {
1624 let comment = ctx.options().process_comment(raw_comment);
1625 field = attributes::doc(&comment);
1626 }
1627 }
1628
1629 let field_name = self
1630 .name()
1631 .map(|name| ctx.rust_mangle(name).into_owned())
1632 .expect("Each field should have a name in codegen!");
1633 let field_name = field_name.as_str();
1634 let field_ident = ctx.rust_ident_raw(field_name);
1635
1636 if let Some(padding_field) =
1637 struct_layout.saw_field(field_name, field_ty, self.offset())
1638 {
1639 fields.extend(Some(padding_field));
1640 }
1641
1642 let visibility = compute_visibility(
1643 ctx,
1644 self.is_public(),
1645 ctx.options().last_callback(|cb| {
1646 cb.field_visibility(FieldInfo {
1647 type_name: &parent_item.canonical_name(ctx),
1648 field_name,
1649 field_type_name: field_ty.name(),
1650 })
1651 }),
1652 self.annotations(),
1653 parent_visibility_kind,
1654 );
1655 let accessor_kind =
1656 self.annotations().accessor_kind().unwrap_or(accessor_kind);
1657
1658 let type_name = parent_item.canonical_name(ctx);
1660 let type_kind = if parent.is_union() {
1661 DeriveTypeKind::Union
1662 } else {
1663 DeriveTypeKind::Struct
1664 };
1665 let all_field_attributes = collect_field_attributes(
1666 ctx,
1667 self.annotations(),
1668 &type_name,
1669 type_kind,
1670 field_name,
1671 field_ty.name(),
1672 );
1673
1674 for attr in &all_field_attributes {
1676 let attr_tokens: proc_macro2::TokenStream =
1677 attr.parse().expect("Invalid field attribute");
1678 field.append_all(quote! {
1679 #[#attr_tokens]
1680 });
1681 }
1682
1683 match visibility {
1684 FieldVisibilityKind::Private => {
1685 field.append_all(quote! {
1686 #field_ident : #ty ,
1687 });
1688 }
1689 FieldVisibilityKind::PublicCrate => {
1690 field.append_all(quote! {
1691 pub(crate) #field_ident : #ty ,
1692 });
1693 }
1694 FieldVisibilityKind::Public => {
1695 field.append_all(quote! {
1696 pub #field_ident : #ty ,
1697 });
1698 }
1699 }
1700
1701 fields.extend(Some(field));
1702
1703 if accessor_kind == FieldAccessorKind::None {
1705 return;
1706 }
1707
1708 let getter_name = ctx.rust_ident_raw(format!("get_{field_name}"));
1709 let mutable_getter_name =
1710 ctx.rust_ident_raw(format!("get_{field_name}_mut"));
1711
1712 methods.extend(Some(match accessor_kind {
1713 FieldAccessorKind::None => unreachable!(),
1714 FieldAccessorKind::Regular => {
1715 quote! {
1716 #[inline]
1717 pub fn #getter_name(&self) -> & #ty {
1718 &self.#field_ident
1719 }
1720
1721 #[inline]
1722 pub fn #mutable_getter_name(&mut self) -> &mut #ty {
1723 &mut self.#field_ident
1724 }
1725 }
1726 }
1727 FieldAccessorKind::Unsafe => {
1728 quote! {
1729 #[inline]
1730 pub unsafe fn #getter_name(&self) -> & #ty {
1731 &self.#field_ident
1732 }
1733
1734 #[inline]
1735 pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty {
1736 &mut self.#field_ident
1737 }
1738 }
1739 }
1740 FieldAccessorKind::Immutable => {
1741 quote! {
1742 #[inline]
1743 pub fn #getter_name(&self) -> & #ty {
1744 &self.#field_ident
1745 }
1746 }
1747 }
1748 }));
1749 }
1750}
1751
1752impl BitfieldUnit {
1753 fn ctor_name(&self) -> proc_macro2::TokenStream {
1755 let ctor_name = Ident::new(
1756 &format!("new_bitfield_{}", self.nth()),
1757 Span::call_site(),
1758 );
1759 quote! {
1760 #ctor_name
1761 }
1762 }
1763}
1764
1765impl Bitfield {
1766 fn extend_ctor_impl(
1770 &self,
1771 ctx: &BindgenContext,
1772 param_name: &proc_macro2::TokenStream,
1773 mut ctor_impl: proc_macro2::TokenStream,
1774 ) -> proc_macro2::TokenStream {
1775 let bitfield_ty = ctx.resolve_type(self.ty());
1776 let bitfield_ty_layout = bitfield_ty
1777 .layout(ctx)
1778 .expect("Bitfield without layout? Gah!");
1779 let bitfield_int_ty = helpers::integer_type(bitfield_ty_layout).expect(
1780 "Should already have verified that the bitfield is \
1781 representable as an int",
1782 );
1783
1784 let offset = self.offset_into_unit();
1785 let width = self.width() as u8;
1786 let prefix = ctx.trait_prefix();
1787
1788 ctor_impl.append_all(quote! {
1789 __bindgen_bitfield_unit.set_const::<#offset, #width>(
1790 {
1791 let #param_name: #bitfield_int_ty = unsafe {
1792 ::#prefix::mem::transmute(#param_name)
1793 };
1794 #param_name as u64
1795 }
1796 );
1797 });
1798
1799 ctor_impl
1800 }
1801}
1802
1803fn access_specifier(
1804 visibility: FieldVisibilityKind,
1805) -> proc_macro2::TokenStream {
1806 match visibility {
1807 FieldVisibilityKind::Private => quote! {},
1808 FieldVisibilityKind::PublicCrate => quote! { pub(crate) },
1809 FieldVisibilityKind::Public => quote! { pub },
1810 }
1811}
1812
1813fn compute_visibility(
1824 ctx: &BindgenContext,
1825 is_declared_public: bool,
1826 callback_override: Option<FieldVisibilityKind>,
1827 annotations: &Annotations,
1828 default_kind: FieldVisibilityKind,
1829) -> FieldVisibilityKind {
1830 callback_override
1831 .or_else(|| annotations.visibility_kind())
1832 .unwrap_or_else(|| {
1833 match (is_declared_public, ctx.options().respect_cxx_access_specs) {
1834 (true, true) => {
1835 FieldVisibilityKind::Public
1837 }
1838 (false, true) => {
1839 FieldVisibilityKind::Private
1841 }
1842 (_, false) => {
1843 default_kind
1845 }
1846 }
1847 })
1848}
1849
1850impl FieldCodegen<'_> for BitfieldUnit {
1851 type Extra = ();
1852
1853 fn codegen<F, M>(
1854 &self,
1855 ctx: &BindgenContext,
1856 visibility_kind: FieldVisibilityKind,
1857 accessor_kind: FieldAccessorKind,
1858 parent: &CompInfo,
1859 parent_item: &Item,
1860 last_field: bool,
1861 result: &mut CodegenResult,
1862 struct_layout: &mut StructLayoutTracker,
1863 fields: &mut F,
1864 methods: &mut M,
1865 _: (),
1866 ) where
1867 F: Extend<proc_macro2::TokenStream>,
1868 M: Extend<proc_macro2::TokenStream>,
1869 {
1870 use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
1871
1872 result.saw_bitfield_unit();
1873
1874 let layout = self.layout();
1875 let unit_field_ty = helpers::bitfield_unit(ctx, layout);
1876 let field_ty = {
1877 let unit_field_ty = unit_field_ty.clone();
1878 if parent.is_union() {
1879 wrap_union_field_if_needed(
1880 ctx,
1881 struct_layout,
1882 unit_field_ty,
1883 result,
1884 )
1885 } else {
1886 unit_field_ty
1887 }
1888 };
1889
1890 let unit_field_name = format!("_bitfield_{}", self.nth());
1891 let unit_field_ident = ctx.rust_ident(&unit_field_name);
1892
1893 let ctor_name = self.ctor_name();
1894 let mut ctor_params = vec![];
1895 let mut ctor_impl = quote! {};
1896
1897 let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;
1903
1904 let mut unit_visibility = visibility_kind;
1905 let bfields = self.bitfields();
1906 for (idx, bf) in bfields.iter().enumerate() {
1907 if bf.name().is_none() {
1909 continue;
1910 }
1911
1912 let mut bitfield_representable_as_int = true;
1913 let mut bitfield_visibility = visibility_kind;
1914 bf.codegen(
1915 ctx,
1916 visibility_kind,
1917 accessor_kind,
1918 parent,
1919 parent_item,
1920 last_field && idx == bfields.len() - 1,
1921 result,
1922 struct_layout,
1923 fields,
1924 methods,
1925 (
1926 &unit_field_name,
1927 &unit_field_ty,
1928 &mut bitfield_representable_as_int,
1929 &mut bitfield_visibility,
1930 ),
1931 );
1932 if bitfield_visibility < unit_visibility {
1933 unit_visibility = bitfield_visibility;
1934 }
1935
1936 if !bitfield_representable_as_int {
1938 generate_ctor = false;
1939 continue;
1940 }
1941
1942 let param_name = bitfield_getter_name(ctx, bf);
1943 let bitfield_ty_item = ctx.resolve_item(bf.ty());
1944 let bitfield_ty = bitfield_ty_item.expect_type();
1945 let bitfield_ty =
1946 bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);
1947
1948 ctor_params.push(quote! {
1949 #param_name : #bitfield_ty
1950 });
1951 ctor_impl = bf.extend_ctor_impl(ctx, ¶m_name, ctor_impl);
1952 }
1953
1954 let access_spec = access_specifier(unit_visibility);
1955
1956 let field = quote! {
1957 #access_spec #unit_field_ident : #field_ty ,
1958 };
1959 fields.extend(Some(field));
1960
1961 if generate_ctor {
1962 methods.extend(Some(quote! {
1963 #[inline]
1964 #access_spec fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty {
1965 let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default();
1966 #ctor_impl
1967 __bindgen_bitfield_unit
1968 }
1969 }));
1970 }
1971
1972 struct_layout.saw_bitfield_unit(layout);
1973 }
1974}
1975
1976fn bitfield_getter_name(
1977 ctx: &BindgenContext,
1978 bitfield: &Bitfield,
1979) -> proc_macro2::TokenStream {
1980 let name = bitfield.getter_name();
1981 let name = ctx.rust_ident_raw(name);
1982 quote! { #name }
1983}
1984
1985fn bitfield_raw_getter_name(
1986 ctx: &BindgenContext,
1987 bitfield: &Bitfield,
1988) -> proc_macro2::TokenStream {
1989 let name = bitfield.getter_name();
1990 let name = ctx.rust_ident_raw(format!("{name}_raw"));
1991 quote! { #name }
1992}
1993
1994fn bitfield_setter_name(
1995 ctx: &BindgenContext,
1996 bitfield: &Bitfield,
1997) -> proc_macro2::TokenStream {
1998 let setter = bitfield.setter_name();
1999 let setter = ctx.rust_ident_raw(setter);
2000 quote! { #setter }
2001}
2002
2003fn bitfield_raw_setter_name(
2004 ctx: &BindgenContext,
2005 bitfield: &Bitfield,
2006) -> proc_macro2::TokenStream {
2007 let setter = bitfield.setter_name();
2008 let setter = ctx.rust_ident_raw(format!("{setter}_raw"));
2009 quote! { #setter }
2010}
2011
2012impl<'a> FieldCodegen<'a> for Bitfield {
2013 type Extra = (
2014 &'a str,
2015 &'a syn::Type,
2016 &'a mut bool,
2017 &'a mut FieldVisibilityKind,
2018 );
2019
2020 fn codegen<F, M>(
2021 &self,
2022 ctx: &BindgenContext,
2023 visibility_kind: FieldVisibilityKind,
2024 _accessor_kind: FieldAccessorKind,
2025 parent: &CompInfo,
2026 parent_item: &Item,
2027 _last_field: bool,
2028 _result: &mut CodegenResult,
2029 struct_layout: &mut StructLayoutTracker,
2030 _fields: &mut F,
2031 methods: &mut M,
2032 (
2033 unit_field_name,
2034 unit_field_ty,
2035 bitfield_representable_as_int,
2036 bitfield_visibility,
2037 ): (
2038 &'a str,
2039 &'a syn::Type,
2040 &mut bool,
2041 &'a mut FieldVisibilityKind,
2042 ),
2043 ) where
2044 F: Extend<proc_macro2::TokenStream>,
2045 M: Extend<proc_macro2::TokenStream>,
2046 {
2047 let prefix = ctx.trait_prefix();
2048 let getter_name = bitfield_getter_name(ctx, self);
2049 let setter_name = bitfield_setter_name(ctx, self);
2050 let raw_getter_name = bitfield_raw_getter_name(ctx, self);
2051 let raw_setter_name = bitfield_raw_setter_name(ctx, self);
2052 let unit_field_ident = Ident::new(unit_field_name, Span::call_site());
2053
2054 let bitfield_ty_item = ctx.resolve_item(self.ty());
2055 let bitfield_ty = bitfield_ty_item.expect_type();
2056 let bitfield_ty_ident = bitfield_ty.name();
2057
2058 let bitfield_ty_layout = bitfield_ty
2059 .layout(ctx)
2060 .expect("Bitfield without layout? Gah!");
2061 let bitfield_int_ty =
2062 if let Some(int_ty) = helpers::integer_type(bitfield_ty_layout) {
2063 *bitfield_representable_as_int = true;
2064 int_ty
2065 } else {
2066 *bitfield_representable_as_int = false;
2067 return;
2068 };
2069
2070 let bitfield_ty =
2071 bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);
2072
2073 let offset = self.offset_into_unit();
2074 let width = self.width() as u8;
2075
2076 let override_visibility = self.name().and_then(|field_name| {
2077 ctx.options().last_callback(|cb| {
2078 cb.field_visibility(FieldInfo {
2079 type_name: &parent_item.canonical_name(ctx),
2080 field_name,
2081 field_type_name: bitfield_ty_ident,
2082 })
2083 })
2084 });
2085 *bitfield_visibility = compute_visibility(
2086 ctx,
2087 self.is_public(),
2088 override_visibility,
2089 self.annotations(),
2090 visibility_kind,
2091 );
2092 let access_spec = access_specifier(*bitfield_visibility);
2093
2094 if parent.is_union() && !struct_layout.is_rust_union() {
2095 methods.extend(Some(quote! {
2096 #[inline]
2097 #access_spec fn #getter_name(&self) -> #bitfield_ty {
2098 unsafe {
2099 ::#prefix::mem::transmute(
2100 self.#unit_field_ident.as_ref().get(#offset, #width)
2101 as #bitfield_int_ty
2102 )
2103 }
2104 }
2105
2106 #[inline]
2107 #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
2108 unsafe {
2109 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2110 self.#unit_field_ident.as_mut().set(
2111 #offset,
2112 #width,
2113 val as u64
2114 )
2115 }
2116 }
2117 }));
2118
2119 methods.extend(Some(quote! {
2120 #[inline]
2121 #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty {
2122 unsafe {
2123 ::#prefix::mem::transmute(<#unit_field_ty>::raw_get(
2124 (*::#prefix::ptr::addr_of!((*this).#unit_field_ident)).as_ref() as *const _,
2125 #offset,
2126 #width,
2127 ) as #bitfield_int_ty)
2128 }
2129 }
2130
2131 #[inline]
2132 #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) {
2133 unsafe {
2134 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2135 <#unit_field_ty>::raw_set(
2136 (*::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident)).as_mut() as *mut _,
2137 #offset,
2138 #width,
2139 val as u64,
2140 )
2141 }
2142 }
2143 }));
2144 } else {
2145 methods.extend(Some(quote! {
2146 #[inline]
2147 #access_spec fn #getter_name(&self) -> #bitfield_ty {
2148 unsafe {
2149 ::#prefix::mem::transmute(
2150 self.#unit_field_ident.get_const::<#offset, #width>()
2151 as #bitfield_int_ty
2152 )
2153 }
2154 }
2155
2156 #[inline]
2157 #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
2158 unsafe {
2159 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2160 self.#unit_field_ident.set_const::<#offset, #width>(
2161 val as u64
2162 )
2163 }
2164 }
2165 }));
2166
2167 methods.extend(Some(quote! {
2168 #[inline]
2169 #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty {
2170 unsafe {
2171 ::#prefix::mem::transmute(<#unit_field_ty>::raw_get_const::<#offset, #width>(
2172 ::#prefix::ptr::addr_of!((*this).#unit_field_ident),
2173 ) as #bitfield_int_ty)
2174 }
2175 }
2176
2177 #[inline]
2178 #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) {
2179 unsafe {
2180 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2181 <#unit_field_ty>::raw_set_const::<#offset, #width>(
2182 ::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident),
2183 val as u64,
2184 )
2185 }
2186 }
2187 }));
2188 }
2189 }
2190}
2191
2192impl CodeGenerator for CompInfo {
2193 type Extra = Item;
2194 type Return = ();
2195
2196 fn codegen(
2197 &self,
2198 ctx: &BindgenContext,
2199 result: &mut CodegenResult<'_>,
2200 item: &Item,
2201 ) {
2202 debug!("<CompInfo as CodeGenerator>::codegen: item = {item:?}");
2203 debug_assert!(item.is_enabled_for_codegen(ctx));
2204
2205 if self.has_non_type_template_params() {
2208 return;
2209 }
2210
2211 let ty = item.expect_type();
2212 let layout = ty.layout(ctx);
2213 let mut packed = self.is_packed(ctx, layout.as_ref());
2214
2215 let canonical_name = item.canonical_name(ctx);
2216 let canonical_ident = ctx.rust_ident(&canonical_name);
2217
2218 let is_opaque = item.is_opaque(ctx, &());
2231 let mut fields = vec![];
2232 let visibility = item
2233 .annotations()
2234 .visibility_kind()
2235 .unwrap_or(ctx.options().default_visibility);
2236 let mut struct_layout = StructLayoutTracker::new(
2237 ctx,
2238 self,
2239 ty,
2240 &canonical_name,
2241 visibility,
2242 packed,
2243 );
2244
2245 let mut generic_param_names = vec![];
2246
2247 for (idx, ty) in item.used_template_params(ctx).iter().enumerate() {
2248 let param = ctx.resolve_type(*ty);
2249 let name = param.name().unwrap();
2250 let ident = ctx.rust_ident(name);
2251 generic_param_names.push(ident.clone());
2252
2253 let prefix = ctx.trait_prefix();
2254 let field_name = ctx.rust_ident(format!("_phantom_{idx}"));
2255 fields.push(quote! {
2256 pub #field_name : ::#prefix::marker::PhantomData<
2257 ::#prefix::cell::UnsafeCell<#ident>
2258 > ,
2259 });
2260 }
2261
2262 if !is_opaque {
2263 if item.has_vtable_ptr(ctx) {
2264 let vtable = Vtable::new(item.id(), self);
2265 vtable.codegen(ctx, result, item);
2266
2267 let vtable_type = vtable
2268 .try_to_rust_ty(ctx, &())
2269 .expect("vtable to Rust type conversion is infallible")
2270 .to_ptr(true);
2271
2272 fields.push(quote! {
2273 pub vtable_: #vtable_type ,
2274 });
2275
2276 struct_layout.saw_vtable();
2277 }
2278
2279 for base in self.base_members() {
2280 if !base.requires_storage(ctx) {
2281 continue;
2282 }
2283
2284 let inner_item = ctx.resolve_item(base.ty);
2285 let inner = inner_item
2286 .to_rust_ty_or_opaque(ctx, &())
2287 .with_implicit_template_params(ctx, inner_item);
2288 let field_name = ctx.rust_ident(&base.field_name);
2289
2290 struct_layout.saw_base(inner_item.expect_type());
2291
2292 let visibility = match (
2293 base.is_public(),
2294 ctx.options().respect_cxx_access_specs,
2295 ) {
2296 (true, true) => FieldVisibilityKind::Public,
2297 (false, true) => FieldVisibilityKind::Private,
2298 _ => ctx.options().default_visibility,
2299 };
2300
2301 let access_spec = access_specifier(visibility);
2302 fields.push(quote! {
2303 #access_spec #field_name: #inner,
2304 });
2305 }
2306 }
2307
2308 let mut methods = vec![];
2309 if !is_opaque {
2310 let struct_accessor_kind = item
2311 .annotations()
2312 .accessor_kind()
2313 .unwrap_or(FieldAccessorKind::None);
2314 let field_decls = self.fields();
2315 for (idx, field) in field_decls.iter().enumerate() {
2316 field.codegen(
2317 ctx,
2318 visibility,
2319 struct_accessor_kind,
2320 self,
2321 item,
2322 idx == field_decls.len() - 1,
2323 result,
2324 &mut struct_layout,
2325 &mut fields,
2326 &mut methods,
2327 (),
2328 );
2329 }
2330 if let Some(comp_layout) = layout {
2333 fields.extend(
2334 struct_layout
2335 .add_tail_padding(&canonical_name, comp_layout),
2336 );
2337 }
2338 }
2339
2340 if is_opaque {
2341 debug_assert!(fields.is_empty());
2343 debug_assert!(methods.is_empty());
2344 }
2345
2346 let is_union = self.kind() == CompKind::Union;
2347 let layout = item.kind().expect_type().layout(ctx);
2348 let zero_sized = item.is_zero_sized(ctx);
2349 let forward_decl = self.is_forward_declaration();
2350
2351 let mut explicit_align = None;
2352
2353 if !forward_decl && zero_sized {
2364 let has_address = if is_opaque {
2365 layout.is_none()
2368 } else {
2369 layout.map_or(true, |l| l.size != 0)
2370 };
2371
2372 if has_address {
2373 let layout = Layout::new(1, 1);
2374 struct_layout.saw_field_with_layout(
2375 "_address",
2376 layout,
2377 Some(0),
2378 );
2379 fields.push(quote! {
2380 pub _address: u8,
2381 });
2382 }
2383 }
2384
2385 if is_opaque {
2386 match layout {
2387 Some(l) => {
2388 explicit_align = Some(l.align);
2389 let ty = helpers::blob(ctx, l, false);
2390 fields.push(quote! {
2391 pub _bindgen_opaque_blob: #ty ,
2392 });
2393 }
2394 None => {
2395 if !forward_decl {
2396 warn!("Opaque type without layout! Expect dragons!");
2397 }
2398 }
2399 }
2400 } else if !is_union && !zero_sized {
2401 if let Some(padding_field) =
2402 layout.and_then(|layout| struct_layout.pad_struct(layout))
2403 {
2404 fields.push(padding_field);
2405 }
2406
2407 if let Some(layout) = layout {
2408 if struct_layout.requires_explicit_align(layout) {
2409 if layout.align == 1 {
2410 packed = true;
2411 } else {
2412 explicit_align = Some(layout.align);
2413 }
2414 }
2415 }
2416 } else if is_union && !forward_decl {
2417 if let Some(layout) = layout {
2418 if struct_layout.requires_explicit_align(layout) {
2420 explicit_align = Some(layout.align);
2421 }
2422 if !struct_layout.is_rust_union() {
2423 let ty = helpers::blob(ctx, layout, false);
2424 fields.push(quote! {
2425 pub bindgen_union_field: #ty,
2426 });
2427 }
2428 }
2429 }
2430
2431 if forward_decl {
2432 fields.push(quote! {
2433 _unused: [u8; 0],
2434 });
2435 }
2436
2437 let (flex_array_generic, flex_inner_ty) = if ctx.options().flexarray_dst
2438 {
2439 match self.flex_array_member(ctx) {
2440 Some(ty) => {
2441 let inner = ty.to_rust_ty_or_opaque(ctx, &());
2442 (
2443 Some(quote! { FAM: ?Sized = [ #inner; 0 ] }),
2444 Some(quote! { #inner }),
2445 )
2446 }
2447 None => (None, None),
2448 }
2449 } else {
2450 (None, None)
2451 };
2452
2453 let (generics, impl_generics_labels, impl_generics_params) =
2461 if !generic_param_names.is_empty() || flex_array_generic.is_some() {
2462 let (flex_sized, flex_fam) = match flex_inner_ty.as_ref() {
2463 None => (None, None),
2464 Some(ty) => (
2465 Some(quote! { [ #ty; 0 ] }),
2466 Some(quote! { FAM: ?Sized = [ #ty; 0 ] }),
2467 ),
2468 };
2469
2470 (
2471 quote! {
2472 < #( #generic_param_names , )* #flex_fam >
2473 },
2474 quote! {
2475 < #( #generic_param_names , )* >
2476 },
2477 quote! {
2478 < #( #generic_param_names , )* #flex_sized >
2479 },
2480 )
2481 } else {
2482 (quote! {}, quote! {}, quote! {})
2483 };
2484
2485 let mut attributes = vec![];
2486 let mut needs_clone_impl = false;
2487 let mut needs_default_impl = false;
2488 let mut needs_debug_impl = false;
2489 let mut needs_partialeq_impl = false;
2490 let needs_flexarray_impl = flex_array_generic.is_some();
2491 if let Some(comment) = item.comment(ctx) {
2492 attributes.push(attributes::doc(&comment));
2493 }
2494
2495 if packed &&
2498 !is_opaque &&
2499 !(explicit_align.is_some() &&
2500 self.already_packed(ctx).unwrap_or(false))
2501 {
2502 let n = layout.map_or(1, |l| l.align);
2503 let packed_repr = if n == 1 {
2504 "packed".to_string()
2505 } else {
2506 format!("packed({n})")
2507 };
2508 attributes.push(attributes::repr_list(&["C", &packed_repr]));
2509 } else {
2510 attributes.push(attributes::repr("C"));
2511 }
2512
2513 if let Some(explicit) = explicit_align {
2515 if self.has_bitfields() && explicit <= 8 {
2520 let align_ty = match explicit {
2521 8 => quote! { u64 },
2522 4 => quote! { u32 },
2523 2 => quote! { u16 },
2524 _ => quote! { u8 },
2525 };
2526 let align_field = quote! {
2527 pub _bindgen_align: [#align_ty; 0],
2528 };
2529 fields.insert(0, align_field);
2530 } else {
2531 let explicit = helpers::ast_ty::int_expr(explicit as i64);
2532 attributes.push(quote! {
2533 #[repr(align(#explicit))]
2534 });
2535 }
2536 }
2537
2538 let derivable_traits = if self.is_forward_declaration() {
2539 let mut derivable_traits = DerivableTraits::empty();
2542 if !item.annotations().disallow_debug() {
2543 derivable_traits |= DerivableTraits::DEBUG;
2544 }
2545 derivable_traits
2546 } else {
2547 derives_of_item(item, ctx, packed)
2548 };
2549 if !derivable_traits.contains(DerivableTraits::DEBUG) {
2550 needs_debug_impl = ctx.options().derive_debug &&
2551 ctx.options().impl_debug &&
2552 !ctx.no_debug_by_name(item) &&
2553 !item.annotations().disallow_debug();
2554 }
2555
2556 if !derivable_traits.contains(DerivableTraits::DEFAULT) {
2557 needs_default_impl = ctx.options().derive_default &&
2558 !self.is_forward_declaration() &&
2559 !ctx.no_default_by_name(item) &&
2560 !item.annotations().disallow_default();
2561 }
2562
2563 let all_template_params = item.all_template_params(ctx);
2564
2565 if derivable_traits.contains(DerivableTraits::COPY) &&
2566 !derivable_traits.contains(DerivableTraits::CLONE)
2567 {
2568 needs_clone_impl = true;
2569 }
2570
2571 if !derivable_traits.contains(DerivableTraits::PARTIAL_EQ) {
2572 needs_partialeq_impl = ctx.options().derive_partialeq &&
2573 ctx.options().impl_partialeq &&
2574 ctx.lookup_can_derive_partialeq_or_partialord(item.id()) ==
2575 CanDerive::Manually;
2576 }
2577
2578 let mut derives: Vec<_> = derivable_traits.into();
2579 derives.extend(item.annotations().derives().iter().map(String::as_str));
2580
2581 let is_rust_union = is_union && struct_layout.is_rust_union();
2582
2583 utils::call_discovered_item_callback(ctx, item, || match self.kind() {
2584 CompKind::Struct => DiscoveredItem::Struct {
2585 original_name: item
2586 .kind()
2587 .expect_type()
2588 .name()
2589 .map(String::from),
2590 final_name: canonical_ident.to_string(),
2591 },
2592 CompKind::Union => DiscoveredItem::Union {
2593 original_name: item
2594 .kind()
2595 .expect_type()
2596 .name()
2597 .map(String::from),
2598 final_name: canonical_ident.to_string(),
2599 },
2600 });
2601
2602 let custom_derives = ctx.options().all_callbacks(|cb| {
2605 cb.add_derives(&DeriveInfo {
2606 name: &canonical_name,
2607 kind: if is_rust_union {
2608 DeriveTypeKind::Union
2609 } else {
2610 DeriveTypeKind::Struct
2611 },
2612 })
2613 });
2614 append_custom_derives(&mut derives, &custom_derives);
2616
2617 if !derives.is_empty() {
2618 attributes.push(attributes::derives(&derives));
2619 }
2620
2621 attributes.extend(
2622 item.annotations()
2623 .attributes()
2624 .iter()
2625 .map(|s| s.parse().unwrap()),
2626 );
2627
2628 let custom_attributes = ctx.options().all_callbacks(|cb| {
2629 cb.add_attributes(&AttributeInfo {
2630 name: &canonical_name,
2631 kind: if is_rust_union {
2632 DeriveTypeKind::Union
2633 } else {
2634 DeriveTypeKind::Struct
2635 },
2636 })
2637 });
2638 attributes.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));
2639
2640 if item.must_use(ctx) {
2641 attributes.push(attributes::must_use());
2642 }
2643
2644 let mut tokens = if is_rust_union {
2645 quote! {
2646 #( #attributes )*
2647 pub union #canonical_ident
2648 }
2649 } else {
2650 quote! {
2651 #( #attributes )*
2652 pub struct #canonical_ident
2653 }
2654 };
2655
2656 tokens.append_all(quote! {
2657 #generics {
2658 #( #fields )*
2659 }
2660 });
2661 result.push(tokens);
2662
2663 for ty in self.inner_types() {
2668 let child_item = ctx.resolve_item(*ty);
2669 child_item.codegen(ctx, result, &());
2671 }
2672
2673 if self.found_unknown_attr() {
2677 warn!("Type {canonical_ident} has an unknown attribute that may affect layout");
2678 }
2679
2680 if all_template_params.is_empty() {
2681 if !is_opaque {
2682 for var in self.inner_vars() {
2683 ctx.resolve_item(*var).codegen(ctx, result, &());
2684 }
2685 }
2686
2687 if ctx.options().layout_tests && !self.is_forward_declaration() {
2688 if let Some(layout) = layout {
2689 let compile_time = ctx.options().rust_features().offset_of;
2690 let fn_name = if compile_time {
2691 None
2692 } else {
2693 let fn_name =
2694 format!("bindgen_test_layout_{canonical_ident}");
2695 Some(ctx.rust_ident_raw(fn_name))
2696 };
2697 let prefix = ctx.trait_prefix();
2698 let size_of_expr = quote! {
2699 ::#prefix::mem::size_of::<#canonical_ident>()
2700 };
2701 let align_of_expr = quote! {
2702 ::#prefix::mem::align_of::<#canonical_ident>()
2703 };
2704 let size = layout.size;
2705 let align = layout.align;
2706 let size_of_err = format!("Size of {canonical_ident}");
2707 let align_of_err =
2708 format!("Alignment of {canonical_ident}");
2709
2710 let check_struct_align = if compile_time {
2711 quote! {
2712 [#align_of_err][#align_of_expr - #align];
2713 }
2714 } else {
2715 quote! {
2716 assert_eq!(#align_of_expr, #align, #align_of_err);
2717 }
2718 };
2719
2720 let should_skip_field_offset_checks = is_opaque;
2721
2722 let check_field_offset = if should_skip_field_offset_checks
2723 {
2724 vec![]
2725 } else {
2726 self.fields()
2727 .iter()
2728 .filter_map(|field| {
2729 let Field::DataMember(field) = field else { return None };
2730 let name = field.name()?;
2731 field.offset().map(|offset| {
2732 let field_offset = offset / 8;
2733 let field_name = ctx.rust_ident(name);
2734 let offset_of_err = format!("Offset of field: {canonical_ident}::{field_name}");
2735 if compile_time {
2736 quote! {
2737 [#offset_of_err][
2738 ::#prefix::mem::offset_of!(#canonical_ident, #field_name) - #field_offset
2739 ];
2740 }
2741 } else {
2742 quote! {
2743 assert_eq!(
2744 unsafe {
2745 ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize
2746 },
2747 #field_offset,
2748 #offset_of_err
2749 );
2750 }
2751 }
2752 })
2753 })
2754 .collect()
2755 };
2756
2757 let uninit_decl = if check_field_offset.is_empty() ||
2758 compile_time
2759 {
2760 None
2761 } else {
2762 Some(quote! {
2765 const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit();
2769 let ptr = UNINIT.as_ptr();
2770 })
2771 };
2772
2773 if compile_time {
2774 result.push(quote! {
2775 #[allow(clippy::unnecessary_operation, clippy::identity_op)]
2776 const _: () = {
2777 [#size_of_err][#size_of_expr - #size];
2778 #check_struct_align
2779 #( #check_field_offset )*
2780 };
2781 });
2782 } else {
2783 result.push(quote! {
2784 #[test]
2785 fn #fn_name() {
2786 #uninit_decl
2787 assert_eq!(#size_of_expr, #size, #size_of_err);
2788 #check_struct_align
2789 #( #check_field_offset )*
2790 }
2791 });
2792 }
2793 }
2794 }
2795
2796 let mut method_names = Default::default();
2797 let discovered_id = DiscoveredItemId::new(item.id().as_usize());
2798 if ctx.options().codegen_config.methods() {
2799 for method in self.methods() {
2800 assert_ne!(method.kind(), MethodKind::Constructor);
2801 method.codegen_method(
2802 ctx,
2803 &mut methods,
2804 &mut method_names,
2805 result,
2806 self,
2807 discovered_id,
2808 );
2809 }
2810 }
2811
2812 if ctx.options().codegen_config.constructors() {
2813 for sig in self.constructors() {
2814 Method::new(
2815 MethodKind::Constructor,
2816 *sig,
2817 false,
2819 )
2820 .codegen_method(
2821 ctx,
2822 &mut methods,
2823 &mut method_names,
2824 result,
2825 self,
2826 discovered_id,
2827 );
2828 }
2829 }
2830
2831 if ctx.options().codegen_config.destructors() {
2832 if let Some((kind, destructor)) = self.destructor() {
2833 debug_assert!(kind.is_destructor());
2834 Method::new(kind, destructor, false).codegen_method(
2835 ctx,
2836 &mut methods,
2837 &mut method_names,
2838 result,
2839 self,
2840 discovered_id,
2841 );
2842 }
2843 }
2844 }
2845
2846 let ty_for_impl = quote! {
2849 #canonical_ident #impl_generics_params
2850 };
2851
2852 if needs_clone_impl {
2853 result.push(quote! {
2854 impl #impl_generics_labels Clone for #ty_for_impl {
2855 fn clone(&self) -> Self { *self }
2856 }
2857 });
2858 }
2859
2860 if needs_flexarray_impl {
2861 result.push(self.generate_flexarray(
2862 ctx,
2863 &canonical_ident,
2864 flex_inner_ty.as_ref(),
2865 &generic_param_names,
2866 &impl_generics_labels,
2867 ));
2868 }
2869
2870 if needs_default_impl {
2871 let prefix = ctx.trait_prefix();
2872 let body = quote! {
2873 let mut s = ::#prefix::mem::MaybeUninit::<Self>::uninit();
2874 unsafe {
2875 ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2876 s.assume_init()
2877 }
2878 };
2879 result.push(quote! {
2884 impl #impl_generics_labels Default for #ty_for_impl {
2885 fn default() -> Self {
2886 #body
2887 }
2888 }
2889 });
2890 }
2891
2892 if needs_debug_impl {
2893 let impl_ = impl_debug::gen_debug_impl(
2894 ctx,
2895 self.fields(),
2896 item,
2897 self.kind(),
2898 );
2899
2900 let prefix = ctx.trait_prefix();
2901
2902 result.push(quote! {
2903 impl #impl_generics_labels ::#prefix::fmt::Debug for #ty_for_impl {
2904 #impl_
2905 }
2906 });
2907 }
2908
2909 if needs_partialeq_impl {
2910 if let Some(impl_) = impl_partialeq::gen_partialeq_impl(
2911 ctx,
2912 self,
2913 item,
2914 &ty_for_impl,
2915 ) {
2916 let partialeq_bounds = if generic_param_names.is_empty() {
2917 quote! {}
2918 } else {
2919 let bounds = generic_param_names.iter().map(|t| {
2920 quote! { #t: PartialEq }
2921 });
2922 quote! { where #( #bounds ),* }
2923 };
2924
2925 let prefix = ctx.trait_prefix();
2926 result.push(quote! {
2927 impl #impl_generics_labels ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds {
2928 #impl_
2929 }
2930 });
2931 }
2932 }
2933
2934 if !methods.is_empty() {
2935 result.push(quote! {
2936 impl #impl_generics_labels #ty_for_impl {
2937 #( #methods )*
2938 }
2939 });
2940 }
2941 }
2942}
2943
2944impl CompInfo {
2945 fn generate_flexarray(
2946 &self,
2947 ctx: &BindgenContext,
2948 canonical_ident: &Ident,
2949 flex_inner_ty: Option<&proc_macro2::TokenStream>,
2950 generic_param_names: &[Ident],
2951 impl_generics_labels: &proc_macro2::TokenStream,
2952 ) -> proc_macro2::TokenStream {
2953 let prefix = ctx.trait_prefix();
2954
2955 let flex_array = flex_inner_ty.as_ref().map(|ty| quote! { [ #ty ] });
2956
2957 let dst_ty_for_impl = quote! {
2958 #canonical_ident < #( #generic_param_names , )* #flex_array >
2959
2960 };
2961 let sized_ty_for_impl = quote! {
2962 #canonical_ident < #( #generic_param_names , )* [ #flex_inner_ty; 0 ] >
2963 };
2964
2965 let layout = if ctx.options().rust_features().layout_for_ptr {
2966 quote! {
2967 pub fn layout(len: usize) -> ::#prefix::alloc::Layout {
2968 unsafe {
2970 let p: *const Self = ::#prefix::ptr::from_raw_parts(::#prefix::ptr::null::<()>(), len);
2971 ::#prefix::alloc::Layout::for_value_raw(p)
2972 }
2973 }
2974 }
2975 } else {
2976 quote!()
2977 };
2978
2979 let (from_ptr_dst, from_ptr_sized) = if ctx
2980 .options()
2981 .rust_features()
2982 .ptr_metadata
2983 {
2984 let flex_ref_inner = ctx.wrap_unsafe_ops(quote! {
2985 Self::flex_ptr(self, len)
2986 });
2987 let flex_ref_mut_inner = ctx.wrap_unsafe_ops(quote! {
2988 Self::flex_ptr_mut(self, len).assume_init()
2989 });
2990 let flex_ptr_inner = ctx.wrap_unsafe_ops(quote! {
2991 &*::#prefix::ptr::from_raw_parts(ptr as *const (), len)
2992 });
2993 let flex_ptr_mut_inner = ctx.wrap_unsafe_ops(quote! {
2994 let mut uninit = ::#prefix::mem::MaybeUninit::<&mut #dst_ty_for_impl>::uninit();
2996 (uninit.as_mut_ptr() as *mut *mut #dst_ty_for_impl)
2997 .write(::#prefix::ptr::from_raw_parts_mut(ptr as *mut (), len));
2998
2999 uninit
3000 });
3001
3002 (
3003 quote! {
3004 #[inline]
3005 pub fn fixed(&self) -> (& #sized_ty_for_impl, usize) {
3006 unsafe {
3007 let (ptr, len) = (self as *const Self).to_raw_parts();
3008 (&*(ptr as *const #sized_ty_for_impl), len)
3009 }
3010 }
3011
3012 #[inline]
3013 pub fn fixed_mut(&mut self) -> (&mut #sized_ty_for_impl, usize) {
3014 unsafe {
3015 let (ptr, len) = (self as *mut Self).to_raw_parts();
3016 (&mut *(ptr as *mut #sized_ty_for_impl), len)
3017 }
3018 }
3019 },
3020 quote! {
3021 pub unsafe fn flex_ref(&self, len: usize) -> &#dst_ty_for_impl {
3025 #flex_ref_inner
3027 }
3028
3029 #[inline]
3033 pub unsafe fn flex_ref_mut(&mut self, len: usize) -> &mut #dst_ty_for_impl {
3034 #flex_ref_mut_inner
3036 }
3037
3038 #[inline]
3043 pub unsafe fn flex_ptr<'unbounded>(ptr: *const Self, len: usize) -> &'unbounded #dst_ty_for_impl {
3044 #flex_ptr_inner
3045 }
3046
3047 #[inline]
3055 pub unsafe fn flex_ptr_mut<'unbounded>(
3056 ptr: *mut Self,
3057 len: usize,
3058 ) -> ::#prefix::mem::MaybeUninit<&'unbounded mut #dst_ty_for_impl> {
3059 #flex_ptr_mut_inner
3060 }
3061 },
3062 )
3063 } else {
3064 (quote!(), quote!())
3065 };
3066
3067 quote! {
3068 impl #impl_generics_labels #dst_ty_for_impl {
3069 #layout
3070 #from_ptr_dst
3071 }
3072
3073 impl #impl_generics_labels #sized_ty_for_impl {
3074 #from_ptr_sized
3075 }
3076 }
3077 }
3078}
3079
3080impl Method {
3081 fn codegen_method(
3082 &self,
3083 ctx: &BindgenContext,
3084 methods: &mut Vec<proc_macro2::TokenStream>,
3085 method_names: &mut HashSet<String>,
3086 result: &mut CodegenResult<'_>,
3087 _parent: &CompInfo,
3088 parent_id: DiscoveredItemId,
3089 ) {
3090 assert!({
3091 let cc = &ctx.options().codegen_config;
3092 match self.kind() {
3093 MethodKind::Constructor => cc.constructors(),
3094 MethodKind::Destructor |
3095 MethodKind::VirtualDestructor { .. } => cc.destructors(),
3096 MethodKind::Static |
3097 MethodKind::Normal |
3098 MethodKind::Virtual { .. } => cc.methods(),
3099 }
3100 });
3101
3102 if self.is_virtual() {
3104 return; }
3106
3107 let function_item = ctx.resolve_item(self.signature());
3109 if !function_item.process_before_codegen(ctx, result) {
3110 return;
3111 }
3112 let function = function_item.expect_function();
3113 let times_seen = function.codegen(ctx, result, function_item);
3114 let Some(times_seen) = times_seen else { return };
3115 let signature_item = ctx.resolve_item(function.signature());
3116 let mut name = match self.kind() {
3117 MethodKind::Constructor => "new".into(),
3118 MethodKind::Destructor => "destruct".into(),
3119 _ => function.name().to_owned(),
3120 };
3121
3122 let TypeKind::Function(ref signature) =
3123 *signature_item.expect_type().kind()
3124 else {
3125 panic!("How in the world?")
3126 };
3127
3128 let supported_abi = signature.abi(ctx, Some(&*name)).is_ok();
3129 if !supported_abi {
3130 return;
3131 }
3132
3133 if signature.is_variadic() {
3136 return;
3137 }
3138
3139 if method_names.contains(&name) {
3140 let mut count = 1;
3141 let mut new_name;
3142
3143 while {
3144 new_name = format!("{name}{count}");
3145 method_names.contains(&new_name)
3146 } {
3147 count += 1;
3148 }
3149
3150 name = new_name;
3151 }
3152
3153 method_names.insert(name.clone());
3154
3155 utils::call_discovered_item_callback(ctx, function_item, || {
3156 DiscoveredItem::Method {
3157 parent: parent_id,
3158 final_name: name.clone(),
3159 }
3160 });
3161
3162 let mut function_name = function_item.canonical_name(ctx);
3163 if times_seen > 0 {
3164 write!(&mut function_name, "{times_seen}").unwrap();
3165 }
3166 let function_name = ctx.rust_ident(function_name);
3167 let mut args = utils::fnsig_arguments(ctx, signature);
3168 let mut ret = utils::fnsig_return_ty(ctx, signature);
3169
3170 if !self.is_static() && !self.is_constructor() {
3171 args[0] = if self.is_const() {
3172 quote! { &self }
3173 } else {
3174 quote! { &mut self }
3175 };
3176 }
3177
3178 if self.is_constructor() {
3184 args.remove(0);
3185 ret = quote! { -> Self };
3186 }
3187
3188 let mut exprs =
3189 helpers::ast_ty::arguments_from_signature(signature, ctx);
3190
3191 let mut stmts = vec![];
3192
3193 if self.is_constructor() {
3196 let prefix = ctx.trait_prefix();
3197 exprs[0] = quote! {
3198 __bindgen_tmp.as_mut_ptr()
3199 };
3200 let tmp_variable_decl = quote! {
3201 let mut __bindgen_tmp = ::#prefix::mem::MaybeUninit::uninit()
3202 };
3203 stmts.push(tmp_variable_decl);
3204 } else if !self.is_static() {
3205 assert!(!exprs.is_empty());
3206 exprs[0] = quote! {
3207 self
3208 };
3209 }
3210
3211 let call = quote! {
3212 #function_name (#( #exprs ),* )
3213 };
3214
3215 stmts.push(call);
3216
3217 if self.is_constructor() {
3218 stmts.push(quote! {
3219 __bindgen_tmp.assume_init()
3220 });
3221 }
3222
3223 let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*));
3224
3225 let mut attrs = vec![attributes::inline()];
3226
3227 if signature.must_use() {
3228 attrs.push(attributes::must_use());
3229 }
3230
3231 let name = ctx.rust_ident(&name);
3232 methods.push(quote! {
3233 #(#attrs)*
3234 pub unsafe fn #name ( #( #args ),* ) #ret {
3235 #block
3236 }
3237 });
3238 }
3239}
3240
3241#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
3243pub enum EnumVariation {
3244 Rust {
3248 non_exhaustive: bool,
3250 },
3251 NewType {
3253 is_bitfield: bool,
3255 is_global: bool,
3257 },
3258 #[default]
3260 Consts,
3261 ModuleConsts,
3263}
3264
3265impl EnumVariation {
3266 fn is_rust(self) -> bool {
3267 matches!(self, EnumVariation::Rust { .. })
3268 }
3269
3270 fn is_const(self) -> bool {
3273 matches!(self, EnumVariation::Consts | EnumVariation::ModuleConsts)
3274 }
3275}
3276
3277impl fmt::Display for EnumVariation {
3278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3279 let s = match self {
3280 Self::Rust {
3281 non_exhaustive: false,
3282 } => "rust",
3283 Self::Rust {
3284 non_exhaustive: true,
3285 } => "rust_non_exhaustive",
3286 Self::NewType {
3287 is_bitfield: true, ..
3288 } => "bitfield",
3289 Self::NewType {
3290 is_bitfield: false,
3291 is_global,
3292 } => {
3293 if *is_global {
3294 "newtype_global"
3295 } else {
3296 "newtype"
3297 }
3298 }
3299 Self::Consts => "consts",
3300 Self::ModuleConsts => "moduleconsts",
3301 };
3302 s.fmt(f)
3303 }
3304}
3305
3306impl FromStr for EnumVariation {
3307 type Err = std::io::Error;
3308
3309 fn from_str(s: &str) -> Result<Self, Self::Err> {
3311 match s {
3312 "rust" => Ok(EnumVariation::Rust {
3313 non_exhaustive: false,
3314 }),
3315 "rust_non_exhaustive" => Ok(EnumVariation::Rust {
3316 non_exhaustive: true,
3317 }),
3318 "bitfield" => Ok(EnumVariation::NewType {
3319 is_bitfield: true,
3320 is_global: false,
3321 }),
3322 "consts" => Ok(EnumVariation::Consts),
3323 "moduleconsts" => Ok(EnumVariation::ModuleConsts),
3324 "newtype" => Ok(EnumVariation::NewType {
3325 is_bitfield: false,
3326 is_global: false,
3327 }),
3328 "newtype_global" => Ok(EnumVariation::NewType {
3329 is_bitfield: false,
3330 is_global: true,
3331 }),
3332 _ => Err(std::io::Error::new(
3333 std::io::ErrorKind::InvalidInput,
3334 concat!(
3335 "Got an invalid EnumVariation. Accepted values ",
3336 "are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',",
3337 "'moduleconsts', 'newtype' and 'newtype_global'."
3338 ),
3339 )),
3340 }
3341 }
3342}
3343
3344struct EnumBuilder {
3345 enum_type: Ident,
3349 attrs: Vec<proc_macro2::TokenStream>,
3351 repr: syn::Type,
3353 kind: EnumBuilderKind,
3355 enum_variants: Vec<EnumVariantInfo>,
3357}
3358
3359enum EnumBuilderKind {
3361 Rust {
3362 non_exhaustive: bool,
3363 },
3364 NewType {
3365 is_bitfield: bool,
3366 is_global: bool,
3367 is_anonymous: bool,
3369 },
3370 Consts {
3371 needs_typedef: bool,
3372 },
3373 ModuleConsts {
3374 module_name: Ident,
3375 },
3376}
3377
3378impl EnumBuilder {
3379 fn is_rust_enum(&self) -> bool {
3381 matches!(self.kind, EnumBuilderKind::Rust { .. })
3382 }
3383
3384 fn new(
3387 name: &str,
3388 attrs: Vec<proc_macro2::TokenStream>,
3389 repr: &syn::Type,
3390 enum_variation: EnumVariation,
3391 has_typedef: bool,
3392 enum_is_anonymous: bool,
3393 ) -> Self {
3394 let ident = Ident::new(name, Span::call_site());
3395 let mut enum_ty = ident.clone();
3397
3398 let kind = match enum_variation {
3399 EnumVariation::NewType {
3400 is_bitfield,
3401 is_global,
3402 } => EnumBuilderKind::NewType {
3403 is_bitfield,
3404 is_global,
3405 is_anonymous: enum_is_anonymous,
3406 },
3407
3408 EnumVariation::Rust { non_exhaustive } => {
3409 EnumBuilderKind::Rust { non_exhaustive }
3410 }
3411
3412 EnumVariation::Consts => EnumBuilderKind::Consts {
3413 needs_typedef: !has_typedef,
3414 },
3415
3416 EnumVariation::ModuleConsts => {
3417 enum_ty = Ident::new(
3418 CONSTIFIED_ENUM_MODULE_REPR_NAME,
3419 Span::call_site(),
3420 );
3421
3422 EnumBuilderKind::ModuleConsts {
3423 module_name: ident.clone(),
3424 }
3425 }
3426 };
3427 EnumBuilder {
3428 enum_type: enum_ty,
3429 attrs,
3430 repr: repr.clone(),
3431 kind,
3432 enum_variants: vec![],
3433 }
3434 }
3435
3436 fn with_variant(
3438 mut self,
3439 ctx: &BindgenContext,
3440 variant: &EnumVariant,
3441 variant_doc: proc_macro2::TokenStream,
3442 mangling_prefix: Option<&str>,
3443 rust_ty: &syn::Type,
3444 is_ty_named: bool,
3445 ) -> Self {
3446 let variant_name = ctx.rust_mangle(variant.name());
3447 let is_rust_enum = self.is_rust_enum();
3448 let expr = match variant.val() {
3449 EnumVariantValue::Boolean(v) if is_rust_enum => {
3450 helpers::ast_ty::uint_expr(u64::from(v))
3451 }
3452 EnumVariantValue::Boolean(v) => quote!(#v),
3453 EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
3454 EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
3455 };
3456
3457 match self.kind {
3458 EnumBuilderKind::Rust { .. } => {
3459 let name = ctx.rust_ident(variant_name);
3460 self.enum_variants.push(EnumVariantInfo {
3461 variant_name: name,
3462 variant_doc,
3463 value: expr,
3464 });
3465 self
3466 }
3467
3468 EnumBuilderKind::NewType { is_global, .. } => {
3469 let variant_ident = if is_ty_named && !is_global {
3470 ctx.rust_ident(variant_name)
3471 } else {
3472 ctx.rust_ident(match mangling_prefix {
3473 Some(prefix) => {
3474 Cow::Owned(format!("{prefix}_{variant_name}"))
3475 }
3476 None => variant_name,
3477 })
3478 };
3479 self.enum_variants.push(EnumVariantInfo {
3480 variant_name: variant_ident,
3481 variant_doc,
3482 value: quote! { #rust_ty ( #expr )},
3483 });
3484
3485 self
3486 }
3487
3488 EnumBuilderKind::Consts { .. } => {
3489 let constant_name = match mangling_prefix {
3490 Some(prefix) => {
3491 Cow::Owned(format!("{prefix}_{variant_name}"))
3492 }
3493 None => variant_name,
3494 };
3495
3496 let ident = ctx.rust_ident(constant_name);
3497 self.enum_variants.push(EnumVariantInfo {
3498 variant_name: ident,
3499 variant_doc,
3500 value: quote! { #expr },
3501 });
3502
3503 self
3504 }
3505 EnumBuilderKind::ModuleConsts { .. } => {
3506 let name = ctx.rust_ident(variant_name);
3507 self.enum_variants.push(EnumVariantInfo {
3508 variant_name: name,
3509 variant_doc,
3510 value: quote! { #expr },
3511 });
3512 self
3513 }
3514 }
3515 }
3516
3517 fn newtype_bitfield_impl(
3518 prefix: &Ident,
3519 rust_ty: &syn::Type,
3520 ) -> proc_macro2::TokenStream {
3521 let rust_ty_name = &rust_ty;
3522 quote! {
3523 impl ::#prefix::ops::BitOr<#rust_ty> for #rust_ty {
3524 type Output = Self;
3525
3526 #[inline]
3527 fn bitor(self, other: Self) -> Self {
3528 #rust_ty_name(self.0 | other.0)
3529 }
3530 }
3531 impl ::#prefix::ops::BitOrAssign for #rust_ty {
3532 #[inline]
3533 fn bitor_assign(&mut self, rhs: #rust_ty) {
3534 self.0 |= rhs.0;
3535 }
3536 }
3537 impl ::#prefix::ops::BitAnd<#rust_ty> for #rust_ty {
3538 type Output = Self;
3539
3540 #[inline]
3541 fn bitand(self, other: Self) -> Self {
3542 #rust_ty_name(self.0 & other.0)
3543 }
3544 }
3545 impl ::#prefix::ops::BitAndAssign for #rust_ty {
3546 #[inline]
3547 fn bitand_assign(&mut self, rhs: #rust_ty) {
3548 self.0 &= rhs.0;
3549 }
3550 }
3551 }
3552 }
3553
3554 fn build(
3555 self,
3556 ctx: &BindgenContext,
3557 rust_ty: &syn::Type,
3558 ) -> proc_macro2::TokenStream {
3559 let enum_ident = self.enum_type;
3560
3561 let variants = match self.kind {
3563 EnumBuilderKind::Rust { .. } => {
3564 let mut variants = vec![];
3565
3566 for v in self.enum_variants {
3567 let variant_doc = &v.variant_doc;
3568 let variant_ident = &v.variant_name;
3569 let variant_value = &v.value;
3570
3571 variants.push(quote! {
3572 #variant_doc
3573 #variant_ident = #variant_value,
3574 });
3575 }
3576
3577 if variants.is_empty() {
3578 variants.push(
3579 quote! {__bindgen_cannot_repr_c_on_empty_enum = 0,},
3580 );
3581 }
3582 variants
3583 }
3584 EnumBuilderKind::NewType { .. } => {
3585 let mut variants = vec![];
3586
3587 for v in self.enum_variants {
3588 let variant_doc = &v.variant_doc;
3589 let variant_ident = &v.variant_name;
3590 let variant_value = &v.value;
3591
3592 variants.push(quote! {
3593 #variant_doc
3594 pub const #variant_ident: #enum_ident = #variant_value;
3595 });
3596 }
3597 variants
3598 }
3599 EnumBuilderKind::Consts { .. } |
3600 EnumBuilderKind::ModuleConsts { .. } => {
3601 let mut variants = vec![];
3602
3603 for v in self.enum_variants {
3604 let variant_doc = &v.variant_doc;
3605 let variant_ident = &v.variant_name;
3606 let variant_value = &v.value;
3607
3608 variants.push(quote! {
3609 #variant_doc
3610 pub const #variant_ident: #enum_ident = #variant_value;
3611 });
3612 }
3613 variants
3614 }
3615 };
3616 let attrs = self.attrs;
3617 let enum_repr = &self.repr;
3618
3619 match self.kind {
3621 EnumBuilderKind::Rust { non_exhaustive } => {
3622 let non_exhaustive_opt =
3623 non_exhaustive.then(attributes::non_exhaustive);
3624
3625 quote! {
3626 #[repr(#enum_repr)]
3629 #non_exhaustive_opt
3630 #( #attrs )*
3631 pub enum #enum_ident {
3632 #( #variants )*
3633 }
3634 }
3635 }
3636 EnumBuilderKind::NewType {
3637 is_bitfield,
3638 is_global,
3639 is_anonymous,
3640 } => {
3641 let impl_variants = if is_anonymous || is_global {
3645 quote! {
3646 #( #variants )*
3647 }
3648 } else {
3649 quote! {
3650 impl #enum_ident {
3651 #( #variants )*
3652 }
3653 }
3654 };
3655
3656 let prefix = ctx.trait_prefix();
3657 let bitfield_impl_opt = is_bitfield
3658 .then(|| Self::newtype_bitfield_impl(&prefix, rust_ty));
3659
3660 quote! {
3661 #impl_variants
3664
3665 #bitfield_impl_opt
3666
3667 #[repr(transparent)]
3668 #( #attrs )*
3669 pub struct #enum_ident (pub #enum_repr);
3670 }
3671 }
3672 EnumBuilderKind::Consts { needs_typedef } => {
3673 let typedef_opt = needs_typedef.then(|| {
3674 quote! {
3675 #( #attrs )*
3676 pub type #enum_ident = #enum_repr;
3677 }
3678 });
3679 quote! {
3680 #( #variants )*
3681
3682 #typedef_opt
3683 }
3684 }
3685 EnumBuilderKind::ModuleConsts { module_name, .. } => {
3686 quote! {
3687 pub mod #module_name {
3689 #[allow(unused_imports)]
3690 use super::*;
3691
3692 #( #attrs )*
3693 pub type #enum_ident = #enum_repr;
3694
3695 #( #variants )*
3696 }
3697 }
3698 }
3699 }
3700 }
3701}
3702
3703impl CodeGenerator for Enum {
3704 type Extra = Item;
3705 type Return = ();
3706
3707 fn codegen(
3708 &self,
3709 ctx: &BindgenContext,
3710 result: &mut CodegenResult<'_>,
3711 item: &Item,
3712 ) {
3713 debug!("<Enum as CodeGenerator>::codegen: item = {item:?}");
3714 debug_assert!(item.is_enabled_for_codegen(ctx));
3715
3716 let name = item.canonical_name(ctx);
3717 let ident = ctx.rust_ident(&name);
3718 let enum_ty = item.expect_type();
3719 let layout = enum_ty.layout(ctx);
3720 let variation = self.computed_enum_variation(ctx, item);
3721
3722 let repr_translated;
3723 let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) {
3724 Some(repr)
3725 if !ctx.options().translate_enum_integer_types &&
3726 !variation.is_rust() =>
3727 {
3728 repr
3729 }
3730 repr => {
3731 let kind = if let Some(repr) = repr {
3739 match *repr.canonical_type(ctx).kind() {
3740 TypeKind::Int(int_kind) => int_kind,
3741 _ => panic!("Unexpected type as enum repr"),
3742 }
3743 } else {
3744 warn!(
3745 "Guessing type of enum! Forward declarations of enums \
3746 shouldn't be legal!"
3747 );
3748 IntKind::Int
3749 };
3750
3751 let signed = kind.is_signed();
3752 let size = layout
3753 .map(|l| l.size)
3754 .or_else(|| kind.known_size())
3755 .unwrap_or(0);
3756
3757 let translated = match (signed, size) {
3758 (true, 1) => IntKind::I8,
3759 (false, 1) => IntKind::U8,
3760 (true, 2) => IntKind::I16,
3761 (false, 2) => IntKind::U16,
3762 (true, 4) => IntKind::I32,
3763 (false, 4) => IntKind::U32,
3764 (true, 8) => IntKind::I64,
3765 (false, 8) => IntKind::U64,
3766 _ => {
3767 warn!(
3768 "invalid enum decl: signed: {signed}, size: {size}"
3769 );
3770 IntKind::I32
3771 }
3772 };
3773
3774 repr_translated =
3775 Type::new(None, None, TypeKind::Int(translated), false);
3776 &repr_translated
3777 }
3778 };
3779
3780 let mut attrs = vec![];
3781
3782 if let Some(comment) = item.comment(ctx) {
3783 attrs.push(attributes::doc(&comment));
3784 }
3785
3786 if item.must_use(ctx) {
3787 attrs.push(attributes::must_use());
3788 }
3789
3790 if !variation.is_const() {
3791 let packed = false; let mut derives = derives_of_item(item, ctx, packed);
3793 derives.insert(
3797 DerivableTraits::CLONE |
3798 DerivableTraits::HASH |
3799 DerivableTraits::PARTIAL_EQ |
3800 DerivableTraits::EQ,
3801 );
3802 let mut derives: Vec<_> = derives.into();
3803 for derive in item.annotations().derives() {
3804 if !derives.contains(&derive.as_str()) {
3805 derives.push(derive);
3806 }
3807 }
3808
3809 let custom_derives = ctx.options().all_callbacks(|cb| {
3812 cb.add_derives(&DeriveInfo {
3813 name: &name,
3814 kind: DeriveTypeKind::Enum,
3815 })
3816 });
3817 append_custom_derives(&mut derives, &custom_derives);
3819
3820 attrs.extend(
3821 item.annotations()
3822 .attributes()
3823 .iter()
3824 .map(|s| s.parse().unwrap()),
3825 );
3826
3827 let custom_attributes = ctx.options().all_callbacks(|cb| {
3830 cb.add_attributes(&AttributeInfo {
3831 name: &name,
3832 kind: DeriveTypeKind::Enum,
3833 })
3834 });
3835 attrs.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));
3836
3837 attrs.push(attributes::derives(&derives));
3838 }
3839
3840 fn add_constant(
3841 ctx: &BindgenContext,
3842 enum_: &Type,
3843 enum_canonical_name: &Ident,
3845 variant_name: &Ident,
3849 referenced_name: &Ident,
3850 enum_rust_ty: &syn::Type,
3851 result: &mut CodegenResult<'_>,
3852 ) {
3853 let constant_name = if enum_.name().is_some() {
3854 if ctx.options().prepend_enum_name {
3855 format!("{enum_canonical_name}_{variant_name}")
3856 } else {
3857 format!("{variant_name}")
3858 }
3859 } else {
3860 format!("{variant_name}")
3861 };
3862 let constant_name = ctx.rust_ident(constant_name);
3863
3864 result.push(quote! {
3865 pub const #constant_name : #enum_rust_ty =
3866 #enum_canonical_name :: #referenced_name ;
3867 });
3868 }
3869
3870 let repr = repr.to_rust_ty_or_opaque(ctx, item);
3871 let has_typedef = ctx.is_enum_typedef_combo(item.id());
3872
3873 utils::call_discovered_item_callback(ctx, item, || {
3874 DiscoveredItem::Enum {
3875 final_name: name.clone(),
3876 }
3877 });
3878
3879 let mut builder = EnumBuilder::new(
3880 &name,
3881 attrs,
3882 &repr,
3883 variation,
3884 has_typedef,
3885 enum_ty.name().is_none(),
3886 );
3887
3888 let mut seen_values = HashMap::<_, Ident>::default();
3890 let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &());
3891 let is_toplevel = item.is_toplevel(ctx);
3892
3893 let parent_canonical_name = if is_toplevel {
3895 None
3896 } else {
3897 Some(item.parent_id().canonical_name(ctx))
3898 };
3899
3900 let constant_mangling_prefix = if ctx.options().prepend_enum_name {
3901 if enum_ty.name().is_none() {
3902 parent_canonical_name.as_deref()
3903 } else {
3904 Some(&*name)
3905 }
3906 } else {
3907 None
3908 };
3909
3910 let mut constified_variants = VecDeque::new();
3914
3915 let mut iter = self.variants().iter().peekable();
3916 while let Some(variant) =
3917 iter.next().or_else(|| constified_variants.pop_front())
3918 {
3919 if variant.hidden() {
3920 continue;
3921 }
3922
3923 if variant.force_constification() && iter.peek().is_some() {
3924 constified_variants.push_back(variant);
3925 continue;
3926 }
3927
3928 let mut variant_doc = quote! {};
3929 if ctx.options().generate_comments {
3930 if let Some(raw_comment) = variant.comment() {
3931 let processed_comment =
3932 ctx.options().process_comment(raw_comment);
3933 variant_doc = attributes::doc(&processed_comment);
3934 }
3935 }
3936
3937 match seen_values.entry(variant.val()) {
3938 Entry::Occupied(ref entry) => {
3939 if variation.is_rust() {
3940 let variant_name = ctx.rust_mangle(variant.name());
3941 let mangled_name = if is_toplevel ||
3942 enum_ty.name().is_some()
3943 {
3944 variant_name
3945 } else {
3946 let parent_name =
3947 parent_canonical_name.as_ref().unwrap();
3948
3949 Cow::Owned(format!("{parent_name}_{variant_name}"))
3950 };
3951
3952 let existing_variant_name = entry.get();
3953 if enum_ty.name().is_some() {
3955 let enum_canonical_name = &ident;
3956 let variant_name =
3957 ctx.rust_ident_raw(&*mangled_name);
3958 result.push(quote! {
3959 impl #enum_rust_ty {
3960 pub const #variant_name : #enum_rust_ty =
3961 #enum_canonical_name :: #existing_variant_name ;
3962 }
3963 });
3964 } else {
3965 add_constant(
3966 ctx,
3967 enum_ty,
3968 &ident,
3969 &Ident::new(&mangled_name, Span::call_site()),
3970 existing_variant_name,
3971 &enum_rust_ty,
3972 result,
3973 );
3974 }
3975 } else {
3976 builder = builder.with_variant(
3977 ctx,
3978 variant,
3979 variant_doc,
3980 constant_mangling_prefix,
3981 &enum_rust_ty,
3982 enum_ty.name().is_some(),
3983 );
3984 }
3985 }
3986 Entry::Vacant(entry) => {
3987 builder = builder.with_variant(
3988 ctx,
3989 variant,
3990 variant_doc,
3991 constant_mangling_prefix,
3992 &enum_rust_ty,
3993 enum_ty.name().is_some(),
3994 );
3995
3996 let variant_name = ctx.rust_ident(variant.name());
3997
3998 if (variation.is_rust() && enum_ty.name().is_none()) ||
4002 variant.force_constification()
4003 {
4004 let mangled_name = if is_toplevel {
4005 variant_name.clone()
4006 } else {
4007 let parent_name =
4008 parent_canonical_name.as_ref().unwrap();
4009
4010 Ident::new(
4011 &format!("{parent_name}_{variant_name}"),
4012 Span::call_site(),
4013 )
4014 };
4015
4016 add_constant(
4017 ctx,
4018 enum_ty,
4019 &ident,
4020 &mangled_name,
4021 &variant_name,
4022 &enum_rust_ty,
4023 result,
4024 );
4025 }
4026
4027 entry.insert(variant_name);
4028 }
4029 }
4030 }
4031
4032 let item = builder.build(ctx, &enum_rust_ty);
4033 result.push(item);
4034 }
4035}
4036
4037struct EnumVariantInfo {
4038 variant_name: Ident,
4039 variant_doc: proc_macro2::TokenStream,
4040 value: proc_macro2::TokenStream,
4041}
4042
4043#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
4045pub enum MacroTypeVariation {
4046 Signed,
4048 #[default]
4050 Unsigned,
4051}
4052
4053impl fmt::Display for MacroTypeVariation {
4054 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4055 let s = match self {
4056 Self::Signed => "signed",
4057 Self::Unsigned => "unsigned",
4058 };
4059 s.fmt(f)
4060 }
4061}
4062
4063impl FromStr for MacroTypeVariation {
4064 type Err = std::io::Error;
4065
4066 fn from_str(s: &str) -> Result<Self, Self::Err> {
4068 match s {
4069 "signed" => Ok(MacroTypeVariation::Signed),
4070 "unsigned" => Ok(MacroTypeVariation::Unsigned),
4071 _ => Err(std::io::Error::new(
4072 std::io::ErrorKind::InvalidInput,
4073 concat!(
4074 "Got an invalid MacroTypeVariation. Accepted values ",
4075 "are 'signed' and 'unsigned'"
4076 ),
4077 )),
4078 }
4079 }
4080}
4081
4082#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
4084pub enum AliasVariation {
4085 #[default]
4087 TypeAlias,
4088 NewType,
4090 NewTypeDeref,
4092}
4093
4094impl fmt::Display for AliasVariation {
4095 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4096 let s = match self {
4097 Self::TypeAlias => "type_alias",
4098 Self::NewType => "new_type",
4099 Self::NewTypeDeref => "new_type_deref",
4100 };
4101
4102 s.fmt(f)
4103 }
4104}
4105
4106impl FromStr for AliasVariation {
4107 type Err = std::io::Error;
4108
4109 fn from_str(s: &str) -> Result<Self, Self::Err> {
4111 match s {
4112 "type_alias" => Ok(AliasVariation::TypeAlias),
4113 "new_type" => Ok(AliasVariation::NewType),
4114 "new_type_deref" => Ok(AliasVariation::NewTypeDeref),
4115 _ => Err(std::io::Error::new(
4116 std::io::ErrorKind::InvalidInput,
4117 concat!(
4118 "Got an invalid AliasVariation. Accepted values ",
4119 "are 'type_alias', 'new_type', and 'new_type_deref'"
4120 ),
4121 )),
4122 }
4123 }
4124}
4125
4126#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
4128pub enum NonCopyUnionStyle {
4129 #[default]
4131 BindgenWrapper,
4132 ManuallyDrop,
4137}
4138
4139impl fmt::Display for NonCopyUnionStyle {
4140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4141 let s = match self {
4142 Self::BindgenWrapper => "bindgen_wrapper",
4143 Self::ManuallyDrop => "manually_drop",
4144 };
4145
4146 s.fmt(f)
4147 }
4148}
4149
4150impl FromStr for NonCopyUnionStyle {
4151 type Err = std::io::Error;
4152
4153 fn from_str(s: &str) -> Result<Self, Self::Err> {
4154 match s {
4155 "bindgen_wrapper" => Ok(Self::BindgenWrapper),
4156 "manually_drop" => Ok(Self::ManuallyDrop),
4157 _ => Err(std::io::Error::new(
4158 std::io::ErrorKind::InvalidInput,
4159 concat!(
4160 "Got an invalid NonCopyUnionStyle. Accepted values ",
4161 "are 'bindgen_wrapper' and 'manually_drop'"
4162 ),
4163 )),
4164 }
4165 }
4166}
4167
4168pub(crate) trait TryToOpaque {
4174 type Extra;
4175
4176 fn try_get_layout(
4178 &self,
4179 ctx: &BindgenContext,
4180 extra: &Self::Extra,
4181 ) -> error::Result<Layout>;
4182
4183 fn try_to_opaque(
4185 &self,
4186 ctx: &BindgenContext,
4187 extra: &Self::Extra,
4188 ) -> error::Result<syn::Type> {
4189 self.try_get_layout(ctx, extra)
4190 .map(|layout| helpers::blob(ctx, layout, true))
4191 }
4192}
4193
4194pub(crate) trait ToOpaque: TryToOpaque {
4205 fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
4206 self.try_get_layout(ctx, extra)
4207 .unwrap_or_else(|_| Layout::for_size(ctx, 1))
4208 }
4209
4210 fn to_opaque(
4211 &self,
4212 ctx: &BindgenContext,
4213 extra: &Self::Extra,
4214 ) -> syn::Type {
4215 let layout = self.get_layout(ctx, extra);
4216 helpers::blob(ctx, layout, true)
4217 }
4218}
4219
4220impl<T> ToOpaque for T where T: TryToOpaque {}
4221
4222pub(crate) trait TryToRustTy {
4230 type Extra;
4231
4232 fn try_to_rust_ty(
4233 &self,
4234 ctx: &BindgenContext,
4235 extra: &Self::Extra,
4236 ) -> error::Result<syn::Type>;
4237}
4238
4239pub(crate) trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque {
4245 type Extra;
4246
4247 fn try_to_rust_ty_or_opaque(
4248 &self,
4249 ctx: &BindgenContext,
4250 extra: &<Self as TryToRustTyOrOpaque>::Extra,
4251 ) -> error::Result<syn::Type>;
4252}
4253
4254impl<E, T> TryToRustTyOrOpaque for T
4255where
4256 T: TryToRustTy<Extra = E> + TryToOpaque<Extra = E>,
4257{
4258 type Extra = E;
4259
4260 fn try_to_rust_ty_or_opaque(
4261 &self,
4262 ctx: &BindgenContext,
4263 extra: &E,
4264 ) -> error::Result<syn::Type> {
4265 self.try_to_rust_ty(ctx, extra).or_else(|_| {
4266 if let Ok(layout) = self.try_get_layout(ctx, extra) {
4267 Ok(helpers::blob(ctx, layout, true))
4268 } else {
4269 Err(Error::NoLayoutForOpaqueBlob)
4270 }
4271 })
4272 }
4273}
4274
4275pub(crate) trait ToRustTyOrOpaque: TryToRustTy + ToOpaque {
4293 type Extra;
4294
4295 fn to_rust_ty_or_opaque(
4296 &self,
4297 ctx: &BindgenContext,
4298 extra: &<Self as ToRustTyOrOpaque>::Extra,
4299 ) -> syn::Type;
4300}
4301
4302impl<E, T> ToRustTyOrOpaque for T
4303where
4304 T: TryToRustTy<Extra = E> + ToOpaque<Extra = E>,
4305{
4306 type Extra = E;
4307
4308 fn to_rust_ty_or_opaque(
4309 &self,
4310 ctx: &BindgenContext,
4311 extra: &E,
4312 ) -> syn::Type {
4313 self.try_to_rust_ty(ctx, extra)
4314 .unwrap_or_else(|_| self.to_opaque(ctx, extra))
4315 }
4316}
4317
4318impl<T> TryToOpaque for T
4319where
4320 T: Copy + Into<ItemId>,
4321{
4322 type Extra = ();
4323
4324 fn try_get_layout(
4325 &self,
4326 ctx: &BindgenContext,
4327 _: &(),
4328 ) -> error::Result<Layout> {
4329 ctx.resolve_item((*self).into()).try_get_layout(ctx, &())
4330 }
4331}
4332
4333impl<T> TryToRustTy for T
4334where
4335 T: Copy + Into<ItemId>,
4336{
4337 type Extra = ();
4338
4339 fn try_to_rust_ty(
4340 &self,
4341 ctx: &BindgenContext,
4342 _: &(),
4343 ) -> error::Result<syn::Type> {
4344 ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &())
4345 }
4346}
4347
4348impl TryToOpaque for Item {
4349 type Extra = ();
4350
4351 fn try_get_layout(
4352 &self,
4353 ctx: &BindgenContext,
4354 _: &(),
4355 ) -> error::Result<Layout> {
4356 self.kind().expect_type().try_get_layout(ctx, self)
4357 }
4358}
4359
4360impl TryToRustTy for Item {
4361 type Extra = ();
4362
4363 fn try_to_rust_ty(
4364 &self,
4365 ctx: &BindgenContext,
4366 _: &(),
4367 ) -> error::Result<syn::Type> {
4368 self.kind().expect_type().try_to_rust_ty(ctx, self)
4369 }
4370}
4371
4372impl TryToOpaque for Type {
4373 type Extra = Item;
4374
4375 fn try_get_layout(
4376 &self,
4377 ctx: &BindgenContext,
4378 _: &Item,
4379 ) -> error::Result<Layout> {
4380 self.layout(ctx).ok_or(Error::NoLayoutForOpaqueBlob)
4381 }
4382}
4383
4384impl TryToRustTy for Type {
4385 type Extra = Item;
4386
4387 fn try_to_rust_ty(
4388 &self,
4389 ctx: &BindgenContext,
4390 item: &Item,
4391 ) -> error::Result<syn::Type> {
4392 use self::helpers::ast_ty::*;
4393
4394 match *self.kind() {
4395 TypeKind::Void => Ok(c_void(ctx)),
4396 TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)),
4399 TypeKind::Int(ik) => {
4400 Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
4401 }
4402 TypeKind::Float(fk) => {
4403 Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
4404 }
4405 TypeKind::Complex(fk) => {
4406 let float_path =
4407 float_kind_rust_type(ctx, fk, self.layout(ctx));
4408
4409 ctx.generated_bindgen_complex();
4410 Ok(if ctx.options().enable_cxx_namespaces {
4411 syn::parse_quote! { root::__BindgenComplex<#float_path> }
4412 } else {
4413 syn::parse_quote! { __BindgenComplex<#float_path> }
4414 })
4415 }
4416 TypeKind::Function(ref signature) => {
4417 let ty = signature.try_to_rust_ty(ctx, item)?;
4422
4423 let prefix = ctx.trait_prefix();
4424 Ok(syn::parse_quote! { ::#prefix::option::Option<#ty> })
4425 }
4426 TypeKind::Array(item, len) | TypeKind::Vector(item, len) => {
4427 let ty = item.try_to_rust_ty(ctx, &())?;
4428 Ok(syn::parse_quote! { [ #ty ; #len ] })
4429 }
4430 TypeKind::Enum(..) => {
4431 let path = item.namespace_aware_canonical_path(ctx);
4432 let path = proc_macro2::TokenStream::from_str(&path.join("::"))
4433 .unwrap();
4434 Ok(syn::parse_quote!(#path))
4435 }
4436 TypeKind::TemplateInstantiation(ref inst) => {
4437 inst.try_to_rust_ty(ctx, item)
4438 }
4439 TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
4440 TypeKind::TemplateAlias(..) |
4441 TypeKind::Alias(..) |
4442 TypeKind::BlockPointer(..) => {
4443 if self.is_block_pointer() && !ctx.options().generate_block {
4444 let void = c_void(ctx);
4445 return Ok(void.to_ptr(false));
4446 }
4447
4448 if item.is_opaque(ctx, &()) &&
4449 item.used_template_params(ctx)
4450 .into_iter()
4451 .any(|param| param.is_template_param(ctx, &()))
4452 {
4453 self.try_to_opaque(ctx, item)
4454 } else if let Some(ty) = self
4455 .name()
4456 .and_then(|name| utils::type_from_named(ctx, name))
4457 {
4458 Ok(ty)
4459 } else {
4460 utils::build_path(item, ctx)
4461 }
4462 }
4463 TypeKind::Comp(ref info) => {
4464 let template_params = item.all_template_params(ctx);
4465 if info.has_non_type_template_params() ||
4466 (item.is_opaque(ctx, &()) && !template_params.is_empty())
4467 {
4468 return self.try_to_opaque(ctx, item);
4469 }
4470
4471 utils::build_path(item, ctx)
4472 }
4473 TypeKind::Opaque => self.try_to_opaque(ctx, item),
4474 TypeKind::Pointer(inner) | TypeKind::Reference(inner) => {
4475 let size = self.get_layout(ctx, item).size;
4477 if size != ctx.target_pointer_size() {
4478 return Err(Error::InvalidPointerSize {
4479 ty_name: self.name().unwrap_or("unknown").into(),
4480 ty_size: size,
4481 ptr_size: ctx.target_pointer_size(),
4482 });
4483 }
4484
4485 let is_const = ctx.resolve_type(inner).is_const();
4486
4487 let inner =
4488 inner.into_resolver().through_type_refs().resolve(ctx);
4489 let inner_ty = inner.expect_type();
4490
4491 let is_objc_pointer =
4492 matches!(inner_ty.kind(), TypeKind::ObjCInterface(..));
4493
4494 let ty = inner
4498 .to_rust_ty_or_opaque(ctx, &())
4499 .with_implicit_template_params(ctx, inner);
4500
4501 if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer
4504 {
4505 Ok(ty)
4506 } else if ctx.options().generate_cxx_nonnull_references &&
4507 matches!(self.kind(), TypeKind::Reference(_))
4508 {
4509 let prefix = ctx.trait_prefix();
4511 Ok(syn::parse_quote! { ::#prefix::ptr::NonNull<#ty> })
4512 } else {
4513 Ok(ty.to_ptr(is_const))
4514 }
4515 }
4516 TypeKind::TypeParam => {
4517 let name = item.canonical_name(ctx);
4518 let ident = ctx.rust_ident(name);
4519 Ok(syn::parse_quote! { #ident })
4520 }
4521 TypeKind::ObjCSel => Ok(syn::parse_quote! { objc::runtime::Sel }),
4522 TypeKind::ObjCId => Ok(syn::parse_quote! { id }),
4523 TypeKind::ObjCInterface(ref interface) => {
4524 let name = ctx.rust_ident(interface.name());
4525 Ok(syn::parse_quote! { #name })
4526 }
4527 ref u @ TypeKind::UnresolvedTypeRef(..) => {
4528 unreachable!("Should have been resolved after parsing {u:?}!")
4529 }
4530 }
4531 }
4532}
4533
4534impl TryToOpaque for TemplateInstantiation {
4535 type Extra = Item;
4536
4537 fn try_get_layout(
4538 &self,
4539 ctx: &BindgenContext,
4540 item: &Item,
4541 ) -> error::Result<Layout> {
4542 item.expect_type()
4543 .layout(ctx)
4544 .ok_or(Error::NoLayoutForOpaqueBlob)
4545 }
4546}
4547
4548impl TryToRustTy for TemplateInstantiation {
4549 type Extra = Item;
4550
4551 fn try_to_rust_ty(
4552 &self,
4553 ctx: &BindgenContext,
4554 item: &Item,
4555 ) -> error::Result<syn::Type> {
4556 if self.is_opaque(ctx, item) {
4557 return Err(Error::InstantiationOfOpaqueType);
4558 }
4559
4560 let def = self
4561 .template_definition()
4562 .into_resolver()
4563 .through_type_refs()
4564 .resolve(ctx);
4565
4566 let mut ty = quote! {};
4567 let def_path = def.namespace_aware_canonical_path(ctx);
4568 ty.append_separated(
4569 def_path.into_iter().map(|p| ctx.rust_ident(p)),
4570 quote!(::),
4571 );
4572
4573 let def_params = def.self_template_params(ctx);
4574 if def_params.is_empty() {
4575 extra_assert!(def.is_opaque(ctx, &()));
4579 return Err(Error::InstantiationOfOpaqueType);
4580 }
4581
4582 let template_args = self
4591 .template_arguments()
4592 .iter()
4593 .zip(def_params.iter())
4594 .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param))
4597 .map(|(arg, _)| {
4598 let arg = arg.into_resolver().through_type_refs().resolve(ctx);
4599 let ty = arg
4600 .try_to_rust_ty(ctx, &())?
4601 .with_implicit_template_params(ctx, arg);
4602 Ok(ty)
4603 })
4604 .collect::<error::Result<Vec<_>>>()?;
4605
4606 Ok(if template_args.is_empty() {
4607 syn::parse_quote! { #ty }
4608 } else {
4609 syn::parse_quote! { #ty<#(#template_args),*> }
4610 })
4611 }
4612}
4613
4614impl TryToRustTy for FunctionSig {
4615 type Extra = Item;
4616
4617 fn try_to_rust_ty(
4618 &self,
4619 ctx: &BindgenContext,
4620 item: &Item,
4621 ) -> error::Result<syn::Type> {
4622 let ret = utils::fnsig_return_ty(ctx, self);
4624 let arguments = utils::fnsig_arguments(ctx, self);
4625
4626 match self.abi(ctx, None) {
4627 Ok(abi) => Ok(
4628 syn::parse_quote! { unsafe extern #abi fn ( #( #arguments ),* ) #ret },
4629 ),
4630 Err(err) => {
4631 if matches!(err, Error::UnsupportedAbi(_)) {
4632 unsupported_abi_diagnostic(
4633 self.name(),
4634 self.is_variadic(),
4635 item.location(),
4636 ctx,
4637 &err,
4638 );
4639 }
4640
4641 Err(err)
4642 }
4643 }
4644 }
4645}
4646
4647impl CodeGenerator for Function {
4648 type Extra = Item;
4649
4650 type Return = Option<u32>;
4653
4654 fn codegen(
4655 &self,
4656 ctx: &BindgenContext,
4657 result: &mut CodegenResult<'_>,
4658 item: &Item,
4659 ) -> Self::Return {
4660 debug!("<Function as CodeGenerator>::codegen: item = {item:?}");
4661 debug_assert!(item.is_enabled_for_codegen(ctx));
4662
4663 let is_internal = matches!(self.linkage(), Linkage::Internal);
4664
4665 let signature_item = ctx.resolve_item(self.signature());
4666 let signature = signature_item.kind().expect_type().canonical_type(ctx);
4667 let TypeKind::Function(ref signature) = *signature.kind() else {
4668 panic!("Signature kind is not a Function: {signature:?}")
4669 };
4670
4671 if is_internal {
4672 if !ctx.options().wrap_static_fns {
4673 return None;
4676 }
4677
4678 if signature.is_variadic() {
4679 variadic_fn_diagnostic(self.name(), item.location(), ctx);
4682 return None;
4683 }
4684 }
4685
4686 let is_pure_virtual = match self.kind() {
4687 FunctionKind::Method(ref method_kind) => {
4688 method_kind.is_pure_virtual()
4689 }
4690 FunctionKind::Function => false,
4691 };
4692 if is_pure_virtual && !ctx.options().generate_pure_virtual_functions {
4693 return None;
4697 }
4698
4699 let is_dynamic_function = match self.kind() {
4700 FunctionKind::Function => {
4701 ctx.options().dynamic_library_name.is_some()
4702 }
4703 FunctionKind::Method(_) => false,
4704 };
4705
4706 if !item.all_template_params(ctx).is_empty() {
4711 return None;
4712 }
4713
4714 let name = self.name();
4715 let mut canonical_name = item.canonical_name(ctx);
4716 let mangled_name = self.mangled_name();
4717
4718 {
4719 let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);
4720
4721 if result.seen_function(seen_symbol_name) {
4724 return None;
4725 }
4726 result.saw_function(seen_symbol_name);
4727 }
4728
4729 let mut attributes = vec![];
4730
4731 if true {
4732 let must_use = signature.must_use() || {
4733 let ret_ty = signature
4734 .return_type()
4735 .into_resolver()
4736 .through_type_refs()
4737 .resolve(ctx);
4738 ret_ty.must_use(ctx)
4739 };
4740
4741 if must_use {
4742 attributes.push(attributes::must_use());
4743 }
4744 }
4745
4746 if let Some(comment) = item.comment(ctx) {
4747 attributes.push(attributes::doc(&comment));
4748 }
4749
4750 let abi = match signature.abi(ctx, Some(name)) {
4751 Err(err) => {
4752 if matches!(err, Error::UnsupportedAbi(_)) {
4753 unsupported_abi_diagnostic(
4754 name,
4755 signature.is_variadic(),
4756 item.location(),
4757 ctx,
4758 &err,
4759 );
4760 }
4761
4762 return None;
4763 }
4764 Ok(ClangAbi::Unknown(unknown_abi)) => {
4765 panic!(
4766 "Invalid or unknown abi {unknown_abi:?} for function {canonical_name:?} ({self:?})"
4767 );
4768 }
4769 Ok(abi) => abi,
4770 };
4771
4772 let times_seen = result.overload_number(&canonical_name);
4775 if times_seen > 0 {
4776 write!(&mut canonical_name, "{times_seen}").unwrap();
4777 }
4778 utils::call_discovered_item_callback(ctx, item, || {
4779 DiscoveredItem::Function {
4780 final_name: canonical_name.clone(),
4781 }
4782 });
4783
4784 let link_name_attr = self.link_name().or_else(|| {
4785 let mangled_name = mangled_name.unwrap_or(name);
4786 (!utils::names_will_be_identical_after_mangling(
4787 &canonical_name,
4788 mangled_name,
4789 Some(abi),
4790 ))
4791 .then_some(mangled_name)
4792 });
4793
4794 if let Some(link_name) = link_name_attr {
4795 if !is_dynamic_function {
4796 attributes.push(attributes::link_name::<false>(link_name));
4797 }
4798 }
4799
4800 let mut block_attributes = quote! {};
4801 for attr in &ctx.options().extern_fn_block_attrs {
4802 let parsed_attr = proc_macro2::TokenStream::from_str(attr).unwrap_or_else(
4803 |err| {
4804 panic!(
4805 "Error parsing extern fn block attribute `{attr}`: {err}"
4806 )
4807 },
4808 );
4809 block_attributes.extend(quote! {
4810 #parsed_attr
4811 });
4812 }
4813
4814 let should_wrap = is_internal &&
4815 ctx.options().wrap_static_fns &&
4816 link_name_attr.is_none();
4817
4818 if should_wrap {
4819 let name = canonical_name.clone() + ctx.wrap_static_fns_suffix();
4820 attributes.push(attributes::link_name::<true>(&name));
4821 }
4822
4823 let wrap_as_variadic = if should_wrap && !signature.is_variadic() {
4824 utils::wrap_as_variadic_fn(ctx, signature, name)
4825 } else {
4826 None
4827 };
4828
4829 let (ident, args) = if let Some(WrapAsVariadic {
4830 idx_of_va_list_arg,
4831 new_name,
4832 }) = &wrap_as_variadic
4833 {
4834 (
4835 new_name,
4836 utils::fnsig_arguments_iter(
4837 ctx,
4838 signature.argument_types().iter().enumerate().filter_map(
4840 |(idx, t)| {
4841 if idx == *idx_of_va_list_arg {
4842 None
4843 } else {
4844 Some(t)
4845 }
4846 },
4847 ),
4848 true,
4850 ),
4851 )
4852 } else {
4853 (&canonical_name, utils::fnsig_arguments(ctx, signature))
4854 };
4855 let ret = utils::fnsig_return_ty(ctx, signature);
4856
4857 let ident = ctx.rust_ident(ident);
4858
4859 let safety = ctx
4860 .options()
4861 .rust_features
4862 .unsafe_extern_blocks
4863 .then(|| quote!(unsafe));
4864
4865 let tokens = quote! {
4866 #block_attributes
4867 #safety extern #abi {
4868 #(#attributes)*
4869 pub fn #ident ( #( #args ),* ) #ret;
4870 }
4871 };
4872
4873 if should_wrap {
4875 result
4876 .items_to_serialize
4877 .push((item.id(), wrap_as_variadic));
4878 }
4879
4880 if is_dynamic_function {
4882 let ident_str = ident.to_string();
4883 let symbol = link_name_attr.unwrap_or(&ident_str);
4884 let args_identifiers =
4885 utils::fnsig_argument_identifiers(ctx, signature);
4886 let ret_ty = utils::fnsig_return_ty(ctx, signature);
4887 result.dynamic_items().push_func(
4888 &ident,
4889 symbol,
4890 abi,
4891 signature.is_variadic(),
4892 ctx.options().dynamic_link_require_all,
4893 &args,
4894 &args_identifiers,
4895 &ret,
4896 &ret_ty,
4897 &attributes,
4898 ctx,
4899 );
4900 } else {
4901 result.push(tokens);
4902 }
4903 Some(times_seen)
4904 }
4905}
4906
4907#[cfg_attr(not(feature = "experimental"), allow(unused_variables))]
4908fn unsupported_abi_diagnostic(
4909 fn_name: &str,
4910 variadic: bool,
4911 location: Option<&crate::clang::SourceLocation>,
4912 ctx: &BindgenContext,
4913 error: &Error,
4914) {
4915 warn!(
4916 "Skipping {}function `{fn_name}` because the {error}",
4917 if variadic { "variadic " } else { "" },
4918 );
4919
4920 #[cfg(feature = "experimental")]
4921 if ctx.options().emit_diagnostics {
4922 use crate::diagnostics::{get_line, Diagnostic, Level, Slice};
4923
4924 let mut diag = Diagnostic::default();
4925 diag.with_title(
4926 format!(
4927 "Skipping {}function `{fn_name}` because the {error}",
4928 if variadic { "variadic " } else { "" },
4929 ),
4930 Level::Warning,
4931 )
4932 .add_annotation(
4933 "No code will be generated for this function.",
4934 Level::Warning,
4935 )
4936 .add_annotation(
4937 format!(
4938 "The configured Rust version is {}.",
4939 ctx.options().rust_target
4940 ),
4941 Level::Note,
4942 );
4943
4944 if let Some(loc) = location {
4945 let (file, line, col, _) = loc.location();
4946
4947 if let Some(filename) = file.name() {
4948 if let Ok(Some(source)) = get_line(&filename, line) {
4949 let mut slice = Slice::default();
4950 slice
4951 .with_source(source)
4952 .with_location(filename, line, col);
4953 diag.add_slice(slice);
4954 }
4955 }
4956 }
4957
4958 diag.display();
4959 }
4960}
4961
4962fn variadic_fn_diagnostic(
4963 fn_name: &str,
4964 _location: Option<&crate::clang::SourceLocation>,
4965 _ctx: &BindgenContext,
4966) {
4967 warn!(
4968 "Cannot generate wrapper for the static variadic function `{fn_name}`."
4969 );
4970
4971 #[cfg(feature = "experimental")]
4972 if _ctx.options().emit_diagnostics {
4973 use crate::diagnostics::{get_line, Diagnostic, Level, Slice};
4974
4975 let mut diag = Diagnostic::default();
4976
4977 diag.with_title(format!("Cannot generate wrapper for the static function `{fn_name}`."), Level::Warning)
4978 .add_annotation("The `--wrap-static-fns` feature does not support variadic functions.", Level::Note)
4979 .add_annotation("No code will be generated for this function.", Level::Note);
4980
4981 if let Some(loc) = _location {
4982 let (file, line, col, _) = loc.location();
4983
4984 if let Some(filename) = file.name() {
4985 if let Ok(Some(source)) = get_line(&filename, line) {
4986 let mut slice = Slice::default();
4987 slice
4988 .with_source(source)
4989 .with_location(filename, line, col);
4990 diag.add_slice(slice);
4991 }
4992 }
4993 }
4994
4995 diag.display();
4996 }
4997}
4998
4999fn objc_method_codegen(
5000 ctx: &BindgenContext,
5001 method: &ObjCMethod,
5002 methods: &mut Vec<proc_macro2::TokenStream>,
5003 class_name: Option<&str>,
5004 rust_class_name: &str,
5005 prefix: &str,
5006) {
5007 let name = format!("{rust_class_name}::{prefix}{}", method.rust_name());
5011 if ctx.options().blocklisted_items.matches(name) {
5012 return;
5013 }
5014
5015 let signature = method.signature();
5016 let fn_args = utils::fnsig_arguments(ctx, signature);
5017 let fn_ret = utils::fnsig_return_ty(ctx, signature);
5018
5019 let sig = if method.is_class_method() {
5020 quote! {
5021 ( #( #fn_args ),* ) #fn_ret
5022 }
5023 } else {
5024 let self_arr = [quote! { &self }];
5025 let args = self_arr.iter().chain(fn_args.iter());
5026 quote! {
5027 ( #( #args ),* ) #fn_ret
5028 }
5029 };
5030
5031 let methods_and_args = method.format_method_call(&fn_args);
5032
5033 let body = {
5034 let body = if method.is_class_method() {
5035 let class_name = ctx.rust_ident(
5036 class_name
5037 .expect("Generating a class method without class name?"),
5038 );
5039 quote!(msg_send!(class!(#class_name), #methods_and_args))
5040 } else {
5041 quote!(msg_send!(*self, #methods_and_args))
5042 };
5043
5044 ctx.wrap_unsafe_ops(body)
5045 };
5046
5047 let method_name = ctx.rust_ident(format!("{prefix}{}", method.rust_name()));
5048
5049 methods.push(quote! {
5050 unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
5051 #body
5052 }
5053 });
5054}
5055
5056impl CodeGenerator for ObjCInterface {
5057 type Extra = Item;
5058 type Return = ();
5059
5060 fn codegen(
5061 &self,
5062 ctx: &BindgenContext,
5063 result: &mut CodegenResult<'_>,
5064 item: &Item,
5065 ) {
5066 debug_assert!(item.is_enabled_for_codegen(ctx));
5067
5068 let mut impl_items = vec![];
5069 let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::");
5070
5071 for method in self.methods() {
5072 objc_method_codegen(
5073 ctx,
5074 method,
5075 &mut impl_items,
5076 None,
5077 &rust_class_name,
5078 "",
5079 );
5080 }
5081
5082 for class_method in self.class_methods() {
5083 let ambiquity = self
5084 .methods()
5085 .iter()
5086 .map(|m| m.rust_name())
5087 .any(|x| x == class_method.rust_name());
5088 let prefix = if ambiquity { "class_" } else { "" };
5089 objc_method_codegen(
5090 ctx,
5091 class_method,
5092 &mut impl_items,
5093 Some(self.name()),
5094 &rust_class_name,
5095 prefix,
5096 );
5097 }
5098
5099 let trait_name = ctx.rust_ident(self.rust_name());
5100 let trait_constraints = quote! {
5101 Sized + std::ops::Deref
5102 };
5103 let trait_block = if self.is_template() {
5104 let template_names: Vec<Ident> = self
5105 .template_names
5106 .iter()
5107 .map(|g| ctx.rust_ident(g))
5108 .collect();
5109
5110 quote! {
5111 pub trait #trait_name <#(#template_names:'static),*> : #trait_constraints {
5112 #( #impl_items )*
5113 }
5114 }
5115 } else {
5116 quote! {
5117 pub trait #trait_name : #trait_constraints {
5118 #( #impl_items )*
5119 }
5120 }
5121 };
5122
5123 let class_name = ctx.rust_ident(self.name());
5124 if !self.is_category() && !self.is_protocol() {
5125 let struct_block = quote! {
5126 #[repr(transparent)]
5127 #[derive(Debug, Copy, Clone)]
5128 pub struct #class_name(pub id);
5129 impl std::ops::Deref for #class_name {
5130 type Target = objc::runtime::Object;
5131 fn deref(&self) -> &Self::Target {
5132 unsafe {
5133 &*self.0
5134 }
5135 }
5136 }
5137 unsafe impl objc::Message for #class_name { }
5138 impl #class_name {
5139 pub fn alloc() -> Self {
5140 Self(unsafe {
5141 msg_send!(class!(#class_name), alloc)
5142 })
5143 }
5144 }
5145 };
5146 result.push(struct_block);
5147 let mut protocol_set: HashSet<ItemId> = Default::default();
5148 for protocol_id in &self.conforms_to {
5149 protocol_set.insert(*protocol_id);
5150 let protocol_name = ctx.rust_ident(
5151 ctx.resolve_type(protocol_id.expect_type_id(ctx))
5152 .name()
5153 .unwrap(),
5154 );
5155 let impl_trait = quote! {
5156 impl #protocol_name for #class_name { }
5157 };
5158 result.push(impl_trait);
5159 }
5160 let mut parent_class = self.parent_class;
5161 while let Some(parent_id) = parent_class {
5162 let parent = parent_id
5163 .expect_type_id(ctx)
5164 .into_resolver()
5165 .through_type_refs()
5166 .resolve(ctx)
5167 .expect_type()
5168 .kind();
5169
5170 let TypeKind::ObjCInterface(parent) = parent else {
5171 break;
5172 };
5173 parent_class = parent.parent_class;
5174
5175 let parent_name = ctx.rust_ident(parent.rust_name());
5176 let impl_trait = if parent.is_template() {
5177 let template_names: Vec<Ident> = parent
5178 .template_names
5179 .iter()
5180 .map(|g| ctx.rust_ident(g))
5181 .collect();
5182 quote! {
5183 impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name {
5184 }
5185 }
5186 } else {
5187 quote! {
5188 impl #parent_name for #class_name { }
5189 }
5190 };
5191 result.push(impl_trait);
5192 for protocol_id in &parent.conforms_to {
5193 if protocol_set.insert(*protocol_id) {
5194 let protocol_name = ctx.rust_ident(
5195 ctx.resolve_type(protocol_id.expect_type_id(ctx))
5196 .name()
5197 .unwrap(),
5198 );
5199 let impl_trait = quote! {
5200 impl #protocol_name for #class_name { }
5201 };
5202 result.push(impl_trait);
5203 }
5204 }
5205 if !parent.is_template() {
5206 let parent_struct_name = parent.name();
5207 let child_struct_name = self.name();
5208 let parent_struct = ctx.rust_ident(parent_struct_name);
5209 let from_block = quote! {
5210 impl From<#class_name> for #parent_struct {
5211 fn from(child: #class_name) -> #parent_struct {
5212 #parent_struct(child.0)
5213 }
5214 }
5215 };
5216 result.push(from_block);
5217
5218 let error_msg = format!(
5219 "This {parent_struct_name} cannot be downcasted to {child_struct_name}"
5220 );
5221 let try_into_block = quote! {
5222 impl std::convert::TryFrom<#parent_struct> for #class_name {
5223 type Error = &'static str;
5224 fn try_from(parent: #parent_struct) -> Result<#class_name, Self::Error> {
5225 let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))};
5226 if is_kind_of {
5227 Ok(#class_name(parent.0))
5228 } else {
5229 Err(#error_msg)
5230 }
5231 }
5232 }
5233 };
5234 result.push(try_into_block);
5235 }
5236 }
5237 }
5238
5239 if !self.is_protocol() {
5240 let impl_block = if self.is_template() {
5241 let template_names: Vec<Ident> = self
5242 .template_names
5243 .iter()
5244 .map(|g| ctx.rust_ident(g))
5245 .collect();
5246 quote! {
5247 impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #class_name {
5248 }
5249 }
5250 } else {
5251 quote! {
5252 impl #trait_name for #class_name {
5253 }
5254 }
5255 };
5256 result.push(impl_block);
5257 }
5258
5259 result.push(trait_block);
5260 result.saw_objc();
5261 }
5262}
5263
5264pub(crate) fn codegen(
5265 context: BindgenContext,
5266) -> Result<(proc_macro2::TokenStream, BindgenOptions), CodegenError> {
5267 context.gen(|context| {
5268 let _t = context.timer("codegen");
5269 let counter = Cell::new(0);
5270 let mut result = CodegenResult::new(&counter);
5271
5272 debug!("codegen: {:?}", context.options());
5273
5274 if context.options().emit_ir {
5275 let codegen_items = context.codegen_items();
5276 for (id, item) in context.items() {
5277 if codegen_items.contains(&id) {
5278 println!("ir: {id:?} = {item:#?}");
5279 }
5280 }
5281 }
5282
5283 if let Some(path) = context.options().emit_ir_graphviz.as_ref() {
5284 match dot::write_dot_file(context, path) {
5285 Ok(()) => info!(
5286 "Your dot file was generated successfully into: {path}"
5287 ),
5288 Err(e) => warn!("{e}"),
5289 }
5290 }
5291
5292 if let Some(spec) = context.options().depfile.as_ref() {
5293 match spec.write(context.deps()) {
5294 Ok(()) => info!(
5295 "Your depfile was generated successfully into: {}",
5296 spec.depfile_path.display()
5297 ),
5298 Err(e) => warn!("{e}"),
5299 }
5300 }
5301
5302 context.resolve_item(context.root_module()).codegen(
5303 context,
5304 &mut result,
5305 &(),
5306 );
5307
5308 if let Some(ref lib_name) = context.options().dynamic_library_name {
5309 let lib_ident = context.rust_ident(lib_name);
5310 let dynamic_items_tokens =
5311 result.dynamic_items().get_tokens(&lib_ident, context);
5312 result.push(dynamic_items_tokens);
5313 }
5314
5315 utils::serialize_items(&result, context)?;
5316
5317 Ok(postprocessing::postprocessing(
5318 result.items,
5319 context.options(),
5320 ))
5321 })
5322}
5323
5324pub(crate) mod utils {
5325 use super::helpers::BITFIELD_UNIT;
5326 use super::serialize::CSerialize;
5327 use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
5328 use crate::callbacks::DiscoveredItemId;
5329 use crate::ir::context::BindgenContext;
5330 use crate::ir::context::TypeId;
5331 use crate::ir::function::{Abi, ClangAbi, FunctionSig};
5332 use crate::ir::item::{Item, ItemCanonicalPath};
5333 use crate::ir::ty::TypeKind;
5334 use crate::{args_are_cpp, file_is_cpp};
5335 use std::borrow::Cow;
5336 use std::io::Write;
5337 use std::mem;
5338 use std::path::PathBuf;
5339 use std::str::FromStr;
5340
5341 pub(super) fn serialize_items(
5342 result: &CodegenResult,
5343 context: &BindgenContext,
5344 ) -> Result<(), CodegenError> {
5345 if result.items_to_serialize.is_empty() {
5346 return Ok(());
5347 }
5348
5349 let path = context.options().wrap_static_fns_path.as_ref().map_or_else(
5350 || std::env::temp_dir().join("bindgen").join("extern"),
5351 PathBuf::from,
5352 );
5353
5354 let dir = path.parent().unwrap();
5355
5356 if !dir.exists() {
5357 std::fs::create_dir_all(dir)?;
5358 }
5359
5360 let is_cpp = args_are_cpp(&context.options().clang_args) ||
5361 context
5362 .options()
5363 .input_headers
5364 .iter()
5365 .any(|h| file_is_cpp(h));
5366
5367 let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" });
5368
5369 let mut code = Vec::new();
5370
5371 if !context.options().input_headers.is_empty() {
5372 for header in &context.options().input_headers {
5373 writeln!(code, "#include \"{header}\"")?;
5374 }
5375
5376 writeln!(code)?;
5377 }
5378
5379 if !context.options().input_header_contents.is_empty() {
5380 for (name, contents) in &context.options().input_header_contents {
5381 writeln!(code, "// {name}\n{contents}")?;
5382 }
5383
5384 writeln!(code)?;
5385 }
5386
5387 writeln!(code, "// Static wrappers\n")?;
5388
5389 for (id, wrap_as_variadic) in &result.items_to_serialize {
5390 let item = context.resolve_item(*id);
5391 item.serialize(context, wrap_as_variadic, &mut vec![], &mut code)?;
5392 }
5393
5394 std::fs::write(source_path, code)?;
5395
5396 Ok(())
5397 }
5398
5399 pub(super) fn wrap_as_variadic_fn(
5400 ctx: &BindgenContext,
5401 signature: &FunctionSig,
5402 name: &str,
5403 ) -> Option<super::WrapAsVariadic> {
5404 if signature.argument_types().len() <= 1 {
5408 return None;
5409 }
5410
5411 let mut it = signature.argument_types().iter().enumerate().filter_map(
5412 |(idx, (_name, mut type_id))| {
5413 loop {
5415 let ty = ctx.resolve_type(type_id);
5416 if Some("__builtin_va_list") == ty.name() {
5417 return Some(idx);
5418 }
5419 match ty.kind() {
5420 TypeKind::Alias(type_id_alias) => {
5421 type_id = *type_id_alias;
5422 }
5423 TypeKind::ResolvedTypeRef(type_id_typedef) => {
5424 type_id = *type_id_typedef;
5425 }
5426 _ => break,
5427 }
5428 }
5429 None
5430 },
5431 );
5432
5433 it.next().filter(|_| it.next().is_none()).and_then(|idx| {
5436 #[cfg(feature = "experimental")]
5438 {
5439 ctx.options()
5440 .last_callback(|c| c.wrap_as_variadic_fn(name))
5441 .map(|new_name| super::WrapAsVariadic {
5442 new_name,
5443 idx_of_va_list_arg: idx,
5444 })
5445 }
5446 #[cfg(not(feature = "experimental"))]
5447 {
5448 let _ = name;
5449 let _ = idx;
5450 None
5451 }
5452 })
5453 }
5454
5455 pub(crate) fn prepend_bitfield_unit_type(
5456 ctx: &BindgenContext,
5457 result: &mut Vec<proc_macro2::TokenStream>,
5458 ) {
5459 if ctx.options().blocklisted_items.matches(BITFIELD_UNIT) ||
5460 ctx.options().blocklisted_types.matches(BITFIELD_UNIT)
5461 {
5462 return;
5463 }
5464
5465 let bitfield_unit_src = include_str!("./bitfield_unit.rs");
5466 let bitfield_unit_src = if true {
5467 Cow::Borrowed(bitfield_unit_src)
5468 } else {
5469 Cow::Owned(bitfield_unit_src.replace("const fn ", "fn "))
5470 };
5471 let bitfield_unit_type =
5472 proc_macro2::TokenStream::from_str(&bitfield_unit_src).unwrap();
5473 let bitfield_unit_type = quote!(#bitfield_unit_type);
5474
5475 let items = vec![bitfield_unit_type];
5476 let old_items = mem::replace(result, items);
5477 result.extend(old_items);
5478 }
5479
5480 pub(crate) fn prepend_objc_header(
5481 ctx: &BindgenContext,
5482 result: &mut Vec<proc_macro2::TokenStream>,
5483 ) {
5484 let use_objc = if ctx.options().objc_extern_crate {
5485 quote! {
5486 #[macro_use]
5487 extern crate objc;
5488 }
5489 } else {
5490 quote! {
5491 use objc::{self, msg_send, sel, sel_impl, class};
5492 }
5493 };
5494
5495 let id_type = quote! {
5496 #[allow(non_camel_case_types)]
5497 pub type id = *mut objc::runtime::Object;
5498 };
5499
5500 let items = vec![use_objc, id_type];
5501 let old_items = mem::replace(result, items);
5502 result.extend(old_items);
5503 }
5504
5505 pub(crate) fn prepend_block_header(
5506 ctx: &BindgenContext,
5507 result: &mut Vec<proc_macro2::TokenStream>,
5508 ) {
5509 let use_block = if ctx.options().block_extern_crate {
5510 quote! {
5511 extern crate block;
5512 }
5513 } else {
5514 quote! {
5515 use block;
5516 }
5517 };
5518
5519 let items = vec![use_block];
5520 let old_items = mem::replace(result, items);
5521 result.extend(old_items);
5522 }
5523
5524 pub(crate) fn prepend_union_types(
5525 ctx: &BindgenContext,
5526 result: &mut Vec<proc_macro2::TokenStream>,
5527 ) {
5528 let prefix = ctx.trait_prefix();
5529
5530 let union_field_decl = quote! {
5533 #[repr(C)]
5534 pub struct __BindgenUnionField<T>(::#prefix::marker::PhantomData<T>);
5535 };
5536
5537 let transmute = quote!(unsafe { ::#prefix::mem::transmute(self) });
5538
5539 let union_field_impl = quote! {
5540 impl<T> __BindgenUnionField<T> {
5541 #[inline]
5542 pub const fn new() -> Self {
5543 __BindgenUnionField(::#prefix::marker::PhantomData)
5544 }
5545
5546 #[inline]
5547 pub const unsafe fn as_ref(&self) -> &T {
5548 #transmute
5549 }
5550
5551 #[inline]
5552 pub const unsafe fn as_mut(&mut self) -> &mut T {
5553 #transmute
5554 }
5555 }
5556 };
5557
5558 let union_field_default_impl = quote! {
5559 impl<T> ::#prefix::default::Default for __BindgenUnionField<T> {
5560 #[inline]
5561 fn default() -> Self {
5562 Self::new()
5563 }
5564 }
5565 };
5566
5567 let union_field_clone_impl = quote! {
5568 impl<T> ::#prefix::clone::Clone for __BindgenUnionField<T> {
5569 #[inline]
5570 fn clone(&self) -> Self {
5571 *self
5572 }
5573 }
5574 };
5575
5576 let union_field_copy_impl = quote! {
5577 impl<T> ::#prefix::marker::Copy for __BindgenUnionField<T> {}
5578 };
5579
5580 let union_field_debug_impl = quote! {
5581 impl<T> ::#prefix::fmt::Debug for __BindgenUnionField<T> {
5582 fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
5583 -> ::#prefix::fmt::Result {
5584 fmt.write_str("__BindgenUnionField")
5585 }
5586 }
5587 };
5588
5589 let union_field_hash_impl = quote! {
5592 impl<T> ::#prefix::hash::Hash for __BindgenUnionField<T> {
5593 fn hash<H: ::#prefix::hash::Hasher>(&self, _state: &mut H) {
5594 }
5595 }
5596 };
5597
5598 let union_field_partialeq_impl = quote! {
5599 impl<T> ::#prefix::cmp::PartialEq for __BindgenUnionField<T> {
5600 fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
5601 true
5602 }
5603 }
5604 };
5605
5606 let union_field_eq_impl = quote! {
5607 impl<T> ::#prefix::cmp::Eq for __BindgenUnionField<T> {
5608 }
5609 };
5610
5611 let items = vec![
5612 union_field_decl,
5613 union_field_impl,
5614 union_field_default_impl,
5615 union_field_clone_impl,
5616 union_field_copy_impl,
5617 union_field_debug_impl,
5618 union_field_hash_impl,
5619 union_field_partialeq_impl,
5620 union_field_eq_impl,
5621 ];
5622
5623 let old_items = mem::replace(result, items);
5624 result.extend(old_items);
5625 }
5626
5627 pub(crate) fn prepend_incomplete_array_types(
5628 ctx: &BindgenContext,
5629 result: &mut Vec<proc_macro2::TokenStream>,
5630 ) {
5631 let prefix = ctx.trait_prefix();
5632
5633 let const_fn = if true {
5636 quote! { const fn }
5637 } else {
5638 quote! { fn }
5639 };
5640
5641 let incomplete_array_decl = quote! {
5642 #[repr(C)]
5643 #[derive(Default)]
5644 pub struct __IncompleteArrayField<T>(
5645 ::#prefix::marker::PhantomData<T>, [T; 0]);
5646 };
5647
5648 let from_raw_parts = ctx.wrap_unsafe_ops(quote! (
5649 ::#prefix::slice::from_raw_parts(self.as_ptr(), len)
5650 ));
5651 let from_raw_parts_mut = ctx.wrap_unsafe_ops(quote! (
5652 ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
5653 ));
5654
5655 let incomplete_array_impl = quote! {
5656 impl<T> __IncompleteArrayField<T> {
5657 #[inline]
5658 pub #const_fn new() -> Self {
5659 __IncompleteArrayField(::#prefix::marker::PhantomData, [])
5660 }
5661
5662 #[inline]
5663 pub fn as_ptr(&self) -> *const T {
5664 self as *const _ as *const T
5665 }
5666
5667 #[inline]
5668 pub fn as_mut_ptr(&mut self) -> *mut T {
5669 self as *mut _ as *mut T
5670 }
5671
5672 #[inline]
5673 pub unsafe fn as_slice(&self, len: usize) -> &[T] {
5674 #from_raw_parts
5675 }
5676
5677 #[inline]
5678 pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
5679 #from_raw_parts_mut
5680 }
5681 }
5682 };
5683
5684 let incomplete_array_debug_impl = quote! {
5685 impl<T> ::#prefix::fmt::Debug for __IncompleteArrayField<T> {
5686 fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
5687 -> ::#prefix::fmt::Result {
5688 fmt.write_str("__IncompleteArrayField")
5689 }
5690 }
5691 };
5692
5693 let items = vec![
5694 incomplete_array_decl,
5695 incomplete_array_impl,
5696 incomplete_array_debug_impl,
5697 ];
5698
5699 let old_items = mem::replace(result, items);
5700 result.extend(old_items);
5701 }
5702
5703 pub(crate) fn prepend_float16_type(
5704 result: &mut Vec<proc_macro2::TokenStream>,
5705 ) {
5706 let float16_type = quote! {
5707 #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5708 #[repr(transparent)]
5709 pub struct __BindgenFloat16(pub u16);
5710 };
5711
5712 let items = vec![float16_type];
5713 let old_items = mem::replace(result, items);
5714 result.extend(old_items);
5715 }
5716
5717 pub(crate) fn prepend_complex_type(
5718 result: &mut Vec<proc_macro2::TokenStream>,
5719 ) {
5720 let complex_type = quote! {
5721 #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5722 #[repr(C)]
5723 pub struct __BindgenComplex<T> {
5724 pub re: T,
5725 pub im: T
5726 }
5727 };
5728
5729 let items = vec![complex_type];
5730 let old_items = mem::replace(result, items);
5731 result.extend(old_items);
5732 }
5733
5734 pub(crate) fn prepend_opaque_array_types(
5735 ctx: &BindgenContext,
5736 result: &mut Vec<proc_macro2::TokenStream>,
5737 ) {
5738 let mut tys = vec![];
5739 for align in ctx.opaque_array_types_needed() {
5742 let ident = if align == 1 {
5743 format_ident!("__BindgenOpaqueArray")
5744 } else {
5745 format_ident!("__BindgenOpaqueArray{align}")
5746 };
5747 let repr = if align <= 1 {
5748 quote! { #[repr(C)] }
5749 } else {
5750 let explicit = super::helpers::ast_ty::int_expr(align as i64);
5751 quote! { #[repr(C, align(#explicit))] }
5752 };
5753 tys.push(quote! {
5754 #[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
5755 #repr
5756 pub struct #ident<T>(pub T);
5757 impl<T: Copy + Default, const N: usize> Default for #ident<[T; N]> {
5758 fn default() -> Self {
5759 Self([<T as Default>::default(); N])
5760 }
5761 }
5762 });
5763 }
5764 result.splice(0..0, tys);
5765 }
5766
5767 pub(crate) fn build_path(
5768 item: &Item,
5769 ctx: &BindgenContext,
5770 ) -> error::Result<syn::Type> {
5771 let path = item.namespace_aware_canonical_path(ctx);
5772 let tokens =
5773 proc_macro2::TokenStream::from_str(&path.join("::")).unwrap();
5774
5775 Ok(syn::parse_quote! { #tokens })
5776 }
5777
5778 fn primitive_ty(ctx: &BindgenContext, name: &str) -> syn::Type {
5779 let ident = ctx.rust_ident_raw(name);
5780 syn::parse_quote! { #ident }
5781 }
5782
5783 pub(crate) fn type_from_named(
5784 ctx: &BindgenContext,
5785 name: &str,
5786 ) -> Option<syn::Type> {
5787 Some(match name {
5790 "int8_t" => primitive_ty(ctx, "i8"),
5791 "uint8_t" => primitive_ty(ctx, "u8"),
5792 "int16_t" => primitive_ty(ctx, "i16"),
5793 "uint16_t" => primitive_ty(ctx, "u16"),
5794 "int32_t" => primitive_ty(ctx, "i32"),
5795 "uint32_t" => primitive_ty(ctx, "u32"),
5796 "int64_t" => primitive_ty(ctx, "i64"),
5797 "uint64_t" => primitive_ty(ctx, "u64"),
5798
5799 "size_t" if ctx.options().size_t_is_usize => {
5800 primitive_ty(ctx, "usize")
5801 }
5802 "uintptr_t" => primitive_ty(ctx, "usize"),
5803
5804 "ssize_t" if ctx.options().size_t_is_usize => {
5805 primitive_ty(ctx, "isize")
5806 }
5807 "intptr_t" | "ptrdiff_t" => primitive_ty(ctx, "isize"),
5808 _ => return None,
5809 })
5810 }
5811
5812 fn fnsig_return_ty_internal(
5813 ctx: &BindgenContext,
5814 sig: &FunctionSig,
5815 ) -> syn::Type {
5816 if sig.is_divergent() {
5817 return syn::parse_quote! { ! };
5818 }
5819
5820 let canonical_type_kind = sig
5821 .return_type()
5822 .into_resolver()
5823 .through_type_refs()
5824 .through_type_aliases()
5825 .resolve(ctx)
5826 .kind()
5827 .expect_type()
5828 .kind();
5829
5830 match canonical_type_kind {
5831 TypeKind::Void => syn::parse_quote! { () },
5832 _ => sig.return_type().to_rust_ty_or_opaque(ctx, &()),
5833 }
5834 }
5835
5836 pub(crate) fn fnsig_return_ty(
5837 ctx: &BindgenContext,
5838 sig: &FunctionSig,
5839 ) -> proc_macro2::TokenStream {
5840 match fnsig_return_ty_internal(ctx, sig) {
5841 syn::Type::Tuple(syn::TypeTuple { elems, .. })
5842 if elems.is_empty() =>
5843 {
5844 quote! {}
5845 }
5846 ty => quote! { -> #ty },
5847 }
5848 }
5849
5850 pub(crate) fn fnsig_argument_type(
5851 ctx: &BindgenContext,
5852 ty: TypeId,
5853 ) -> syn::Type {
5854 use super::ToPtr;
5855
5856 let arg_item = ctx.resolve_item(ty);
5857 let arg_ty = arg_item.kind().expect_type();
5858
5859 match *arg_ty.canonical_type(ctx).kind() {
5868 TypeKind::Array(t, _) => {
5869 let stream = if ctx.options().array_pointers_in_arguments {
5870 arg_ty.to_rust_ty_or_opaque(ctx, arg_item)
5871 } else {
5872 t.to_rust_ty_or_opaque(ctx, &())
5873 };
5874 stream
5875 .to_ptr(ctx.resolve_type(t).is_const() || arg_ty.is_const())
5876 }
5877 TypeKind::Pointer(inner) => {
5878 let inner = ctx.resolve_item(inner);
5879 let inner_ty = inner.expect_type();
5880 if let TypeKind::ObjCInterface(ref interface) =
5881 *inner_ty.canonical_type(ctx).kind()
5882 {
5883 let name = ctx.rust_ident(interface.name());
5884 syn::parse_quote! { #name }
5885 } else {
5886 arg_item.to_rust_ty_or_opaque(ctx, &())
5887 }
5888 }
5889 _ => arg_item.to_rust_ty_or_opaque(ctx, &()),
5890 }
5891 }
5892
5893 pub(crate) fn fnsig_arguments_iter<
5894 'a,
5895 I: Iterator<Item = &'a (Option<String>, TypeId)>,
5896 >(
5897 ctx: &BindgenContext,
5898 args_iter: I,
5899 is_variadic: bool,
5900 ) -> Vec<proc_macro2::TokenStream> {
5901 let mut unnamed_arguments = 0;
5902 let mut args = args_iter
5903 .map(|(name, ty)| {
5904 let arg_ty = fnsig_argument_type(ctx, *ty);
5905
5906 let arg_name = if let Some(ref name) = *name {
5907 ctx.rust_mangle(name).into_owned()
5908 } else {
5909 unnamed_arguments += 1;
5910 format!("arg{unnamed_arguments}")
5911 };
5912
5913 assert!(!arg_name.is_empty());
5914 let arg_name = ctx.rust_ident(arg_name);
5915
5916 quote! {
5917 #arg_name : #arg_ty
5918 }
5919 })
5920 .collect::<Vec<_>>();
5921
5922 if is_variadic {
5923 args.push(quote! { ... });
5924 }
5925
5926 args
5927 }
5928
5929 pub(crate) fn fnsig_arguments(
5930 ctx: &BindgenContext,
5931 sig: &FunctionSig,
5932 ) -> Vec<proc_macro2::TokenStream> {
5933 fnsig_arguments_iter(
5934 ctx,
5935 sig.argument_types().iter(),
5936 sig.is_variadic(),
5937 )
5938 }
5939
5940 pub(crate) fn fnsig_argument_identifiers(
5941 ctx: &BindgenContext,
5942 sig: &FunctionSig,
5943 ) -> Vec<proc_macro2::TokenStream> {
5944 let mut unnamed_arguments = 0;
5945 let args = sig
5946 .argument_types()
5947 .iter()
5948 .map(|&(ref name, _ty)| {
5949 let arg_name = if let Some(ref name) = *name {
5950 ctx.rust_mangle(name).into_owned()
5951 } else {
5952 unnamed_arguments += 1;
5953 format!("arg{unnamed_arguments}")
5954 };
5955
5956 assert!(!arg_name.is_empty());
5957 let arg_name = ctx.rust_ident(arg_name);
5958
5959 quote! {
5960 #arg_name
5961 }
5962 })
5963 .collect::<Vec<_>>();
5964
5965 args
5966 }
5967
5968 pub(crate) fn fnsig_block(
5969 ctx: &BindgenContext,
5970 sig: &FunctionSig,
5971 ) -> proc_macro2::TokenStream {
5972 let args = sig.argument_types().iter().map(|&(_, ty)| {
5973 let arg_item = ctx.resolve_item(ty);
5974
5975 arg_item.to_rust_ty_or_opaque(ctx, &())
5976 });
5977
5978 let ret_ty = fnsig_return_ty_internal(ctx, sig);
5979 quote! {
5980 *const ::block::Block<(#(#args,)*), #ret_ty>
5981 }
5982 }
5983
5984 pub(crate) fn names_will_be_identical_after_mangling(
5988 canonical_name: &str,
5989 mangled_name: &str,
5990 call_conv: Option<ClangAbi>,
5991 ) -> bool {
5992 if canonical_name == mangled_name {
5995 return true;
5996 }
5997
5998 let canonical_name = canonical_name.as_bytes();
6000 let mangled_name = mangled_name.as_bytes();
6001
6002 let (mangling_prefix, expect_suffix) = match call_conv {
6003 Some(ClangAbi::Known(Abi::C | Abi::CUnwind)) |
6004 None => {
6006 (b'_', false)
6007 }
6008 Some(ClangAbi::Known(Abi::Stdcall)) => (b'_', true),
6009 Some(ClangAbi::Known(Abi::Fastcall)) => (b'@', true),
6010
6011 Some(_) => return false,
6014 };
6015
6016 if mangled_name.len() < canonical_name.len() + 1 {
6019 return false;
6020 }
6021
6022 if mangled_name[0] != mangling_prefix {
6025 return false;
6026 }
6027
6028 if &mangled_name[1..=canonical_name.len()] != canonical_name {
6031 return false;
6032 }
6033
6034 if expect_suffix {
6037 let suffix = &mangled_name[canonical_name.len() + 1..];
6038
6039 if suffix.len() < 2 {
6041 return false;
6042 }
6043
6044 if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit)
6047 {
6048 return false;
6049 }
6050 } else if mangled_name.len() != canonical_name.len() + 1 {
6051 return false;
6054 }
6055
6056 true
6057 }
6058
6059 pub(super) fn call_discovered_item_callback(
6060 ctx: &BindgenContext,
6061 item: &Item,
6062 discovered_item_creator: impl Fn() -> crate::callbacks::DiscoveredItem,
6063 ) {
6064 let source_location = item.location().map(|clang_location| {
6065 let (file, line, col, byte_offset) = clang_location.location();
6066 let file_name = file.name();
6067 crate::callbacks::SourceLocation {
6068 line,
6069 col,
6070 byte_offset,
6071 file_name,
6072 }
6073 });
6074 ctx.options().for_each_callback(|cb| {
6075 cb.new_item_found(
6076 DiscoveredItemId::new(item.id().as_usize()),
6077 discovered_item_creator(),
6078 source_location.as_ref(),
6079 );
6080 });
6081 }
6082}