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