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