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 if let Some(link_name) = self.link_name() {
784 attrs.push(attributes::link_name::<false>(link_name));
785 } else {
786 let link_name =
787 self.mangled_name().unwrap_or_else(|| self.name());
788 if !utils::names_will_be_identical_after_mangling(
789 &canonical_name,
790 link_name,
791 None,
792 ) {
793 attrs.push(attributes::link_name::<false>(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 self.ty()
820 .to_rust_ty_or_opaque(ctx, &())
821 .into_token_stream(),
822 ctx.options().dynamic_link_require_all,
823 ctx.options().wrap_unsafe_ops,
824 );
825 } else {
826 result.push(tokens);
827 }
828 }
829 }
830}
831
832impl CodeGenerator for Type {
833 type Extra = Item;
834 type Return = ();
835
836 fn codegen(
837 &self,
838 ctx: &BindgenContext,
839 result: &mut CodegenResult<'_>,
840 item: &Item,
841 ) {
842 debug!("<Type as CodeGenerator>::codegen: item = {item:?}");
843 debug_assert!(item.is_enabled_for_codegen(ctx));
844
845 match *self.kind() {
846 TypeKind::Void |
847 TypeKind::NullPtr |
848 TypeKind::Int(..) |
849 TypeKind::Float(..) |
850 TypeKind::Complex(..) |
851 TypeKind::Array(..) |
852 TypeKind::Vector(..) |
853 TypeKind::Pointer(..) |
854 TypeKind::Reference(..) |
855 TypeKind::Function(..) |
856 TypeKind::ResolvedTypeRef(..) |
857 TypeKind::Opaque |
858 TypeKind::TypeParam => {
859 }
864 TypeKind::TemplateInstantiation(ref inst) => {
865 inst.codegen(ctx, result, item);
866 }
867 TypeKind::BlockPointer(inner) => {
868 if !ctx.options().generate_block {
869 return;
870 }
871
872 let inner_item =
873 inner.into_resolver().through_type_refs().resolve(ctx);
874 let name = item.canonical_name(ctx);
875
876 let inner_rust_type = {
877 if let TypeKind::Function(fnsig) =
878 inner_item.kind().expect_type().kind()
879 {
880 utils::fnsig_block(ctx, fnsig)
881 } else {
882 panic!("invalid block typedef: {inner_item:?}")
883 }
884 };
885
886 let rust_name = ctx.rust_ident(name);
887
888 let mut tokens = if let Some(comment) = item.comment(ctx) {
889 attributes::doc(comment)
890 } else {
891 quote! {}
892 };
893
894 tokens.append_all(quote! {
895 pub type #rust_name = #inner_rust_type ;
896 });
897
898 result.push(tokens);
899 result.saw_block();
900 }
901 TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
902 TypeKind::TemplateAlias(inner, _) | TypeKind::Alias(inner) => {
903 let inner_item =
904 inner.into_resolver().through_type_refs().resolve(ctx);
905 let name = item.canonical_name(ctx);
906 let path = item.canonical_path(ctx);
907
908 {
909 let through_type_aliases = inner
910 .into_resolver()
911 .through_type_refs()
912 .through_type_aliases()
913 .resolve(ctx);
914
915 if through_type_aliases.canonical_path(ctx) == path {
921 return;
922 }
923 }
924
925 let spelling = self.name().expect("Unnamed alias?");
930 if utils::type_from_named(ctx, spelling).is_some() {
931 if let "size_t" | "ssize_t" = spelling {
932 let layout = inner_item
933 .kind()
934 .expect_type()
935 .layout(ctx)
936 .expect("No layout?");
937 assert_eq!(
938 layout.size,
939 ctx.target_pointer_size(),
940 "Target platform requires `--no-size_t-is-usize`. The size of `{spelling}` ({}) does not match the target pointer size ({})",
941 layout.size,
942 ctx.target_pointer_size(),
943 );
944 assert_eq!(
945 layout.align,
946 ctx.target_pointer_size(),
947 "Target platform requires `--no-size_t-is-usize`. The alignment of `{spelling}` ({}) does not match the target pointer size ({})",
948 layout.align,
949 ctx.target_pointer_size(),
950 );
951 }
952 return;
953 }
954
955 let mut outer_params = item.used_template_params(ctx);
956
957 let is_opaque = item.is_opaque(ctx, &());
958 let inner_rust_type = if is_opaque {
959 outer_params = vec![];
960 self.to_opaque(ctx, item)
961 } else {
962 inner_item
966 .try_to_rust_ty_or_opaque(ctx, &())
967 .unwrap_or_else(|_| self.to_opaque(ctx, item))
968 .with_implicit_template_params(ctx, inner_item)
969 };
970
971 {
972 let inner_canon_type =
983 inner_item.expect_type().canonical_type(ctx);
984 if inner_canon_type.is_invalid_type_param() {
985 warn!(
986 "Item contained invalid named type, skipping: \
987 {:?}, {:?}",
988 item, inner_item
989 );
990 return;
991 }
992 }
993
994 let rust_name = ctx.rust_ident(&name);
995
996 ctx.options().for_each_callback(|cb| {
997 cb.new_item_found(
998 DiscoveredItemId::new(item.id().as_usize()),
999 DiscoveredItem::Alias {
1000 alias_name: rust_name.to_string(),
1001 alias_for: DiscoveredItemId::new(
1002 inner_item.id().as_usize(),
1003 ),
1004 },
1005 );
1006 });
1007
1008 let mut tokens = if let Some(comment) = item.comment(ctx) {
1009 attributes::doc(comment)
1010 } else {
1011 quote! {}
1012 };
1013
1014 let alias_style = if ctx.options().type_alias.matches(&name) {
1015 AliasVariation::TypeAlias
1016 } else if ctx.options().new_type_alias.matches(&name) {
1017 AliasVariation::NewType
1018 } else if ctx.options().new_type_alias_deref.matches(&name) {
1019 AliasVariation::NewTypeDeref
1020 } else {
1021 ctx.options().default_alias_style
1022 };
1023
1024 if matches!(inner_rust_type, syn::Type::Path(_)) &&
1027 outer_params.is_empty() &&
1028 !is_opaque &&
1029 alias_style == AliasVariation::TypeAlias &&
1030 inner_item.expect_type().canonical_type(ctx).is_enum()
1031 {
1032 tokens.append_all(quote! {
1033 pub use
1034 });
1035 let path = top_level_path(ctx, item);
1036 tokens.append_separated(path, quote!(::));
1037 tokens.append_all(quote! {
1038 :: #inner_rust_type as #rust_name ;
1039 });
1040 result.push(tokens);
1041 return;
1042 }
1043
1044 tokens.append_all(match alias_style {
1045 AliasVariation::TypeAlias => quote! {
1046 pub type #rust_name
1047 },
1048 AliasVariation::NewType | AliasVariation::NewTypeDeref => {
1049 let mut attributes =
1050 vec![attributes::repr("transparent")];
1051 let packed = false; let derivable_traits =
1053 derives_of_item(item, ctx, packed);
1054 let mut derives: Vec<_> = derivable_traits.into();
1055 let custom_derives =
1058 ctx.options().all_callbacks(|cb| {
1059 cb.add_derives(&DeriveInfo {
1060 name: &name,
1061 kind: DeriveTypeKind::Struct,
1062 })
1063 });
1064 derives
1066 .extend(custom_derives.iter().map(|s| s.as_str()));
1067 attributes.push(attributes::derives(&derives));
1068
1069 let custom_attributes =
1070 ctx.options().all_callbacks(|cb| {
1071 cb.add_attributes(&AttributeInfo {
1072 name: &name,
1073 kind: DeriveTypeKind::Struct,
1074 })
1075 });
1076 attributes.extend(
1077 custom_attributes
1078 .iter()
1079 .map(|s| s.parse().unwrap()),
1080 );
1081
1082 quote! {
1083 #( #attributes )*
1084 pub struct #rust_name
1085 }
1086 }
1087 });
1088
1089 let params: Vec<_> = outer_params
1090 .into_iter()
1091 .filter_map(|p| p.as_template_param(ctx, &()))
1092 .collect();
1093 if params
1094 .iter()
1095 .any(|p| ctx.resolve_type(*p).is_invalid_type_param())
1096 {
1097 warn!(
1098 "Item contained invalid template \
1099 parameter: {:?}",
1100 item
1101 );
1102 return;
1103 }
1104 let params: Vec<_> = params
1105 .iter()
1106 .map(|p| {
1107 p.try_to_rust_ty(ctx, &()).expect(
1108 "type parameters can always convert to rust ty OK",
1109 )
1110 })
1111 .collect();
1112
1113 if !params.is_empty() {
1114 tokens.append_all(quote! {
1115 < #( #params ),* >
1116 });
1117 }
1118
1119 tokens.append_all(match alias_style {
1120 AliasVariation::TypeAlias => quote! {
1121 = #inner_rust_type ;
1122 },
1123 AliasVariation::NewType | AliasVariation::NewTypeDeref => {
1124 let visibility = ctx
1125 .options()
1126 .last_callback(|cb| {
1127 cb.field_visibility(FieldInfo {
1128 type_name: &item.canonical_name(ctx),
1129 field_name: "0",
1130 field_type_name: inner_item
1131 .expect_type()
1132 .name(),
1133 })
1134 })
1135 .unwrap_or(ctx.options().default_visibility);
1136 let access_spec = access_specifier(visibility);
1137 quote! {
1138 (#access_spec #inner_rust_type) ;
1139 }
1140 }
1141 });
1142
1143 if alias_style == AliasVariation::NewTypeDeref {
1144 let prefix = ctx.trait_prefix();
1145 tokens.append_all(quote! {
1146 impl ::#prefix::ops::Deref for #rust_name {
1147 type Target = #inner_rust_type;
1148 #[inline]
1149 fn deref(&self) -> &Self::Target {
1150 &self.0
1151 }
1152 }
1153 impl ::#prefix::ops::DerefMut for #rust_name {
1154 #[inline]
1155 fn deref_mut(&mut self) -> &mut Self::Target {
1156 &mut self.0
1157 }
1158 }
1159 });
1160 }
1161
1162 result.push(tokens);
1163 }
1164 TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item),
1165 TypeKind::ObjCId | TypeKind::ObjCSel => {
1166 result.saw_objc();
1167 }
1168 TypeKind::ObjCInterface(ref interface) => {
1169 interface.codegen(ctx, result, item);
1170 }
1171 ref u @ TypeKind::UnresolvedTypeRef(..) => {
1172 unreachable!("Should have been resolved after parsing {u:?}!")
1173 }
1174 }
1175 }
1176}
1177
1178struct Vtable<'a> {
1179 item_id: ItemId,
1180 #[allow(dead_code)]
1182 comp_info: &'a CompInfo,
1183}
1184
1185impl<'a> Vtable<'a> {
1186 fn new(item_id: ItemId, comp_info: &'a CompInfo) -> Self {
1187 Vtable { item_id, comp_info }
1188 }
1189}
1190
1191impl CodeGenerator for Vtable<'_> {
1192 type Extra = Item;
1193 type Return = ();
1194
1195 fn codegen(
1196 &self,
1197 ctx: &BindgenContext,
1198 result: &mut CodegenResult<'_>,
1199 item: &Item,
1200 ) {
1201 assert_eq!(item.id(), self.item_id);
1202 debug_assert!(item.is_enabled_for_codegen(ctx));
1203 let name = ctx.rust_ident(self.canonical_name(ctx));
1204
1205 if ctx.options().vtable_generation &&
1209 self.comp_info.base_members().is_empty() &&
1210 self.comp_info.destructor().is_none()
1211 {
1212 let class_ident = ctx.rust_ident(self.item_id.canonical_name(ctx));
1213
1214 let methods = self
1215 .comp_info
1216 .methods()
1217 .iter()
1218 .filter_map(|m| {
1219 if !m.is_virtual() {
1220 return None;
1221 }
1222
1223 let function_item = ctx.resolve_item(m.signature());
1224 let function = function_item.expect_function();
1225 let signature_item = ctx.resolve_item(function.signature());
1226 let TypeKind::Function(ref signature) = signature_item.expect_type().kind() else { panic!("Function signature type mismatch") };
1227
1228 let function_name = function_item.canonical_name(ctx);
1230
1231 let function_name = ctx.rust_ident(function_name);
1233 let mut args = utils::fnsig_arguments(ctx, signature);
1234 let ret = utils::fnsig_return_ty(ctx, signature);
1235
1236 args[0] = if m.is_const() {
1237 quote! { this: *const #class_ident }
1238 } else {
1239 quote! { this: *mut #class_ident }
1240 };
1241
1242 Some(quote! {
1243 pub #function_name : unsafe extern "C" fn( #( #args ),* ) #ret
1244 })
1245 })
1246 .collect::<Vec<_>>();
1247
1248 result.push(quote! {
1249 #[repr(C)]
1250 pub struct #name {
1251 #( #methods ),*
1252 }
1253 });
1254 } else {
1255 let void = helpers::ast_ty::c_void(ctx);
1257
1258 result.push(quote! {
1259 #[repr(C)]
1260 pub struct #name ( #void );
1261 });
1262 }
1263 }
1264}
1265
1266impl ItemCanonicalName for Vtable<'_> {
1267 fn canonical_name(&self, ctx: &BindgenContext) -> String {
1268 format!("{}__bindgen_vtable", self.item_id.canonical_name(ctx))
1269 }
1270}
1271
1272impl TryToRustTy for Vtable<'_> {
1273 type Extra = ();
1274
1275 fn try_to_rust_ty(
1276 &self,
1277 ctx: &BindgenContext,
1278 _: &(),
1279 ) -> error::Result<syn::Type> {
1280 let name = ctx.rust_ident(self.canonical_name(ctx));
1281 Ok(syn::parse_quote! { #name })
1282 }
1283}
1284
1285impl CodeGenerator for TemplateInstantiation {
1286 type Extra = Item;
1287 type Return = ();
1288
1289 fn codegen(
1290 &self,
1291 ctx: &BindgenContext,
1292 result: &mut CodegenResult<'_>,
1293 item: &Item,
1294 ) {
1295 debug_assert!(item.is_enabled_for_codegen(ctx));
1296
1297 if !ctx.options().layout_tests || self.is_opaque(ctx, item) {
1304 return;
1305 }
1306
1307 let compile_time = ctx.options().rust_features().offset_of;
1309
1310 if ctx.uses_any_template_parameters(item.id()) {
1314 return;
1315 }
1316
1317 let layout = item.kind().expect_type().layout(ctx);
1318
1319 if let Some(layout) = layout {
1320 let size = layout.size;
1321 let align = layout.align;
1322
1323 let name = item.full_disambiguated_name(ctx);
1324 let fn_name = if compile_time {
1325 None
1326 } else {
1327 let mut fn_name =
1328 format!("__bindgen_test_layout_{name}_instantiation");
1329 let times_seen = result.overload_number(&fn_name);
1330 if times_seen > 0 {
1331 write!(&mut fn_name, "_{times_seen}").unwrap();
1332 }
1333 Some(ctx.rust_ident_raw(fn_name))
1334 };
1335
1336 let prefix = ctx.trait_prefix();
1337 let ident = item.to_rust_ty_or_opaque(ctx, &());
1338 let size_of_expr = quote! {
1339 ::#prefix::mem::size_of::<#ident>()
1340 };
1341 let align_of_expr = quote! {
1342 ::#prefix::mem::align_of::<#ident>()
1343 };
1344 let size_of_err =
1345 format!("Size of template specialization: {name}");
1346 let align_of_err =
1347 format!("Align of template specialization: {name}");
1348
1349 if compile_time {
1350 result.push(quote! {
1356 #[allow(clippy::unnecessary_operation, clippy::identity_op)]
1357 const _: () = {
1358 [#size_of_err][#size_of_expr - #size];
1359 [#align_of_err][#align_of_expr - #align];
1360 };
1361 });
1362 } else {
1363 result.push(quote! {
1364 #[test]
1365 fn #fn_name() {
1366 assert_eq!(#size_of_expr, #size, #size_of_err);
1367 assert_eq!(#align_of_expr, #align, #align_of_err);
1368 }
1369 });
1370 }
1371 }
1372 }
1373}
1374
1375trait FieldCodegen<'a> {
1377 type Extra;
1378
1379 #[allow(clippy::too_many_arguments)]
1380 fn codegen<F, M>(
1381 &self,
1382 ctx: &BindgenContext,
1383 visibility_kind: FieldVisibilityKind,
1384 accessor_kind: FieldAccessorKind,
1385 parent: &CompInfo,
1386 parent_item: &Item,
1387 last_field: bool,
1388 result: &mut CodegenResult,
1389 struct_layout: &mut StructLayoutTracker,
1390 fields: &mut F,
1391 methods: &mut M,
1392 extra: Self::Extra,
1393 ) where
1394 F: Extend<proc_macro2::TokenStream>,
1395 M: Extend<proc_macro2::TokenStream>;
1396}
1397
1398impl FieldCodegen<'_> for Field {
1399 type Extra = ();
1400
1401 fn codegen<F, M>(
1402 &self,
1403 ctx: &BindgenContext,
1404 visibility_kind: FieldVisibilityKind,
1405 accessor_kind: FieldAccessorKind,
1406 parent: &CompInfo,
1407 parent_item: &Item,
1408 last_field: bool,
1409 result: &mut CodegenResult,
1410 struct_layout: &mut StructLayoutTracker,
1411 fields: &mut F,
1412 methods: &mut M,
1413 _: (),
1414 ) where
1415 F: Extend<proc_macro2::TokenStream>,
1416 M: Extend<proc_macro2::TokenStream>,
1417 {
1418 match *self {
1419 Field::DataMember(ref data) => {
1420 data.codegen(
1421 ctx,
1422 visibility_kind,
1423 accessor_kind,
1424 parent,
1425 parent_item,
1426 last_field,
1427 result,
1428 struct_layout,
1429 fields,
1430 methods,
1431 (),
1432 );
1433 }
1434 Field::Bitfields(ref unit) => {
1435 unit.codegen(
1436 ctx,
1437 visibility_kind,
1438 accessor_kind,
1439 parent,
1440 parent_item,
1441 last_field,
1442 result,
1443 struct_layout,
1444 fields,
1445 methods,
1446 (),
1447 );
1448 }
1449 }
1450 }
1451}
1452
1453fn wrap_union_field_if_needed(
1454 ctx: &BindgenContext,
1455 struct_layout: &StructLayoutTracker,
1456 ty: syn::Type,
1457 result: &mut CodegenResult,
1458) -> syn::Type {
1459 if struct_layout.is_rust_union() {
1460 if struct_layout.can_copy_union_fields() {
1461 ty
1462 } else {
1463 let prefix = ctx.trait_prefix();
1464 syn::parse_quote! { ::#prefix::mem::ManuallyDrop<#ty> }
1465 }
1466 } else {
1467 result.saw_bindgen_union();
1468 if ctx.options().enable_cxx_namespaces {
1469 syn::parse_quote! { root::__BindgenUnionField<#ty> }
1470 } else {
1471 syn::parse_quote! { __BindgenUnionField<#ty> }
1472 }
1473 }
1474}
1475
1476impl FieldCodegen<'_> for FieldData {
1477 type Extra = ();
1478
1479 fn codegen<F, M>(
1480 &self,
1481 ctx: &BindgenContext,
1482 parent_visibility_kind: FieldVisibilityKind,
1483 accessor_kind: FieldAccessorKind,
1484 parent: &CompInfo,
1485 parent_item: &Item,
1486 last_field: bool,
1487 result: &mut CodegenResult,
1488 struct_layout: &mut StructLayoutTracker,
1489 fields: &mut F,
1490 methods: &mut M,
1491 _: (),
1492 ) where
1493 F: Extend<proc_macro2::TokenStream>,
1494 M: Extend<proc_macro2::TokenStream>,
1495 {
1496 assert!(self.bitfield_width().is_none());
1499
1500 let field_item =
1501 self.ty().into_resolver().through_type_refs().resolve(ctx);
1502 let field_ty = field_item.expect_type();
1503 let ty = self
1504 .ty()
1505 .to_rust_ty_or_opaque(ctx, &())
1506 .with_implicit_template_params(ctx, field_item);
1507
1508 let ty = if parent.is_union() {
1510 wrap_union_field_if_needed(ctx, struct_layout, ty, result)
1511 } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
1512 if ctx.options().flexarray_dst && last_field {
1514 struct_layout.saw_flexible_array();
1515 syn::parse_quote! { FAM }
1516 } else {
1517 result.saw_incomplete_array();
1518
1519 let inner = item.to_rust_ty_or_opaque(ctx, &());
1520
1521 if ctx.options().enable_cxx_namespaces {
1522 syn::parse_quote! { root::__IncompleteArrayField<#inner> }
1523 } else {
1524 syn::parse_quote! { __IncompleteArrayField<#inner> }
1525 }
1526 }
1527 } else {
1528 ty
1529 };
1530
1531 let mut field = quote! {};
1532 if ctx.options().generate_comments {
1533 if let Some(raw_comment) = self.comment() {
1534 let comment = ctx.options().process_comment(raw_comment);
1535 field = attributes::doc(comment);
1536 }
1537 }
1538
1539 let field_name = self
1540 .name()
1541 .map(|name| ctx.rust_mangle(name).into_owned())
1542 .expect("Each field should have a name in codegen!");
1543 let field_name = field_name.as_str();
1544 let field_ident = ctx.rust_ident_raw(field_name);
1545
1546 if let Some(padding_field) =
1547 struct_layout.saw_field(field_name, field_ty, self.offset())
1548 {
1549 fields.extend(Some(padding_field));
1550 }
1551
1552 let visibility = compute_visibility(
1553 ctx,
1554 self.is_public(),
1555 ctx.options().last_callback(|cb| {
1556 cb.field_visibility(FieldInfo {
1557 type_name: &parent_item.canonical_name(ctx),
1558 field_name,
1559 field_type_name: field_ty.name(),
1560 })
1561 }),
1562 self.annotations(),
1563 parent_visibility_kind,
1564 );
1565 let accessor_kind =
1566 self.annotations().accessor_kind().unwrap_or(accessor_kind);
1567
1568 match visibility {
1569 FieldVisibilityKind::Private => {
1570 field.append_all(quote! {
1571 #field_ident : #ty ,
1572 });
1573 }
1574 FieldVisibilityKind::PublicCrate => {
1575 field.append_all(quote! {
1576 pub(crate) #field_ident : #ty ,
1577 });
1578 }
1579 FieldVisibilityKind::Public => {
1580 field.append_all(quote! {
1581 pub #field_ident : #ty ,
1582 });
1583 }
1584 }
1585
1586 fields.extend(Some(field));
1587
1588 if accessor_kind == FieldAccessorKind::None {
1590 return;
1591 }
1592
1593 let getter_name = ctx.rust_ident_raw(format!("get_{field_name}"));
1594 let mutable_getter_name =
1595 ctx.rust_ident_raw(format!("get_{field_name}_mut"));
1596
1597 methods.extend(Some(match accessor_kind {
1598 FieldAccessorKind::None => unreachable!(),
1599 FieldAccessorKind::Regular => {
1600 quote! {
1601 #[inline]
1602 pub fn #getter_name(&self) -> & #ty {
1603 &self.#field_ident
1604 }
1605
1606 #[inline]
1607 pub fn #mutable_getter_name(&mut self) -> &mut #ty {
1608 &mut self.#field_ident
1609 }
1610 }
1611 }
1612 FieldAccessorKind::Unsafe => {
1613 quote! {
1614 #[inline]
1615 pub unsafe fn #getter_name(&self) -> & #ty {
1616 &self.#field_ident
1617 }
1618
1619 #[inline]
1620 pub unsafe fn #mutable_getter_name(&mut self) -> &mut #ty {
1621 &mut self.#field_ident
1622 }
1623 }
1624 }
1625 FieldAccessorKind::Immutable => {
1626 quote! {
1627 #[inline]
1628 pub fn #getter_name(&self) -> & #ty {
1629 &self.#field_ident
1630 }
1631 }
1632 }
1633 }));
1634 }
1635}
1636
1637impl BitfieldUnit {
1638 fn ctor_name(&self) -> proc_macro2::TokenStream {
1640 let ctor_name = Ident::new(
1641 &format!("new_bitfield_{}", self.nth()),
1642 Span::call_site(),
1643 );
1644 quote! {
1645 #ctor_name
1646 }
1647 }
1648}
1649
1650impl Bitfield {
1651 fn extend_ctor_impl(
1655 &self,
1656 ctx: &BindgenContext,
1657 param_name: proc_macro2::TokenStream,
1658 mut ctor_impl: proc_macro2::TokenStream,
1659 ) -> proc_macro2::TokenStream {
1660 let bitfield_ty = ctx.resolve_type(self.ty());
1661 let bitfield_ty_layout = bitfield_ty
1662 .layout(ctx)
1663 .expect("Bitfield without layout? Gah!");
1664 let bitfield_int_ty = helpers::integer_type(bitfield_ty_layout).expect(
1665 "Should already have verified that the bitfield is \
1666 representable as an int",
1667 );
1668
1669 let offset = self.offset_into_unit();
1670 let width = self.width() as u8;
1671 let prefix = ctx.trait_prefix();
1672
1673 ctor_impl.append_all(quote! {
1674 __bindgen_bitfield_unit.set(
1675 #offset,
1676 #width,
1677 {
1678 let #param_name: #bitfield_int_ty = unsafe {
1679 ::#prefix::mem::transmute(#param_name)
1680 };
1681 #param_name as u64
1682 }
1683 );
1684 });
1685
1686 ctor_impl
1687 }
1688}
1689
1690fn access_specifier(
1691 visibility: FieldVisibilityKind,
1692) -> proc_macro2::TokenStream {
1693 match visibility {
1694 FieldVisibilityKind::Private => quote! {},
1695 FieldVisibilityKind::PublicCrate => quote! { pub(crate) },
1696 FieldVisibilityKind::Public => quote! { pub },
1697 }
1698}
1699
1700fn compute_visibility(
1711 ctx: &BindgenContext,
1712 is_declared_public: bool,
1713 callback_override: Option<FieldVisibilityKind>,
1714 annotations: &Annotations,
1715 default_kind: FieldVisibilityKind,
1716) -> FieldVisibilityKind {
1717 callback_override
1718 .or_else(|| annotations.visibility_kind())
1719 .unwrap_or_else(|| {
1720 match (is_declared_public, ctx.options().respect_cxx_access_specs) {
1721 (true, true) => {
1722 FieldVisibilityKind::Public
1724 }
1725 (false, true) => {
1726 FieldVisibilityKind::Private
1728 }
1729 (_, false) => {
1730 default_kind
1732 }
1733 }
1734 })
1735}
1736
1737impl FieldCodegen<'_> for BitfieldUnit {
1738 type Extra = ();
1739
1740 fn codegen<F, M>(
1741 &self,
1742 ctx: &BindgenContext,
1743 visibility_kind: FieldVisibilityKind,
1744 accessor_kind: FieldAccessorKind,
1745 parent: &CompInfo,
1746 parent_item: &Item,
1747 last_field: bool,
1748 result: &mut CodegenResult,
1749 struct_layout: &mut StructLayoutTracker,
1750 fields: &mut F,
1751 methods: &mut M,
1752 _: (),
1753 ) where
1754 F: Extend<proc_macro2::TokenStream>,
1755 M: Extend<proc_macro2::TokenStream>,
1756 {
1757 use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
1758
1759 result.saw_bitfield_unit();
1760
1761 let layout = self.layout();
1762 let unit_field_ty = helpers::bitfield_unit(ctx, layout);
1763 let field_ty = {
1764 let unit_field_ty = unit_field_ty.clone();
1765 if parent.is_union() {
1766 wrap_union_field_if_needed(
1767 ctx,
1768 struct_layout,
1769 unit_field_ty,
1770 result,
1771 )
1772 } else {
1773 unit_field_ty
1774 }
1775 };
1776
1777 {
1778 let align_field_name = format!("_bitfield_align_{}", self.nth());
1779 let align_field_ident = ctx.rust_ident(align_field_name);
1780 let align_ty = match self.layout().align {
1781 n if n >= 8 => quote! { u64 },
1782 4 => quote! { u32 },
1783 2 => quote! { u16 },
1784 _ => quote! { u8 },
1785 };
1786 let access_spec = access_specifier(visibility_kind);
1787 let align_field = quote! {
1788 #access_spec #align_field_ident: [#align_ty; 0],
1789 };
1790 fields.extend(Some(align_field));
1791 }
1792
1793 let unit_field_name = format!("_bitfield_{}", self.nth());
1794 let unit_field_ident = ctx.rust_ident(&unit_field_name);
1795
1796 let ctor_name = self.ctor_name();
1797 let mut ctor_params = vec![];
1798 let mut ctor_impl = quote! {};
1799
1800 let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;
1806
1807 let mut unit_visibility = visibility_kind;
1808 let bfields = self.bitfields();
1809 for (idx, bf) in bfields.iter().enumerate() {
1810 if bf.name().is_none() {
1812 continue;
1813 }
1814
1815 if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT &&
1816 !ctx.options().rust_features().larger_arrays
1817 {
1818 continue;
1819 }
1820
1821 let mut bitfield_representable_as_int = true;
1822 let mut bitfield_visibility = visibility_kind;
1823 bf.codegen(
1824 ctx,
1825 visibility_kind,
1826 accessor_kind,
1827 parent,
1828 parent_item,
1829 last_field && idx == bfields.len() - 1,
1830 result,
1831 struct_layout,
1832 fields,
1833 methods,
1834 (
1835 &unit_field_name,
1836 &unit_field_ty,
1837 &mut bitfield_representable_as_int,
1838 &mut bitfield_visibility,
1839 ),
1840 );
1841 if bitfield_visibility < unit_visibility {
1842 unit_visibility = bitfield_visibility;
1843 }
1844
1845 if !bitfield_representable_as_int {
1847 generate_ctor = false;
1848 continue;
1849 }
1850
1851 let param_name = bitfield_getter_name(ctx, bf);
1852 let bitfield_ty_item = ctx.resolve_item(bf.ty());
1853 let bitfield_ty = bitfield_ty_item.expect_type();
1854 let bitfield_ty =
1855 bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);
1856
1857 ctor_params.push(quote! {
1858 #param_name : #bitfield_ty
1859 });
1860 ctor_impl = bf.extend_ctor_impl(ctx, param_name, ctor_impl);
1861 }
1862
1863 let access_spec = access_specifier(unit_visibility);
1864
1865 let field = quote! {
1866 #access_spec #unit_field_ident : #field_ty ,
1867 };
1868 fields.extend(Some(field));
1869
1870 if generate_ctor {
1871 methods.extend(Some(quote! {
1872 #[inline]
1873 #access_spec fn #ctor_name ( #( #ctor_params ),* ) -> #unit_field_ty {
1874 let mut __bindgen_bitfield_unit: #unit_field_ty = Default::default();
1875 #ctor_impl
1876 __bindgen_bitfield_unit
1877 }
1878 }));
1879 }
1880
1881 struct_layout.saw_bitfield_unit(layout);
1882 }
1883}
1884
1885fn bitfield_getter_name(
1886 ctx: &BindgenContext,
1887 bitfield: &Bitfield,
1888) -> proc_macro2::TokenStream {
1889 let name = bitfield.getter_name();
1890 let name = ctx.rust_ident_raw(name);
1891 quote! { #name }
1892}
1893
1894fn bitfield_raw_getter_name(
1895 ctx: &BindgenContext,
1896 bitfield: &Bitfield,
1897) -> proc_macro2::TokenStream {
1898 let name = bitfield.getter_name();
1899 let name = ctx.rust_ident_raw(format!("{name}_raw"));
1900 quote! { #name }
1901}
1902
1903fn bitfield_setter_name(
1904 ctx: &BindgenContext,
1905 bitfield: &Bitfield,
1906) -> proc_macro2::TokenStream {
1907 let setter = bitfield.setter_name();
1908 let setter = ctx.rust_ident_raw(setter);
1909 quote! { #setter }
1910}
1911
1912fn bitfield_raw_setter_name(
1913 ctx: &BindgenContext,
1914 bitfield: &Bitfield,
1915) -> proc_macro2::TokenStream {
1916 let setter = bitfield.setter_name();
1917 let setter = ctx.rust_ident_raw(format!("{setter}_raw"));
1918 quote! { #setter }
1919}
1920
1921impl<'a> FieldCodegen<'a> for Bitfield {
1922 type Extra = (
1923 &'a str,
1924 &'a syn::Type,
1925 &'a mut bool,
1926 &'a mut FieldVisibilityKind,
1927 );
1928
1929 fn codegen<F, M>(
1930 &self,
1931 ctx: &BindgenContext,
1932 visibility_kind: FieldVisibilityKind,
1933 _accessor_kind: FieldAccessorKind,
1934 parent: &CompInfo,
1935 parent_item: &Item,
1936 _last_field: bool,
1937 _result: &mut CodegenResult,
1938 struct_layout: &mut StructLayoutTracker,
1939 _fields: &mut F,
1940 methods: &mut M,
1941 (
1942 unit_field_name,
1943 unit_field_ty,
1944 bitfield_representable_as_int,
1945 bitfield_visibility,
1946 ): (
1947 &'a str,
1948 &'a syn::Type,
1949 &mut bool,
1950 &'a mut FieldVisibilityKind,
1951 ),
1952 ) where
1953 F: Extend<proc_macro2::TokenStream>,
1954 M: Extend<proc_macro2::TokenStream>,
1955 {
1956 let prefix = ctx.trait_prefix();
1957 let getter_name = bitfield_getter_name(ctx, self);
1958 let setter_name = bitfield_setter_name(ctx, self);
1959 let raw_getter_name = bitfield_raw_getter_name(ctx, self);
1960 let raw_setter_name = bitfield_raw_setter_name(ctx, self);
1961 let unit_field_ident = Ident::new(unit_field_name, Span::call_site());
1962
1963 let bitfield_ty_item = ctx.resolve_item(self.ty());
1964 let bitfield_ty = bitfield_ty_item.expect_type();
1965 let bitfield_ty_ident = bitfield_ty.name();
1966
1967 let bitfield_ty_layout = bitfield_ty
1968 .layout(ctx)
1969 .expect("Bitfield without layout? Gah!");
1970 let bitfield_int_ty =
1971 if let Some(int_ty) = helpers::integer_type(bitfield_ty_layout) {
1972 *bitfield_representable_as_int = true;
1973 int_ty
1974 } else {
1975 *bitfield_representable_as_int = false;
1976 return;
1977 };
1978
1979 let bitfield_ty =
1980 bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item);
1981
1982 let offset = self.offset_into_unit();
1983 let width = self.width() as u8;
1984
1985 let override_visibility = self.name().and_then(|field_name| {
1986 ctx.options().last_callback(|cb| {
1987 cb.field_visibility(FieldInfo {
1988 type_name: &parent_item.canonical_name(ctx),
1989 field_name,
1990 field_type_name: bitfield_ty_ident,
1991 })
1992 })
1993 });
1994 *bitfield_visibility = compute_visibility(
1995 ctx,
1996 self.is_public(),
1997 override_visibility,
1998 self.annotations(),
1999 visibility_kind,
2000 );
2001 let access_spec = access_specifier(*bitfield_visibility);
2002
2003 if parent.is_union() && !struct_layout.is_rust_union() {
2004 methods.extend(Some(quote! {
2005 #[inline]
2006 #access_spec fn #getter_name(&self) -> #bitfield_ty {
2007 unsafe {
2008 ::#prefix::mem::transmute(
2009 self.#unit_field_ident.as_ref().get(#offset, #width)
2010 as #bitfield_int_ty
2011 )
2012 }
2013 }
2014
2015 #[inline]
2016 #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
2017 unsafe {
2018 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2019 self.#unit_field_ident.as_mut().set(
2020 #offset,
2021 #width,
2022 val as u64
2023 )
2024 }
2025 }
2026 }));
2027
2028 if ctx.options().rust_features.raw_ref_macros {
2029 methods.extend(Some(quote! {
2030 #[inline]
2031 #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty {
2032 unsafe {
2033 ::#prefix::mem::transmute(<#unit_field_ty>::raw_get(
2034 (*::#prefix::ptr::addr_of!((*this).#unit_field_ident)).as_ref() as *const _,
2035 #offset,
2036 #width,
2037 ) as #bitfield_int_ty)
2038 }
2039 }
2040
2041 #[inline]
2042 #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) {
2043 unsafe {
2044 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2045 <#unit_field_ty>::raw_set(
2046 (*::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident)).as_mut() as *mut _,
2047 #offset,
2048 #width,
2049 val as u64,
2050 )
2051 }
2052 }
2053 }));
2054 }
2055 } else {
2056 methods.extend(Some(quote! {
2057 #[inline]
2058 #access_spec fn #getter_name(&self) -> #bitfield_ty {
2059 unsafe {
2060 ::#prefix::mem::transmute(
2061 self.#unit_field_ident.get(#offset, #width)
2062 as #bitfield_int_ty
2063 )
2064 }
2065 }
2066
2067 #[inline]
2068 #access_spec fn #setter_name(&mut self, val: #bitfield_ty) {
2069 unsafe {
2070 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2071 self.#unit_field_ident.set(
2072 #offset,
2073 #width,
2074 val as u64
2075 )
2076 }
2077 }
2078 }));
2079
2080 if ctx.options().rust_features.raw_ref_macros {
2081 methods.extend(Some(quote! {
2082 #[inline]
2083 #access_spec unsafe fn #raw_getter_name(this: *const Self) -> #bitfield_ty {
2084 unsafe {
2085 ::#prefix::mem::transmute(<#unit_field_ty>::raw_get(
2086 ::#prefix::ptr::addr_of!((*this).#unit_field_ident),
2087 #offset,
2088 #width,
2089 ) as #bitfield_int_ty)
2090 }
2091 }
2092
2093 #[inline]
2094 #access_spec unsafe fn #raw_setter_name(this: *mut Self, val: #bitfield_ty) {
2095 unsafe {
2096 let val: #bitfield_int_ty = ::#prefix::mem::transmute(val);
2097 <#unit_field_ty>::raw_set(
2098 ::#prefix::ptr::addr_of_mut!((*this).#unit_field_ident),
2099 #offset,
2100 #width,
2101 val as u64,
2102 )
2103 }
2104 }
2105 }));
2106 }
2107 }
2108 }
2109}
2110
2111impl CodeGenerator for CompInfo {
2112 type Extra = Item;
2113 type Return = ();
2114
2115 fn codegen(
2116 &self,
2117 ctx: &BindgenContext,
2118 result: &mut CodegenResult<'_>,
2119 item: &Item,
2120 ) {
2121 debug!("<CompInfo as CodeGenerator>::codegen: item = {item:?}");
2122 debug_assert!(item.is_enabled_for_codegen(ctx));
2123
2124 if self.has_non_type_template_params() {
2127 return;
2128 }
2129
2130 let ty = item.expect_type();
2131 let layout = ty.layout(ctx);
2132 let mut packed = self.is_packed(ctx, layout.as_ref());
2133
2134 let canonical_name = item.canonical_name(ctx);
2135 let canonical_ident = ctx.rust_ident(&canonical_name);
2136
2137 let is_opaque = item.is_opaque(ctx, &());
2150 let mut fields = vec![];
2151 let visibility = item
2152 .annotations()
2153 .visibility_kind()
2154 .unwrap_or(ctx.options().default_visibility);
2155 let mut struct_layout = StructLayoutTracker::new(
2156 ctx,
2157 self,
2158 ty,
2159 &canonical_name,
2160 visibility,
2161 packed,
2162 );
2163
2164 let mut generic_param_names = vec![];
2165
2166 for (idx, ty) in item.used_template_params(ctx).iter().enumerate() {
2167 let param = ctx.resolve_type(*ty);
2168 let name = param.name().unwrap();
2169 let ident = ctx.rust_ident(name);
2170 generic_param_names.push(ident.clone());
2171
2172 let prefix = ctx.trait_prefix();
2173 let field_name = ctx.rust_ident(format!("_phantom_{idx}"));
2174 fields.push(quote! {
2175 pub #field_name : ::#prefix::marker::PhantomData<
2176 ::#prefix::cell::UnsafeCell<#ident>
2177 > ,
2178 });
2179 }
2180
2181 if !is_opaque {
2182 if item.has_vtable_ptr(ctx) {
2183 let vtable = Vtable::new(item.id(), self);
2184 vtable.codegen(ctx, result, item);
2185
2186 let vtable_type = vtable
2187 .try_to_rust_ty(ctx, &())
2188 .expect("vtable to Rust type conversion is infallible")
2189 .to_ptr(true);
2190
2191 fields.push(quote! {
2192 pub vtable_: #vtable_type ,
2193 });
2194
2195 struct_layout.saw_vtable();
2196 }
2197
2198 for base in self.base_members() {
2199 if !base.requires_storage(ctx) {
2200 continue;
2201 }
2202
2203 let inner_item = ctx.resolve_item(base.ty);
2204 let inner = inner_item
2205 .to_rust_ty_or_opaque(ctx, &())
2206 .with_implicit_template_params(ctx, inner_item);
2207 let field_name = ctx.rust_ident(&base.field_name);
2208
2209 struct_layout.saw_base(inner_item.expect_type());
2210
2211 let visibility = match (
2212 base.is_public(),
2213 ctx.options().respect_cxx_access_specs,
2214 ) {
2215 (true, true) => FieldVisibilityKind::Public,
2216 (false, true) => FieldVisibilityKind::Private,
2217 _ => ctx.options().default_visibility,
2218 };
2219
2220 let access_spec = access_specifier(visibility);
2221 fields.push(quote! {
2222 #access_spec #field_name: #inner,
2223 });
2224 }
2225 }
2226
2227 let mut methods = vec![];
2228 if !is_opaque {
2229 let struct_accessor_kind = item
2230 .annotations()
2231 .accessor_kind()
2232 .unwrap_or(FieldAccessorKind::None);
2233 let field_decls = self.fields();
2234 for (idx, field) in field_decls.iter().enumerate() {
2235 field.codegen(
2236 ctx,
2237 visibility,
2238 struct_accessor_kind,
2239 self,
2240 item,
2241 idx == field_decls.len() - 1,
2242 result,
2243 &mut struct_layout,
2244 &mut fields,
2245 &mut methods,
2246 (),
2247 );
2248 }
2249 if let Some(comp_layout) = layout {
2252 fields.extend(
2253 struct_layout
2254 .add_tail_padding(&canonical_name, comp_layout),
2255 );
2256 }
2257 }
2258
2259 if is_opaque {
2260 debug_assert!(fields.is_empty());
2262 debug_assert!(methods.is_empty());
2263 }
2264
2265 let is_union = self.kind() == CompKind::Union;
2266 let layout = item.kind().expect_type().layout(ctx);
2267 let zero_sized = item.is_zero_sized(ctx);
2268 let forward_decl = self.is_forward_declaration();
2269
2270 let mut explicit_align = None;
2271
2272 if !forward_decl && zero_sized {
2283 let has_address = if is_opaque {
2284 layout.is_none()
2287 } else {
2288 layout.map_or(true, |l| l.size != 0)
2289 };
2290
2291 if has_address {
2292 let layout = Layout::new(1, 1);
2293 let ty = helpers::blob(ctx, Layout::new(1, 1), false);
2294 struct_layout.saw_field_with_layout(
2295 "_address",
2296 layout,
2297 Some(0),
2298 );
2299 fields.push(quote! {
2300 pub _address: #ty,
2301 });
2302 }
2303 }
2304
2305 if is_opaque {
2306 match layout {
2307 Some(l) => {
2308 explicit_align = Some(l.align);
2309
2310 let ty = helpers::blob(ctx, l, false);
2311 fields.push(quote! {
2312 pub _bindgen_opaque_blob: #ty ,
2313 });
2314 }
2315 None => {
2316 warn!("Opaque type without layout! Expect dragons!");
2317 }
2318 }
2319 } else if !is_union && !zero_sized {
2320 if let Some(padding_field) =
2321 layout.and_then(|layout| struct_layout.pad_struct(layout))
2322 {
2323 fields.push(padding_field);
2324 }
2325
2326 if let Some(layout) = layout {
2327 if struct_layout.requires_explicit_align(layout) {
2328 if layout.align == 1 {
2329 packed = true;
2330 } else {
2331 explicit_align = Some(layout.align);
2332 }
2333 }
2334 }
2335 } else if is_union && !forward_decl {
2336 let layout = layout.expect("Unable to get layout information?");
2339 if struct_layout.requires_explicit_align(layout) {
2340 explicit_align = Some(layout.align);
2341 }
2342
2343 if !struct_layout.is_rust_union() {
2344 let ty = helpers::blob(ctx, layout, false);
2345 fields.push(quote! {
2346 pub bindgen_union_field: #ty ,
2347 });
2348 }
2349 }
2350
2351 if forward_decl {
2352 fields.push(quote! {
2353 _unused: [u8; 0],
2354 });
2355 }
2356
2357 let (flex_array_generic, flex_inner_ty) = if ctx.options().flexarray_dst
2358 {
2359 match self.flex_array_member(ctx) {
2360 Some(ty) => {
2361 let inner = ty.to_rust_ty_or_opaque(ctx, &());
2362 (
2363 Some(quote! { FAM: ?Sized = [ #inner; 0 ] }),
2364 Some(quote! { #inner }),
2365 )
2366 }
2367 None => (None, None),
2368 }
2369 } else {
2370 (None, None)
2371 };
2372
2373 let (generics, impl_generics_labels, impl_generics_params) =
2381 if !generic_param_names.is_empty() || flex_array_generic.is_some() {
2382 let (flex_sized, flex_fam) = match flex_inner_ty.as_ref() {
2383 None => (None, None),
2384 Some(ty) => (
2385 Some(quote! { [ #ty; 0 ] }),
2386 Some(quote! { FAM: ?Sized = [ #ty; 0 ] }),
2387 ),
2388 };
2389
2390 (
2391 quote! {
2392 < #( #generic_param_names , )* #flex_fam >
2393 },
2394 quote! {
2395 < #( #generic_param_names , )* >
2396 },
2397 quote! {
2398 < #( #generic_param_names , )* #flex_sized >
2399 },
2400 )
2401 } else {
2402 (quote! {}, quote! {}, quote! {})
2403 };
2404
2405 let mut attributes = vec![];
2406 let mut needs_clone_impl = false;
2407 let mut needs_default_impl = false;
2408 let mut needs_debug_impl = false;
2409 let mut needs_partialeq_impl = false;
2410 let needs_flexarray_impl = flex_array_generic.is_some();
2411 if let Some(comment) = item.comment(ctx) {
2412 attributes.push(attributes::doc(comment));
2413 }
2414
2415 if packed &&
2418 !is_opaque &&
2419 !(explicit_align.is_some() &&
2420 self.already_packed(ctx).unwrap_or(false))
2421 {
2422 let n = layout.map_or(1, |l| l.align);
2423 assert!(ctx.options().rust_features().repr_packed_n || n == 1);
2424 let packed_repr = if n == 1 {
2425 "packed".to_string()
2426 } else {
2427 format!("packed({n})")
2428 };
2429 attributes.push(attributes::repr_list(&["C", &packed_repr]));
2430 } else {
2431 attributes.push(attributes::repr("C"));
2432 }
2433
2434 if true {
2435 if let Some(explicit) = explicit_align {
2436 let explicit = helpers::ast_ty::int_expr(explicit as i64);
2439 attributes.push(quote! {
2440 #[repr(align(#explicit))]
2441 });
2442 }
2443 }
2444
2445 let derivable_traits = derives_of_item(item, ctx, packed);
2446 if !derivable_traits.contains(DerivableTraits::DEBUG) {
2447 needs_debug_impl = ctx.options().derive_debug &&
2448 ctx.options().impl_debug &&
2449 !ctx.no_debug_by_name(item) &&
2450 !item.annotations().disallow_debug();
2451 }
2452
2453 if !derivable_traits.contains(DerivableTraits::DEFAULT) {
2454 needs_default_impl = ctx.options().derive_default &&
2455 !self.is_forward_declaration() &&
2456 !ctx.no_default_by_name(item) &&
2457 !item.annotations().disallow_default();
2458 }
2459
2460 let all_template_params = item.all_template_params(ctx);
2461
2462 if derivable_traits.contains(DerivableTraits::COPY) &&
2463 !derivable_traits.contains(DerivableTraits::CLONE)
2464 {
2465 needs_clone_impl = true;
2466 }
2467
2468 if !derivable_traits.contains(DerivableTraits::PARTIAL_EQ) {
2469 needs_partialeq_impl = ctx.options().derive_partialeq &&
2470 ctx.options().impl_partialeq &&
2471 ctx.lookup_can_derive_partialeq_or_partialord(item.id()) ==
2472 CanDerive::Manually;
2473 }
2474
2475 let mut derives: Vec<_> = derivable_traits.into();
2476 derives.extend(item.annotations().derives().iter().map(String::as_str));
2477
2478 let is_rust_union = is_union && struct_layout.is_rust_union();
2479
2480 ctx.options().for_each_callback(|cb| {
2481 let discovered_item = match self.kind() {
2482 CompKind::Struct => DiscoveredItem::Struct {
2483 original_name: item
2484 .kind()
2485 .expect_type()
2486 .name()
2487 .map(String::from),
2488 final_name: canonical_ident.to_string(),
2489 },
2490 CompKind::Union => DiscoveredItem::Union {
2491 original_name: item
2492 .kind()
2493 .expect_type()
2494 .name()
2495 .map(String::from),
2496 final_name: canonical_ident.to_string(),
2497 },
2498 };
2499
2500 cb.new_item_found(
2501 DiscoveredItemId::new(item.id().as_usize()),
2502 discovered_item,
2503 );
2504 });
2505
2506 let custom_derives = ctx.options().all_callbacks(|cb| {
2509 cb.add_derives(&DeriveInfo {
2510 name: &canonical_name,
2511 kind: if is_rust_union {
2512 DeriveTypeKind::Union
2513 } else {
2514 DeriveTypeKind::Struct
2515 },
2516 })
2517 });
2518 derives.extend(custom_derives.iter().map(|s| s.as_str()));
2520
2521 if !derives.is_empty() {
2522 attributes.push(attributes::derives(&derives));
2523 }
2524
2525 attributes.extend(
2526 item.annotations()
2527 .attributes()
2528 .iter()
2529 .map(|s| s.parse().unwrap()),
2530 );
2531
2532 let custom_attributes = ctx.options().all_callbacks(|cb| {
2533 cb.add_attributes(&AttributeInfo {
2534 name: &canonical_name,
2535 kind: if is_rust_union {
2536 DeriveTypeKind::Union
2537 } else {
2538 DeriveTypeKind::Struct
2539 },
2540 })
2541 });
2542 attributes.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));
2543
2544 if item.must_use(ctx) {
2545 attributes.push(attributes::must_use());
2546 }
2547
2548 let mut tokens = if is_rust_union {
2549 quote! {
2550 #( #attributes )*
2551 pub union #canonical_ident
2552 }
2553 } else {
2554 quote! {
2555 #( #attributes )*
2556 pub struct #canonical_ident
2557 }
2558 };
2559
2560 tokens.append_all(quote! {
2561 #generics {
2562 #( #fields )*
2563 }
2564 });
2565 result.push(tokens);
2566
2567 for ty in self.inner_types() {
2572 let child_item = ctx.resolve_item(*ty);
2573 child_item.codegen(ctx, result, &());
2575 }
2576
2577 if self.found_unknown_attr() {
2581 warn!("Type {canonical_ident} has an unknown attribute that may affect layout");
2582 }
2583
2584 if all_template_params.is_empty() {
2585 if !is_opaque {
2586 for var in self.inner_vars() {
2587 ctx.resolve_item(*var).codegen(ctx, result, &());
2588 }
2589 }
2590
2591 if ctx.options().layout_tests && !self.is_forward_declaration() {
2592 if let Some(layout) = layout {
2593 let compile_time = ctx.options().rust_features().offset_of;
2594 let fn_name = if compile_time {
2595 None
2596 } else {
2597 let fn_name =
2598 format!("bindgen_test_layout_{canonical_ident}");
2599 Some(ctx.rust_ident_raw(fn_name))
2600 };
2601 let prefix = ctx.trait_prefix();
2602 let size_of_expr = quote! {
2603 ::#prefix::mem::size_of::<#canonical_ident>()
2604 };
2605 let align_of_expr = quote! {
2606 ::#prefix::mem::align_of::<#canonical_ident>()
2607 };
2608 let size = layout.size;
2609 let align = layout.align;
2610 let size_of_err = format!("Size of {canonical_ident}");
2611 let align_of_err =
2612 format!("Alignment of {canonical_ident}");
2613
2614 let check_struct_align = if compile_time {
2615 quote! {
2616 [#align_of_err][#align_of_expr - #align];
2617 }
2618 } else {
2619 quote! {
2620 assert_eq!(#align_of_expr, #align, #align_of_err);
2621 }
2622 };
2623
2624 let should_skip_field_offset_checks = is_opaque;
2625
2626 let check_field_offset = if should_skip_field_offset_checks
2627 {
2628 vec![]
2629 } else {
2630 self.fields()
2631 .iter()
2632 .filter_map(|field| match *field {
2633 Field::DataMember(ref f) if f.name().is_some() => Some(f),
2634 _ => None,
2635 })
2636 .flat_map(|field| {
2637 let name = field.name().unwrap();
2638 field.offset().map(|offset| {
2639 let field_offset = offset / 8;
2640 let field_name = ctx.rust_ident(name);
2641 let offset_of_err = format!("Offset of field: {canonical_ident}::{field_name}");
2642 if compile_time {
2643 quote! {
2644 [#offset_of_err][
2645 ::#prefix::mem::offset_of!(#canonical_ident, #field_name) - #field_offset
2646 ];
2647 }
2648 } else {
2649 quote! {
2650 assert_eq!(
2651 unsafe {
2652 ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize
2653 },
2654 #field_offset,
2655 #offset_of_err
2656 );
2657 }
2658 }
2659 })
2660 })
2661 .collect()
2662 };
2663
2664 let uninit_decl = if check_field_offset.is_empty() ||
2665 compile_time
2666 {
2667 None
2668 } else {
2669 Some(quote! {
2672 const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit();
2676 let ptr = UNINIT.as_ptr();
2677 })
2678 };
2679
2680 if compile_time {
2681 result.push(quote! {
2682 #[allow(clippy::unnecessary_operation, clippy::identity_op)]
2683 const _: () = {
2684 [#size_of_err][#size_of_expr - #size];
2685 #check_struct_align
2686 #( #check_field_offset )*
2687 };
2688 });
2689 } else {
2690 result.push(quote! {
2691 #[test]
2692 fn #fn_name() {
2693 #uninit_decl
2694 assert_eq!(#size_of_expr, #size, #size_of_err);
2695 #check_struct_align
2696 #( #check_field_offset )*
2697 }
2698 });
2699 }
2700 }
2701 }
2702
2703 let mut method_names = Default::default();
2704 if ctx.options().codegen_config.methods() {
2705 for method in self.methods() {
2706 assert!(method.kind() != MethodKind::Constructor);
2707 method.codegen_method(
2708 ctx,
2709 &mut methods,
2710 &mut method_names,
2711 result,
2712 self,
2713 );
2714 }
2715 }
2716
2717 if ctx.options().codegen_config.constructors() {
2718 for sig in self.constructors() {
2719 Method::new(
2720 MethodKind::Constructor,
2721 *sig,
2722 false,
2724 )
2725 .codegen_method(
2726 ctx,
2727 &mut methods,
2728 &mut method_names,
2729 result,
2730 self,
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 );
2745 }
2746 }
2747 }
2748
2749 let ty_for_impl = quote! {
2752 #canonical_ident #impl_generics_params
2753 };
2754
2755 if needs_clone_impl {
2756 result.push(quote! {
2757 impl #impl_generics_labels Clone for #ty_for_impl {
2758 fn clone(&self) -> Self { *self }
2759 }
2760 });
2761 }
2762
2763 if needs_flexarray_impl {
2764 result.push(self.generate_flexarray(
2765 ctx,
2766 &canonical_ident,
2767 flex_inner_ty,
2768 &generic_param_names,
2769 &impl_generics_labels,
2770 ));
2771 }
2772
2773 if needs_default_impl {
2774 let prefix = ctx.trait_prefix();
2775 let body = if ctx.options().rust_features().maybe_uninit {
2776 quote! {
2777 let mut s = ::#prefix::mem::MaybeUninit::<Self>::uninit();
2778 unsafe {
2779 ::#prefix::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
2780 s.assume_init()
2781 }
2782 }
2783 } else {
2784 quote! {
2785 unsafe {
2786 let mut s: Self = ::#prefix::mem::uninitialized();
2787 ::#prefix::ptr::write_bytes(&mut s, 0, 1);
2788 s
2789 }
2790 }
2791 };
2792 result.push(quote! {
2797 impl #impl_generics_labels Default for #ty_for_impl {
2798 fn default() -> Self {
2799 #body
2800 }
2801 }
2802 });
2803 }
2804
2805 if needs_debug_impl {
2806 let impl_ = impl_debug::gen_debug_impl(
2807 ctx,
2808 self.fields(),
2809 item,
2810 self.kind(),
2811 );
2812
2813 let prefix = ctx.trait_prefix();
2814
2815 result.push(quote! {
2816 impl #impl_generics_labels ::#prefix::fmt::Debug for #ty_for_impl {
2817 #impl_
2818 }
2819 });
2820 }
2821
2822 if needs_partialeq_impl {
2823 if let Some(impl_) = impl_partialeq::gen_partialeq_impl(
2824 ctx,
2825 self,
2826 item,
2827 &ty_for_impl,
2828 ) {
2829 let partialeq_bounds = if generic_param_names.is_empty() {
2830 quote! {}
2831 } else {
2832 let bounds = generic_param_names.iter().map(|t| {
2833 quote! { #t: PartialEq }
2834 });
2835 quote! { where #( #bounds ),* }
2836 };
2837
2838 let prefix = ctx.trait_prefix();
2839 result.push(quote! {
2840 impl #impl_generics_labels ::#prefix::cmp::PartialEq for #ty_for_impl #partialeq_bounds {
2841 #impl_
2842 }
2843 });
2844 }
2845 }
2846
2847 if !methods.is_empty() {
2848 result.push(quote! {
2849 impl #impl_generics_labels #ty_for_impl {
2850 #( #methods )*
2851 }
2852 });
2853 }
2854 }
2855}
2856
2857impl CompInfo {
2858 fn generate_flexarray(
2859 &self,
2860 ctx: &BindgenContext,
2861 canonical_ident: &Ident,
2862 flex_inner_ty: Option<proc_macro2::TokenStream>,
2863 generic_param_names: &[Ident],
2864 impl_generics_labels: &proc_macro2::TokenStream,
2865 ) -> proc_macro2::TokenStream {
2866 let prefix = ctx.trait_prefix();
2867
2868 let flex_array = flex_inner_ty.as_ref().map(|ty| quote! { [ #ty ] });
2869
2870 let dst_ty_for_impl = quote! {
2871 #canonical_ident < #( #generic_param_names , )* #flex_array >
2872
2873 };
2874 let sized_ty_for_impl = quote! {
2875 #canonical_ident < #( #generic_param_names , )* [ #flex_inner_ty; 0 ] >
2876 };
2877
2878 let layout = if ctx.options().rust_features().layout_for_ptr {
2879 quote! {
2880 pub fn layout(len: usize) -> ::#prefix::alloc::Layout {
2881 unsafe {
2883 let p: *const Self = ::#prefix::ptr::from_raw_parts(::#prefix::ptr::null::<()>(), len);
2884 ::#prefix::alloc::Layout::for_value_raw(p)
2885 }
2886 }
2887 }
2888 } else {
2889 quote!()
2890 };
2891
2892 let (from_ptr_dst, from_ptr_sized) = if ctx
2893 .options()
2894 .rust_features()
2895 .ptr_metadata
2896 {
2897 let flex_ref_inner = ctx.wrap_unsafe_ops(quote! {
2898 Self::flex_ptr(self, len)
2899 });
2900 let flex_ref_mut_inner = ctx.wrap_unsafe_ops(quote! {
2901 Self::flex_ptr_mut(self, len).assume_init()
2902 });
2903 let flex_ptr_inner = ctx.wrap_unsafe_ops(quote! {
2904 &*::#prefix::ptr::from_raw_parts(ptr as *const (), len)
2905 });
2906 let flex_ptr_mut_inner = ctx.wrap_unsafe_ops(quote! {
2907 let mut uninit = ::#prefix::mem::MaybeUninit::<&mut #dst_ty_for_impl>::uninit();
2909 (uninit.as_mut_ptr() as *mut *mut #dst_ty_for_impl)
2910 .write(::#prefix::ptr::from_raw_parts_mut(ptr as *mut (), len));
2911
2912 uninit
2913 });
2914
2915 (
2916 quote! {
2917 #[inline]
2918 pub fn fixed(&self) -> (& #sized_ty_for_impl, usize) {
2919 unsafe {
2920 let (ptr, len) = (self as *const Self).to_raw_parts();
2921 (&*(ptr as *const #sized_ty_for_impl), len)
2922 }
2923 }
2924
2925 #[inline]
2926 pub fn fixed_mut(&mut self) -> (&mut #sized_ty_for_impl, usize) {
2927 unsafe {
2928 let (ptr, len) = (self as *mut Self).to_raw_parts();
2929 (&mut *(ptr as *mut #sized_ty_for_impl), len)
2930 }
2931 }
2932 },
2933 quote! {
2934 pub unsafe fn flex_ref(&self, len: usize) -> &#dst_ty_for_impl {
2938 #flex_ref_inner
2940 }
2941
2942 #[inline]
2946 pub unsafe fn flex_ref_mut(&mut self, len: usize) -> &mut #dst_ty_for_impl {
2947 #flex_ref_mut_inner
2949 }
2950
2951 #[inline]
2956 pub unsafe fn flex_ptr<'unbounded>(ptr: *const Self, len: usize) -> &'unbounded #dst_ty_for_impl {
2957 #flex_ptr_inner
2958 }
2959
2960 #[inline]
2968 pub unsafe fn flex_ptr_mut<'unbounded>(
2969 ptr: *mut Self,
2970 len: usize,
2971 ) -> ::#prefix::mem::MaybeUninit<&'unbounded mut #dst_ty_for_impl> {
2972 #flex_ptr_mut_inner
2973 }
2974 },
2975 )
2976 } else {
2977 (quote!(), quote!())
2978 };
2979
2980 quote! {
2981 impl #impl_generics_labels #dst_ty_for_impl {
2982 #layout
2983 #from_ptr_dst
2984 }
2985
2986 impl #impl_generics_labels #sized_ty_for_impl {
2987 #from_ptr_sized
2988 }
2989 }
2990 }
2991}
2992
2993impl Method {
2994 fn codegen_method(
2995 &self,
2996 ctx: &BindgenContext,
2997 methods: &mut Vec<proc_macro2::TokenStream>,
2998 method_names: &mut HashSet<String>,
2999 result: &mut CodegenResult<'_>,
3000 _parent: &CompInfo,
3001 ) {
3002 assert!({
3003 let cc = &ctx.options().codegen_config;
3004 match self.kind() {
3005 MethodKind::Constructor => cc.constructors(),
3006 MethodKind::Destructor => cc.destructors(),
3007 MethodKind::VirtualDestructor { .. } => cc.destructors(),
3008 MethodKind::Static |
3009 MethodKind::Normal |
3010 MethodKind::Virtual { .. } => cc.methods(),
3011 }
3012 });
3013
3014 if self.is_virtual() {
3016 return; }
3018
3019 let function_item = ctx.resolve_item(self.signature());
3021 if !function_item.process_before_codegen(ctx, result) {
3022 return;
3023 }
3024 let function = function_item.expect_function();
3025 let times_seen = function.codegen(ctx, result, function_item);
3026 let Some(times_seen) = times_seen else { return };
3027 let signature_item = ctx.resolve_item(function.signature());
3028 let mut name = match self.kind() {
3029 MethodKind::Constructor => "new".into(),
3030 MethodKind::Destructor => "destruct".into(),
3031 _ => function.name().to_owned(),
3032 };
3033
3034 let TypeKind::Function(ref signature) =
3035 *signature_item.expect_type().kind()
3036 else {
3037 panic!("How in the world?")
3038 };
3039
3040 let supported_abi = signature.abi(ctx, Some(&*name)).is_ok();
3041 if !supported_abi {
3042 return;
3043 }
3044
3045 if signature.is_variadic() {
3048 return;
3049 }
3050
3051 if method_names.contains(&name) {
3052 let mut count = 1;
3053 let mut new_name;
3054
3055 while {
3056 new_name = format!("{name}{count}");
3057 method_names.contains(&new_name)
3058 } {
3059 count += 1;
3060 }
3061
3062 name = new_name;
3063 }
3064
3065 method_names.insert(name.clone());
3066
3067 let mut function_name = function_item.canonical_name(ctx);
3068 if times_seen > 0 {
3069 write!(&mut function_name, "{times_seen}").unwrap();
3070 }
3071 let function_name = ctx.rust_ident(function_name);
3072 let mut args = utils::fnsig_arguments(ctx, signature);
3073 let mut ret = utils::fnsig_return_ty(ctx, signature);
3074
3075 if !self.is_static() && !self.is_constructor() {
3076 args[0] = if self.is_const() {
3077 quote! { &self }
3078 } else {
3079 quote! { &mut self }
3080 };
3081 }
3082
3083 if self.is_constructor() {
3089 args.remove(0);
3090 ret = quote! { -> Self };
3091 }
3092
3093 let mut exprs =
3094 helpers::ast_ty::arguments_from_signature(signature, ctx);
3095
3096 let mut stmts = vec![];
3097
3098 if self.is_constructor() {
3101 let prefix = ctx.trait_prefix();
3102 let tmp_variable_decl = if ctx
3103 .options()
3104 .rust_features()
3105 .maybe_uninit
3106 {
3107 exprs[0] = quote! {
3108 __bindgen_tmp.as_mut_ptr()
3109 };
3110 quote! {
3111 let mut __bindgen_tmp = ::#prefix::mem::MaybeUninit::uninit()
3112 }
3113 } else {
3114 exprs[0] = quote! {
3115 &mut __bindgen_tmp
3116 };
3117 quote! {
3118 let mut __bindgen_tmp = ::#prefix::mem::uninitialized()
3119 }
3120 };
3121 stmts.push(tmp_variable_decl);
3122 } else if !self.is_static() {
3123 assert!(!exprs.is_empty());
3124 exprs[0] = quote! {
3125 self
3126 };
3127 };
3128
3129 let call = quote! {
3130 #function_name (#( #exprs ),* )
3131 };
3132
3133 stmts.push(call);
3134
3135 if self.is_constructor() {
3136 stmts.push(if ctx.options().rust_features().maybe_uninit {
3137 quote! {
3138 __bindgen_tmp.assume_init()
3139 }
3140 } else {
3141 quote! {
3142 __bindgen_tmp
3143 }
3144 });
3145 }
3146
3147 let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*));
3148
3149 let mut attrs = vec![attributes::inline()];
3150
3151 if signature.must_use() {
3152 attrs.push(attributes::must_use());
3153 }
3154
3155 let name = ctx.rust_ident(&name);
3156 methods.push(quote! {
3157 #(#attrs)*
3158 pub unsafe fn #name ( #( #args ),* ) #ret {
3159 #block
3160 }
3161 });
3162 }
3163}
3164
3165#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
3167pub enum EnumVariation {
3168 Rust {
3172 non_exhaustive: bool,
3174 },
3175 NewType {
3177 is_bitfield: bool,
3179 is_global: bool,
3181 },
3182 #[default]
3184 Consts,
3185 ModuleConsts,
3187}
3188
3189impl EnumVariation {
3190 fn is_rust(&self) -> bool {
3191 matches!(*self, EnumVariation::Rust { .. })
3192 }
3193
3194 fn is_const(&self) -> bool {
3197 matches!(*self, EnumVariation::Consts | EnumVariation::ModuleConsts)
3198 }
3199}
3200
3201impl fmt::Display for EnumVariation {
3202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3203 let s = match self {
3204 Self::Rust {
3205 non_exhaustive: false,
3206 } => "rust",
3207 Self::Rust {
3208 non_exhaustive: true,
3209 } => "rust_non_exhaustive",
3210 Self::NewType {
3211 is_bitfield: true, ..
3212 } => "bitfield",
3213 Self::NewType {
3214 is_bitfield: false,
3215 is_global,
3216 } => {
3217 if *is_global {
3218 "newtype_global"
3219 } else {
3220 "newtype"
3221 }
3222 }
3223 Self::Consts => "consts",
3224 Self::ModuleConsts => "moduleconsts",
3225 };
3226 s.fmt(f)
3227 }
3228}
3229
3230impl FromStr for EnumVariation {
3231 type Err = std::io::Error;
3232
3233 fn from_str(s: &str) -> Result<Self, Self::Err> {
3235 match s {
3236 "rust" => Ok(EnumVariation::Rust {
3237 non_exhaustive: false,
3238 }),
3239 "rust_non_exhaustive" => Ok(EnumVariation::Rust {
3240 non_exhaustive: true,
3241 }),
3242 "bitfield" => Ok(EnumVariation::NewType {
3243 is_bitfield: true,
3244 is_global: false,
3245 }),
3246 "consts" => Ok(EnumVariation::Consts),
3247 "moduleconsts" => Ok(EnumVariation::ModuleConsts),
3248 "newtype" => Ok(EnumVariation::NewType {
3249 is_bitfield: false,
3250 is_global: false,
3251 }),
3252 "newtype_global" => Ok(EnumVariation::NewType {
3253 is_bitfield: false,
3254 is_global: true,
3255 }),
3256 _ => Err(std::io::Error::new(
3257 std::io::ErrorKind::InvalidInput,
3258 concat!(
3259 "Got an invalid EnumVariation. Accepted values ",
3260 "are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',",
3261 "'moduleconsts', 'newtype' and 'newtype_global'."
3262 ),
3263 )),
3264 }
3265 }
3266}
3267
3268enum EnumBuilder<'a> {
3270 Rust {
3271 attrs: Vec<proc_macro2::TokenStream>,
3272 ident: Ident,
3273 tokens: proc_macro2::TokenStream,
3274 emitted_any_variants: bool,
3275 },
3276 NewType {
3277 canonical_name: &'a str,
3278 tokens: proc_macro2::TokenStream,
3279 is_bitfield: bool,
3280 is_global: bool,
3281 },
3282 Consts {
3283 variants: Vec<proc_macro2::TokenStream>,
3284 },
3285 ModuleConsts {
3286 module_name: &'a str,
3287 module_items: Vec<proc_macro2::TokenStream>,
3288 },
3289}
3290
3291impl<'a> EnumBuilder<'a> {
3292 fn is_rust_enum(&self) -> bool {
3294 matches!(*self, EnumBuilder::Rust { .. })
3295 }
3296
3297 fn new(
3300 name: &'a str,
3301 mut attrs: Vec<proc_macro2::TokenStream>,
3302 repr: syn::Type,
3303 enum_variation: EnumVariation,
3304 has_typedef: bool,
3305 ) -> Self {
3306 let ident = Ident::new(name, Span::call_site());
3307
3308 match enum_variation {
3309 EnumVariation::NewType {
3310 is_bitfield,
3311 is_global,
3312 } => EnumBuilder::NewType {
3313 canonical_name: name,
3314 tokens: quote! {
3315 #( #attrs )*
3316 pub struct #ident (pub #repr);
3317 },
3318 is_bitfield,
3319 is_global,
3320 },
3321
3322 EnumVariation::Rust { .. } => {
3323 attrs.insert(0, quote! { #[repr( #repr )] });
3325 let tokens = quote!();
3326 EnumBuilder::Rust {
3327 attrs,
3328 ident,
3329 tokens,
3330 emitted_any_variants: false,
3331 }
3332 }
3333
3334 EnumVariation::Consts => {
3335 let mut variants = Vec::new();
3336
3337 if !has_typedef {
3338 variants.push(quote! {
3339 #( #attrs )*
3340 pub type #ident = #repr;
3341 });
3342 }
3343
3344 EnumBuilder::Consts { variants }
3345 }
3346
3347 EnumVariation::ModuleConsts => {
3348 let ident = Ident::new(
3349 CONSTIFIED_ENUM_MODULE_REPR_NAME,
3350 Span::call_site(),
3351 );
3352 let type_definition = quote! {
3353 #( #attrs )*
3354 pub type #ident = #repr;
3355 };
3356
3357 EnumBuilder::ModuleConsts {
3358 module_name: name,
3359 module_items: vec![type_definition],
3360 }
3361 }
3362 }
3363 }
3364
3365 fn with_variant(
3367 self,
3368 ctx: &BindgenContext,
3369 variant: &EnumVariant,
3370 mangling_prefix: Option<&str>,
3371 rust_ty: syn::Type,
3372 result: &mut CodegenResult<'_>,
3373 is_ty_named: bool,
3374 ) -> Self {
3375 let variant_name = ctx.rust_mangle(variant.name());
3376 let is_rust_enum = self.is_rust_enum();
3377 let expr = match variant.val() {
3378 EnumVariantValue::Boolean(v) if is_rust_enum => {
3379 helpers::ast_ty::uint_expr(u64::from(v))
3380 }
3381 EnumVariantValue::Boolean(v) => quote!(#v),
3382 EnumVariantValue::Signed(v) => helpers::ast_ty::int_expr(v),
3383 EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
3384 };
3385
3386 let mut doc = quote! {};
3387 if ctx.options().generate_comments {
3388 if let Some(raw_comment) = variant.comment() {
3389 let comment = ctx.options().process_comment(raw_comment);
3390 doc = attributes::doc(comment);
3391 }
3392 }
3393
3394 match self {
3395 EnumBuilder::Rust {
3396 attrs,
3397 ident,
3398 tokens,
3399 emitted_any_variants: _,
3400 } => {
3401 let name = ctx.rust_ident(variant_name);
3402 EnumBuilder::Rust {
3403 attrs,
3404 ident,
3405 tokens: quote! {
3406 #tokens
3407 #doc
3408 #name = #expr,
3409 },
3410 emitted_any_variants: true,
3411 }
3412 }
3413
3414 EnumBuilder::NewType {
3415 canonical_name,
3416 is_global,
3417 ..
3418 } => {
3419 if is_ty_named && !is_global {
3420 let enum_ident = ctx.rust_ident(canonical_name);
3421 let variant_ident = ctx.rust_ident(variant_name);
3422
3423 result.push(quote! {
3424 impl #enum_ident {
3425 #doc
3426 pub const #variant_ident : #rust_ty = #rust_ty ( #expr );
3427 }
3428 });
3429 } else {
3430 let ident = ctx.rust_ident(match mangling_prefix {
3431 Some(prefix) => {
3432 Cow::Owned(format!("{prefix}_{variant_name}"))
3433 }
3434 None => variant_name,
3435 });
3436 result.push(quote! {
3437 #doc
3438 pub const #ident : #rust_ty = #rust_ty ( #expr );
3439 });
3440 }
3441
3442 self
3443 }
3444
3445 EnumBuilder::Consts { .. } => {
3446 let constant_name = match mangling_prefix {
3447 Some(prefix) => {
3448 Cow::Owned(format!("{prefix}_{variant_name}"))
3449 }
3450 None => variant_name,
3451 };
3452
3453 let ident = ctx.rust_ident(constant_name);
3454 result.push(quote! {
3455 #doc
3456 pub const #ident : #rust_ty = #expr ;
3457 });
3458
3459 self
3460 }
3461 EnumBuilder::ModuleConsts {
3462 module_name,
3463 mut module_items,
3464 } => {
3465 let name = ctx.rust_ident(variant_name);
3466 let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME);
3467 module_items.push(quote! {
3468 #doc
3469 pub const #name : #ty = #expr ;
3470 });
3471
3472 EnumBuilder::ModuleConsts {
3473 module_name,
3474 module_items,
3475 }
3476 }
3477 }
3478 }
3479
3480 fn build(
3481 self,
3482 ctx: &BindgenContext,
3483 rust_ty: syn::Type,
3484 result: &mut CodegenResult<'_>,
3485 ) -> proc_macro2::TokenStream {
3486 match self {
3487 EnumBuilder::Rust {
3488 attrs,
3489 ident,
3490 tokens,
3491 emitted_any_variants,
3492 ..
3493 } => {
3494 let variants = if emitted_any_variants {
3495 tokens
3496 } else {
3497 quote!(__bindgen_cannot_repr_c_on_empty_enum = 0)
3498 };
3499
3500 quote! {
3501 #( #attrs )*
3502 pub enum #ident {
3503 #variants
3504 }
3505 }
3506 }
3507 EnumBuilder::NewType {
3508 canonical_name,
3509 tokens,
3510 is_bitfield,
3511 ..
3512 } => {
3513 if !is_bitfield {
3514 return tokens;
3515 }
3516
3517 let rust_ty_name = ctx.rust_ident_raw(canonical_name);
3518 let prefix = ctx.trait_prefix();
3519
3520 result.push(quote! {
3521 impl ::#prefix::ops::BitOr<#rust_ty> for #rust_ty {
3522 type Output = Self;
3523
3524 #[inline]
3525 fn bitor(self, other: Self) -> Self {
3526 #rust_ty_name(self.0 | other.0)
3527 }
3528 }
3529 });
3530
3531 result.push(quote! {
3532 impl ::#prefix::ops::BitOrAssign for #rust_ty {
3533 #[inline]
3534 fn bitor_assign(&mut self, rhs: #rust_ty) {
3535 self.0 |= rhs.0;
3536 }
3537 }
3538 });
3539
3540 result.push(quote! {
3541 impl ::#prefix::ops::BitAnd<#rust_ty> for #rust_ty {
3542 type Output = Self;
3543
3544 #[inline]
3545 fn bitand(self, other: Self) -> Self {
3546 #rust_ty_name(self.0 & other.0)
3547 }
3548 }
3549 });
3550
3551 result.push(quote! {
3552 impl ::#prefix::ops::BitAndAssign for #rust_ty {
3553 #[inline]
3554 fn bitand_assign(&mut self, rhs: #rust_ty) {
3555 self.0 &= rhs.0;
3556 }
3557 }
3558 });
3559
3560 tokens
3561 }
3562 EnumBuilder::Consts { variants, .. } => quote! { #( #variants )* },
3563 EnumBuilder::ModuleConsts {
3564 module_items,
3565 module_name,
3566 ..
3567 } => {
3568 let ident = ctx.rust_ident(module_name);
3569 quote! {
3570 pub mod #ident {
3571 #( #module_items )*
3572 }
3573 }
3574 }
3575 }
3576 }
3577}
3578
3579impl CodeGenerator for Enum {
3580 type Extra = Item;
3581 type Return = ();
3582
3583 fn codegen(
3584 &self,
3585 ctx: &BindgenContext,
3586 result: &mut CodegenResult<'_>,
3587 item: &Item,
3588 ) {
3589 debug!("<Enum as CodeGenerator>::codegen: item = {item:?}");
3590 debug_assert!(item.is_enabled_for_codegen(ctx));
3591
3592 let name = item.canonical_name(ctx);
3593 let ident = ctx.rust_ident(&name);
3594 let enum_ty = item.expect_type();
3595 let layout = enum_ty.layout(ctx);
3596 let variation = self.computed_enum_variation(ctx, item);
3597
3598 let repr_translated;
3599 let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) {
3600 Some(repr)
3601 if !ctx.options().translate_enum_integer_types &&
3602 !variation.is_rust() =>
3603 {
3604 repr
3605 }
3606 repr => {
3607 let kind = if let Some(repr) = repr {
3615 match *repr.canonical_type(ctx).kind() {
3616 TypeKind::Int(int_kind) => int_kind,
3617 _ => panic!("Unexpected type as enum repr"),
3618 }
3619 } else {
3620 warn!(
3621 "Guessing type of enum! Forward declarations of enums \
3622 shouldn't be legal!"
3623 );
3624 IntKind::Int
3625 };
3626
3627 let signed = kind.is_signed();
3628 let size = layout
3629 .map(|l| l.size)
3630 .or_else(|| kind.known_size())
3631 .unwrap_or(0);
3632
3633 let translated = match (signed, size) {
3634 (true, 1) => IntKind::I8,
3635 (false, 1) => IntKind::U8,
3636 (true, 2) => IntKind::I16,
3637 (false, 2) => IntKind::U16,
3638 (true, 4) => IntKind::I32,
3639 (false, 4) => IntKind::U32,
3640 (true, 8) => IntKind::I64,
3641 (false, 8) => IntKind::U64,
3642 _ => {
3643 warn!(
3644 "invalid enum decl: signed: {signed}, size: {size}"
3645 );
3646 IntKind::I32
3647 }
3648 };
3649
3650 repr_translated =
3651 Type::new(None, None, TypeKind::Int(translated), false);
3652 &repr_translated
3653 }
3654 };
3655
3656 let mut attrs = vec![];
3657
3658 match variation {
3660 EnumVariation::Rust { non_exhaustive } => {
3661 if non_exhaustive &&
3662 ctx.options().rust_features().non_exhaustive
3663 {
3664 attrs.push(attributes::non_exhaustive());
3665 } else if non_exhaustive &&
3666 !ctx.options().rust_features().non_exhaustive
3667 {
3668 panic!("The rust target you're using doesn't seem to support non_exhaustive enums");
3669 }
3670 }
3671 EnumVariation::NewType { .. } => {
3672 if true {
3673 attrs.push(attributes::repr("transparent"));
3674 } else {
3675 attrs.push(attributes::repr("C"));
3676 }
3677 }
3678 _ => {}
3679 };
3680
3681 if let Some(comment) = item.comment(ctx) {
3682 attrs.push(attributes::doc(comment));
3683 }
3684
3685 if item.must_use(ctx) {
3686 attrs.push(attributes::must_use());
3687 }
3688
3689 if !variation.is_const() {
3690 let packed = false; let mut derives = derives_of_item(item, ctx, packed);
3692 derives.insert(
3696 DerivableTraits::CLONE |
3697 DerivableTraits::HASH |
3698 DerivableTraits::PARTIAL_EQ |
3699 DerivableTraits::EQ,
3700 );
3701 let mut derives: Vec<_> = derives.into();
3702 for derive in item.annotations().derives() {
3703 if !derives.contains(&derive.as_str()) {
3704 derives.push(derive);
3705 }
3706 }
3707
3708 let custom_derives = ctx.options().all_callbacks(|cb| {
3711 cb.add_derives(&DeriveInfo {
3712 name: &name,
3713 kind: DeriveTypeKind::Enum,
3714 })
3715 });
3716 derives.extend(custom_derives.iter().map(|s| s.as_str()));
3718
3719 attrs.extend(
3720 item.annotations()
3721 .attributes()
3722 .iter()
3723 .map(|s| s.parse().unwrap()),
3724 );
3725
3726 let custom_attributes = ctx.options().all_callbacks(|cb| {
3729 cb.add_attributes(&AttributeInfo {
3730 name: &name,
3731 kind: DeriveTypeKind::Enum,
3732 })
3733 });
3734 attrs.extend(custom_attributes.iter().map(|s| s.parse().unwrap()));
3735
3736 attrs.push(attributes::derives(&derives));
3737 }
3738
3739 fn add_constant(
3740 ctx: &BindgenContext,
3741 enum_: &Type,
3742 enum_canonical_name: &Ident,
3744 variant_name: &Ident,
3748 referenced_name: &Ident,
3749 enum_rust_ty: syn::Type,
3750 result: &mut CodegenResult<'_>,
3751 ) {
3752 let constant_name = if enum_.name().is_some() {
3753 if ctx.options().prepend_enum_name {
3754 format!("{enum_canonical_name}_{variant_name}")
3755 } else {
3756 format!("{variant_name}")
3757 }
3758 } else {
3759 format!("{variant_name}")
3760 };
3761 let constant_name = ctx.rust_ident(constant_name);
3762
3763 result.push(quote! {
3764 pub const #constant_name : #enum_rust_ty =
3765 #enum_canonical_name :: #referenced_name ;
3766 });
3767 }
3768
3769 let repr = repr.to_rust_ty_or_opaque(ctx, item);
3770 let has_typedef = ctx.is_enum_typedef_combo(item.id());
3771
3772 let mut builder =
3773 EnumBuilder::new(&name, attrs, repr, variation, has_typedef);
3774
3775 let mut seen_values = HashMap::<_, Ident>::default();
3777 let enum_rust_ty = item.to_rust_ty_or_opaque(ctx, &());
3778 let is_toplevel = item.is_toplevel(ctx);
3779
3780 let parent_canonical_name = if is_toplevel {
3782 None
3783 } else {
3784 Some(item.parent_id().canonical_name(ctx))
3785 };
3786
3787 let constant_mangling_prefix = if ctx.options().prepend_enum_name {
3788 if enum_ty.name().is_none() {
3789 parent_canonical_name.as_deref()
3790 } else {
3791 Some(&*name)
3792 }
3793 } else {
3794 None
3795 };
3796
3797 let mut constified_variants = VecDeque::new();
3801
3802 let mut iter = self.variants().iter().peekable();
3803 while let Some(variant) =
3804 iter.next().or_else(|| constified_variants.pop_front())
3805 {
3806 if variant.hidden() {
3807 continue;
3808 }
3809
3810 if variant.force_constification() && iter.peek().is_some() {
3811 constified_variants.push_back(variant);
3812 continue;
3813 }
3814
3815 match seen_values.entry(variant.val()) {
3816 Entry::Occupied(ref entry) => {
3817 if variation.is_rust() {
3818 let variant_name = ctx.rust_mangle(variant.name());
3819 let mangled_name = if is_toplevel ||
3820 enum_ty.name().is_some()
3821 {
3822 variant_name
3823 } else {
3824 let parent_name =
3825 parent_canonical_name.as_ref().unwrap();
3826
3827 Cow::Owned(format!("{parent_name}_{variant_name}"))
3828 };
3829
3830 let existing_variant_name = entry.get();
3831 if enum_ty.name().is_some() {
3833 let enum_canonical_name = &ident;
3834 let variant_name =
3835 ctx.rust_ident_raw(&*mangled_name);
3836 result.push(quote! {
3837 impl #enum_rust_ty {
3838 pub const #variant_name : #enum_rust_ty =
3839 #enum_canonical_name :: #existing_variant_name ;
3840 }
3841 });
3842 } else {
3843 add_constant(
3844 ctx,
3845 enum_ty,
3846 &ident,
3847 &Ident::new(&mangled_name, Span::call_site()),
3848 existing_variant_name,
3849 enum_rust_ty.clone(),
3850 result,
3851 );
3852 }
3853 } else {
3854 builder = builder.with_variant(
3855 ctx,
3856 variant,
3857 constant_mangling_prefix,
3858 enum_rust_ty.clone(),
3859 result,
3860 enum_ty.name().is_some(),
3861 );
3862 }
3863 }
3864 Entry::Vacant(entry) => {
3865 builder = builder.with_variant(
3866 ctx,
3867 variant,
3868 constant_mangling_prefix,
3869 enum_rust_ty.clone(),
3870 result,
3871 enum_ty.name().is_some(),
3872 );
3873
3874 let variant_name = ctx.rust_ident(variant.name());
3875
3876 if (variation.is_rust() && enum_ty.name().is_none()) ||
3880 variant.force_constification()
3881 {
3882 let mangled_name = if is_toplevel {
3883 variant_name.clone()
3884 } else {
3885 let parent_name =
3886 parent_canonical_name.as_ref().unwrap();
3887
3888 Ident::new(
3889 &format!("{parent_name}_{variant_name}"),
3890 Span::call_site(),
3891 )
3892 };
3893
3894 add_constant(
3895 ctx,
3896 enum_ty,
3897 &ident,
3898 &mangled_name,
3899 &variant_name,
3900 enum_rust_ty.clone(),
3901 result,
3902 );
3903 }
3904
3905 entry.insert(variant_name);
3906 }
3907 }
3908 }
3909
3910 let item = builder.build(ctx, enum_rust_ty, result);
3911 result.push(item);
3912 }
3913}
3914
3915#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
3917pub enum MacroTypeVariation {
3918 Signed,
3920 #[default]
3922 Unsigned,
3923}
3924
3925impl fmt::Display for MacroTypeVariation {
3926 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3927 let s = match self {
3928 Self::Signed => "signed",
3929 Self::Unsigned => "unsigned",
3930 };
3931 s.fmt(f)
3932 }
3933}
3934
3935impl FromStr for MacroTypeVariation {
3936 type Err = std::io::Error;
3937
3938 fn from_str(s: &str) -> Result<Self, Self::Err> {
3940 match s {
3941 "signed" => Ok(MacroTypeVariation::Signed),
3942 "unsigned" => Ok(MacroTypeVariation::Unsigned),
3943 _ => Err(std::io::Error::new(
3944 std::io::ErrorKind::InvalidInput,
3945 concat!(
3946 "Got an invalid MacroTypeVariation. Accepted values ",
3947 "are 'signed' and 'unsigned'"
3948 ),
3949 )),
3950 }
3951 }
3952}
3953
3954#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
3956pub enum AliasVariation {
3957 #[default]
3959 TypeAlias,
3960 NewType,
3962 NewTypeDeref,
3964}
3965
3966impl fmt::Display for AliasVariation {
3967 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3968 let s = match self {
3969 Self::TypeAlias => "type_alias",
3970 Self::NewType => "new_type",
3971 Self::NewTypeDeref => "new_type_deref",
3972 };
3973
3974 s.fmt(f)
3975 }
3976}
3977
3978impl FromStr for AliasVariation {
3979 type Err = std::io::Error;
3980
3981 fn from_str(s: &str) -> Result<Self, Self::Err> {
3983 match s {
3984 "type_alias" => Ok(AliasVariation::TypeAlias),
3985 "new_type" => Ok(AliasVariation::NewType),
3986 "new_type_deref" => Ok(AliasVariation::NewTypeDeref),
3987 _ => Err(std::io::Error::new(
3988 std::io::ErrorKind::InvalidInput,
3989 concat!(
3990 "Got an invalid AliasVariation. Accepted values ",
3991 "are 'type_alias', 'new_type', and 'new_type_deref'"
3992 ),
3993 )),
3994 }
3995 }
3996}
3997
3998#[derive(Copy, Clone, PartialEq, Eq, Debug)]
4000pub enum NonCopyUnionStyle {
4001 BindgenWrapper,
4003 ManuallyDrop,
4008}
4009
4010impl fmt::Display for NonCopyUnionStyle {
4011 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
4012 let s = match self {
4013 Self::BindgenWrapper => "bindgen_wrapper",
4014 Self::ManuallyDrop => "manually_drop",
4015 };
4016
4017 s.fmt(f)
4018 }
4019}
4020
4021impl Default for NonCopyUnionStyle {
4022 fn default() -> Self {
4023 Self::BindgenWrapper
4024 }
4025}
4026
4027impl FromStr for NonCopyUnionStyle {
4028 type Err = std::io::Error;
4029
4030 fn from_str(s: &str) -> Result<Self, Self::Err> {
4031 match s {
4032 "bindgen_wrapper" => Ok(Self::BindgenWrapper),
4033 "manually_drop" => Ok(Self::ManuallyDrop),
4034 _ => Err(std::io::Error::new(
4035 std::io::ErrorKind::InvalidInput,
4036 concat!(
4037 "Got an invalid NonCopyUnionStyle. Accepted values ",
4038 "are 'bindgen_wrapper' and 'manually_drop'"
4039 ),
4040 )),
4041 }
4042 }
4043}
4044
4045pub(crate) trait TryToOpaque {
4051 type Extra;
4052
4053 fn try_get_layout(
4055 &self,
4056 ctx: &BindgenContext,
4057 extra: &Self::Extra,
4058 ) -> error::Result<Layout>;
4059
4060 fn try_to_opaque(
4062 &self,
4063 ctx: &BindgenContext,
4064 extra: &Self::Extra,
4065 ) -> error::Result<syn::Type> {
4066 self.try_get_layout(ctx, extra)
4067 .map(|layout| helpers::blob(ctx, layout, true))
4068 }
4069}
4070
4071pub(crate) trait ToOpaque: TryToOpaque {
4082 fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout {
4083 self.try_get_layout(ctx, extra)
4084 .unwrap_or_else(|_| Layout::for_size(ctx, 1))
4085 }
4086
4087 fn to_opaque(
4088 &self,
4089 ctx: &BindgenContext,
4090 extra: &Self::Extra,
4091 ) -> syn::Type {
4092 let layout = self.get_layout(ctx, extra);
4093 helpers::blob(ctx, layout, true)
4094 }
4095}
4096
4097impl<T> ToOpaque for T where T: TryToOpaque {}
4098
4099pub(crate) trait TryToRustTy {
4107 type Extra;
4108
4109 fn try_to_rust_ty(
4110 &self,
4111 ctx: &BindgenContext,
4112 extra: &Self::Extra,
4113 ) -> error::Result<syn::Type>;
4114}
4115
4116pub(crate) trait TryToRustTyOrOpaque: TryToRustTy + TryToOpaque {
4122 type Extra;
4123
4124 fn try_to_rust_ty_or_opaque(
4125 &self,
4126 ctx: &BindgenContext,
4127 extra: &<Self as TryToRustTyOrOpaque>::Extra,
4128 ) -> error::Result<syn::Type>;
4129}
4130
4131impl<E, T> TryToRustTyOrOpaque for T
4132where
4133 T: TryToRustTy<Extra = E> + TryToOpaque<Extra = E>,
4134{
4135 type Extra = E;
4136
4137 fn try_to_rust_ty_or_opaque(
4138 &self,
4139 ctx: &BindgenContext,
4140 extra: &E,
4141 ) -> error::Result<syn::Type> {
4142 self.try_to_rust_ty(ctx, extra).or_else(|_| {
4143 if let Ok(layout) = self.try_get_layout(ctx, extra) {
4144 Ok(helpers::blob(ctx, layout, true))
4145 } else {
4146 Err(Error::NoLayoutForOpaqueBlob)
4147 }
4148 })
4149 }
4150}
4151
4152pub(crate) trait ToRustTyOrOpaque: TryToRustTy + ToOpaque {
4170 type Extra;
4171
4172 fn to_rust_ty_or_opaque(
4173 &self,
4174 ctx: &BindgenContext,
4175 extra: &<Self as ToRustTyOrOpaque>::Extra,
4176 ) -> syn::Type;
4177}
4178
4179impl<E, T> ToRustTyOrOpaque for T
4180where
4181 T: TryToRustTy<Extra = E> + ToOpaque<Extra = E>,
4182{
4183 type Extra = E;
4184
4185 fn to_rust_ty_or_opaque(
4186 &self,
4187 ctx: &BindgenContext,
4188 extra: &E,
4189 ) -> syn::Type {
4190 self.try_to_rust_ty(ctx, extra)
4191 .unwrap_or_else(|_| self.to_opaque(ctx, extra))
4192 }
4193}
4194
4195impl<T> TryToOpaque for T
4196where
4197 T: Copy + Into<ItemId>,
4198{
4199 type Extra = ();
4200
4201 fn try_get_layout(
4202 &self,
4203 ctx: &BindgenContext,
4204 _: &(),
4205 ) -> error::Result<Layout> {
4206 ctx.resolve_item((*self).into()).try_get_layout(ctx, &())
4207 }
4208}
4209
4210impl<T> TryToRustTy for T
4211where
4212 T: Copy + Into<ItemId>,
4213{
4214 type Extra = ();
4215
4216 fn try_to_rust_ty(
4217 &self,
4218 ctx: &BindgenContext,
4219 _: &(),
4220 ) -> error::Result<syn::Type> {
4221 ctx.resolve_item((*self).into()).try_to_rust_ty(ctx, &())
4222 }
4223}
4224
4225impl TryToOpaque for Item {
4226 type Extra = ();
4227
4228 fn try_get_layout(
4229 &self,
4230 ctx: &BindgenContext,
4231 _: &(),
4232 ) -> error::Result<Layout> {
4233 self.kind().expect_type().try_get_layout(ctx, self)
4234 }
4235}
4236
4237impl TryToRustTy for Item {
4238 type Extra = ();
4239
4240 fn try_to_rust_ty(
4241 &self,
4242 ctx: &BindgenContext,
4243 _: &(),
4244 ) -> error::Result<syn::Type> {
4245 self.kind().expect_type().try_to_rust_ty(ctx, self)
4246 }
4247}
4248
4249impl TryToOpaque for Type {
4250 type Extra = Item;
4251
4252 fn try_get_layout(
4253 &self,
4254 ctx: &BindgenContext,
4255 _: &Item,
4256 ) -> error::Result<Layout> {
4257 self.layout(ctx).ok_or(Error::NoLayoutForOpaqueBlob)
4258 }
4259}
4260
4261impl TryToRustTy for Type {
4262 type Extra = Item;
4263
4264 fn try_to_rust_ty(
4265 &self,
4266 ctx: &BindgenContext,
4267 item: &Item,
4268 ) -> error::Result<syn::Type> {
4269 use self::helpers::ast_ty::*;
4270
4271 match *self.kind() {
4272 TypeKind::Void => Ok(c_void(ctx)),
4273 TypeKind::NullPtr => Ok(c_void(ctx).to_ptr(true)),
4276 TypeKind::Int(ik) => {
4277 Ok(int_kind_rust_type(ctx, ik, self.layout(ctx)))
4278 }
4279 TypeKind::Float(fk) => {
4280 Ok(float_kind_rust_type(ctx, fk, self.layout(ctx)))
4281 }
4282 TypeKind::Complex(fk) => {
4283 let float_path =
4284 float_kind_rust_type(ctx, fk, self.layout(ctx));
4285
4286 ctx.generated_bindgen_complex();
4287 Ok(if ctx.options().enable_cxx_namespaces {
4288 syn::parse_quote! { root::__BindgenComplex<#float_path> }
4289 } else {
4290 syn::parse_quote! { __BindgenComplex<#float_path> }
4291 })
4292 }
4293 TypeKind::Function(ref signature) => {
4294 let ty = signature.try_to_rust_ty(ctx, item)?;
4299
4300 let prefix = ctx.trait_prefix();
4301 Ok(syn::parse_quote! { ::#prefix::option::Option<#ty> })
4302 }
4303 TypeKind::Array(item, len) | TypeKind::Vector(item, len) => {
4304 let ty = item.try_to_rust_ty(ctx, &())?;
4305 Ok(syn::parse_quote! { [ #ty ; #len ] })
4306 }
4307 TypeKind::Enum(..) => {
4308 let path = item.namespace_aware_canonical_path(ctx);
4309 let path = proc_macro2::TokenStream::from_str(&path.join("::"))
4310 .unwrap();
4311 Ok(syn::parse_quote!(#path))
4312 }
4313 TypeKind::TemplateInstantiation(ref inst) => {
4314 inst.try_to_rust_ty(ctx, item)
4315 }
4316 TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
4317 TypeKind::TemplateAlias(..) |
4318 TypeKind::Alias(..) |
4319 TypeKind::BlockPointer(..) => {
4320 if self.is_block_pointer() && !ctx.options().generate_block {
4321 let void = c_void(ctx);
4322 return Ok(void.to_ptr(false));
4323 }
4324
4325 if item.is_opaque(ctx, &()) &&
4326 item.used_template_params(ctx)
4327 .into_iter()
4328 .any(|param| param.is_template_param(ctx, &()))
4329 {
4330 self.try_to_opaque(ctx, item)
4331 } else if let Some(ty) = self
4332 .name()
4333 .and_then(|name| utils::type_from_named(ctx, name))
4334 {
4335 Ok(ty)
4336 } else {
4337 utils::build_path(item, ctx)
4338 }
4339 }
4340 TypeKind::Comp(ref info) => {
4341 let template_params = item.all_template_params(ctx);
4342 if info.has_non_type_template_params() ||
4343 (item.is_opaque(ctx, &()) && !template_params.is_empty())
4344 {
4345 return self.try_to_opaque(ctx, item);
4346 }
4347
4348 utils::build_path(item, ctx)
4349 }
4350 TypeKind::Opaque => self.try_to_opaque(ctx, item),
4351 TypeKind::Pointer(inner) | TypeKind::Reference(inner) => {
4352 let size = self.get_layout(ctx, item).size;
4354 if size != ctx.target_pointer_size() {
4355 return Err(Error::InvalidPointerSize {
4356 ty_name: self.name().unwrap_or("unknown").into(),
4357 ty_size: size,
4358 ptr_size: ctx.target_pointer_size(),
4359 });
4360 }
4361
4362 let is_const = ctx.resolve_type(inner).is_const();
4363
4364 let inner =
4365 inner.into_resolver().through_type_refs().resolve(ctx);
4366 let inner_ty = inner.expect_type();
4367
4368 let is_objc_pointer =
4369 matches!(inner_ty.kind(), TypeKind::ObjCInterface(..));
4370
4371 let ty = inner
4375 .to_rust_ty_or_opaque(ctx, &())
4376 .with_implicit_template_params(ctx, inner);
4377
4378 if inner_ty.canonical_type(ctx).is_function() || is_objc_pointer
4381 {
4382 Ok(ty)
4383 } else {
4384 Ok(ty.to_ptr(is_const))
4385 }
4386 }
4387 TypeKind::TypeParam => {
4388 let name = item.canonical_name(ctx);
4389 let ident = ctx.rust_ident(name);
4390 Ok(syn::parse_quote! { #ident })
4391 }
4392 TypeKind::ObjCSel => Ok(syn::parse_quote! { objc::runtime::Sel }),
4393 TypeKind::ObjCId => Ok(syn::parse_quote! { id }),
4394 TypeKind::ObjCInterface(ref interface) => {
4395 let name = ctx.rust_ident(interface.name());
4396 Ok(syn::parse_quote! { #name })
4397 }
4398 ref u @ TypeKind::UnresolvedTypeRef(..) => {
4399 unreachable!("Should have been resolved after parsing {u:?}!")
4400 }
4401 }
4402 }
4403}
4404
4405impl TryToOpaque for TemplateInstantiation {
4406 type Extra = Item;
4407
4408 fn try_get_layout(
4409 &self,
4410 ctx: &BindgenContext,
4411 item: &Item,
4412 ) -> error::Result<Layout> {
4413 item.expect_type()
4414 .layout(ctx)
4415 .ok_or(Error::NoLayoutForOpaqueBlob)
4416 }
4417}
4418
4419impl TryToRustTy for TemplateInstantiation {
4420 type Extra = Item;
4421
4422 fn try_to_rust_ty(
4423 &self,
4424 ctx: &BindgenContext,
4425 item: &Item,
4426 ) -> error::Result<syn::Type> {
4427 if self.is_opaque(ctx, item) {
4428 return Err(Error::InstantiationOfOpaqueType);
4429 }
4430
4431 let def = self
4432 .template_definition()
4433 .into_resolver()
4434 .through_type_refs()
4435 .resolve(ctx);
4436
4437 let mut ty = quote! {};
4438 let def_path = def.namespace_aware_canonical_path(ctx);
4439 ty.append_separated(
4440 def_path.into_iter().map(|p| ctx.rust_ident(p)),
4441 quote!(::),
4442 );
4443
4444 let def_params = def.self_template_params(ctx);
4445 if def_params.is_empty() {
4446 extra_assert!(def.is_opaque(ctx, &()));
4450 return Err(Error::InstantiationOfOpaqueType);
4451 }
4452
4453 let template_args = self
4462 .template_arguments()
4463 .iter()
4464 .zip(def_params.iter())
4465 .filter(|&(_, param)| ctx.uses_template_parameter(def.id(), *param))
4468 .map(|(arg, _)| {
4469 let arg = arg.into_resolver().through_type_refs().resolve(ctx);
4470 let ty = arg
4471 .try_to_rust_ty(ctx, &())?
4472 .with_implicit_template_params(ctx, arg);
4473 Ok(ty)
4474 })
4475 .collect::<error::Result<Vec<_>>>()?;
4476
4477 Ok(if template_args.is_empty() {
4478 syn::parse_quote! { #ty }
4479 } else {
4480 syn::parse_quote! { #ty<#(#template_args),*> }
4481 })
4482 }
4483}
4484
4485impl TryToRustTy for FunctionSig {
4486 type Extra = Item;
4487
4488 fn try_to_rust_ty(
4489 &self,
4490 ctx: &BindgenContext,
4491 item: &Item,
4492 ) -> error::Result<syn::Type> {
4493 let ret = utils::fnsig_return_ty(ctx, self);
4495 let arguments = utils::fnsig_arguments(ctx, self);
4496
4497 match self.abi(ctx, None) {
4498 Ok(abi) => Ok(
4499 syn::parse_quote! { unsafe extern #abi fn ( #( #arguments ),* ) #ret },
4500 ),
4501 Err(err) => {
4502 if matches!(err, Error::UnsupportedAbi(_)) {
4503 unsupported_abi_diagnostic(
4504 self.name(),
4505 self.is_variadic(),
4506 item.location(),
4507 ctx,
4508 &err,
4509 );
4510 }
4511
4512 Err(err)
4513 }
4514 }
4515 }
4516}
4517
4518impl CodeGenerator for Function {
4519 type Extra = Item;
4520
4521 type Return = Option<u32>;
4524
4525 fn codegen(
4526 &self,
4527 ctx: &BindgenContext,
4528 result: &mut CodegenResult<'_>,
4529 item: &Item,
4530 ) -> Self::Return {
4531 debug!("<Function as CodeGenerator>::codegen: item = {item:?}");
4532 debug_assert!(item.is_enabled_for_codegen(ctx));
4533
4534 let is_internal = matches!(self.linkage(), Linkage::Internal);
4535
4536 let signature_item = ctx.resolve_item(self.signature());
4537 let signature = signature_item.kind().expect_type().canonical_type(ctx);
4538 let TypeKind::Function(ref signature) = *signature.kind() else {
4539 panic!("Signature kind is not a Function: {signature:?}")
4540 };
4541
4542 if is_internal {
4543 if !ctx.options().wrap_static_fns {
4544 return None;
4547 }
4548
4549 if signature.is_variadic() {
4550 variadic_fn_diagnostic(self.name(), item.location(), ctx);
4553 return None;
4554 }
4555 }
4556
4557 let is_dynamic_function = match self.kind() {
4560 FunctionKind::Method(ref method_kind)
4561 if method_kind.is_pure_virtual() =>
4562 {
4563 return None;
4564 }
4565 FunctionKind::Function => {
4566 ctx.options().dynamic_library_name.is_some()
4567 }
4568 _ => false,
4569 };
4570
4571 if !item.all_template_params(ctx).is_empty() {
4576 return None;
4577 }
4578
4579 let name = self.name();
4580 let mut canonical_name = item.canonical_name(ctx);
4581 let mangled_name = self.mangled_name();
4582
4583 {
4584 let seen_symbol_name = mangled_name.unwrap_or(&canonical_name);
4585
4586 if result.seen_function(seen_symbol_name) {
4589 return None;
4590 }
4591 result.saw_function(seen_symbol_name);
4592 }
4593
4594 let mut attributes = vec![];
4595
4596 if true {
4597 let must_use = signature.must_use() || {
4598 let ret_ty = signature
4599 .return_type()
4600 .into_resolver()
4601 .through_type_refs()
4602 .resolve(ctx);
4603 ret_ty.must_use(ctx)
4604 };
4605
4606 if must_use {
4607 attributes.push(attributes::must_use());
4608 }
4609 }
4610
4611 if let Some(comment) = item.comment(ctx) {
4612 attributes.push(attributes::doc(comment));
4613 }
4614
4615 let abi = match signature.abi(ctx, Some(name)) {
4616 Err(err) => {
4617 if matches!(err, Error::UnsupportedAbi(_)) {
4618 unsupported_abi_diagnostic(
4619 name,
4620 signature.is_variadic(),
4621 item.location(),
4622 ctx,
4623 &err,
4624 );
4625 }
4626
4627 return None;
4628 }
4629 Ok(ClangAbi::Unknown(unknown_abi)) => {
4630 panic!(
4631 "Invalid or unknown abi {unknown_abi:?} for function {canonical_name:?} ({self:?})"
4632 );
4633 }
4634 Ok(abi) => abi,
4635 };
4636
4637 let times_seen = result.overload_number(&canonical_name);
4640 if times_seen > 0 {
4641 write!(&mut canonical_name, "{times_seen}").unwrap();
4642 }
4643
4644 let mut has_link_name_attr = false;
4645 if let Some(link_name) = self.link_name() {
4646 attributes.push(attributes::link_name::<false>(link_name));
4647 has_link_name_attr = true;
4648 } else {
4649 let link_name = mangled_name.unwrap_or(name);
4650 if !is_dynamic_function &&
4651 !utils::names_will_be_identical_after_mangling(
4652 &canonical_name,
4653 link_name,
4654 Some(abi),
4655 )
4656 {
4657 attributes.push(attributes::link_name::<false>(link_name));
4658 has_link_name_attr = true;
4659 }
4660 }
4661
4662 let wasm_link_attribute =
4666 ctx.options().wasm_import_module_name.as_ref().map(|name| {
4667 quote! { #[link(wasm_import_module = #name)] }
4668 });
4669
4670 let should_wrap =
4671 is_internal && ctx.options().wrap_static_fns && !has_link_name_attr;
4672
4673 if should_wrap {
4674 let name = canonical_name.clone() + ctx.wrap_static_fns_suffix();
4675 attributes.push(attributes::link_name::<true>(&name));
4676 }
4677
4678 let wrap_as_variadic = if should_wrap && !signature.is_variadic() {
4679 utils::wrap_as_variadic_fn(ctx, signature, name)
4680 } else {
4681 None
4682 };
4683
4684 let (ident, args) = if let Some(WrapAsVariadic {
4685 idx_of_va_list_arg,
4686 new_name,
4687 }) = &wrap_as_variadic
4688 {
4689 (
4690 new_name,
4691 utils::fnsig_arguments_iter(
4692 ctx,
4693 signature.argument_types().iter().enumerate().filter_map(
4695 |(idx, t)| {
4696 if idx == *idx_of_va_list_arg {
4697 None
4698 } else {
4699 Some(t)
4700 }
4701 },
4702 ),
4703 true,
4705 ),
4706 )
4707 } else {
4708 (&canonical_name, utils::fnsig_arguments(ctx, signature))
4709 };
4710 let ret = utils::fnsig_return_ty(ctx, signature);
4711
4712 let ident = ctx.rust_ident(ident);
4713
4714 let safety = ctx
4715 .options()
4716 .rust_features
4717 .unsafe_extern_blocks
4718 .then(|| quote!(unsafe));
4719
4720 let tokens = quote! {
4721 #wasm_link_attribute
4722 #safety extern #abi {
4723 #(#attributes)*
4724 pub fn #ident ( #( #args ),* ) #ret;
4725 }
4726 };
4727
4728 if should_wrap {
4730 result
4731 .items_to_serialize
4732 .push((item.id(), wrap_as_variadic));
4733 }
4734
4735 if is_dynamic_function {
4737 let args_identifiers =
4738 utils::fnsig_argument_identifiers(ctx, signature);
4739 let ret_ty = utils::fnsig_return_ty(ctx, signature);
4740 result.dynamic_items().push_func(
4741 ident,
4742 abi,
4743 signature.is_variadic(),
4744 ctx.options().dynamic_link_require_all,
4745 args,
4746 args_identifiers,
4747 ret,
4748 ret_ty,
4749 attributes,
4750 ctx,
4751 );
4752 } else {
4753 result.push(tokens);
4754 }
4755 Some(times_seen)
4756 }
4757}
4758
4759#[cfg_attr(not(feature = "experimental"), allow(unused_variables))]
4760fn unsupported_abi_diagnostic(
4761 fn_name: &str,
4762 variadic: bool,
4763 location: Option<&crate::clang::SourceLocation>,
4764 ctx: &BindgenContext,
4765 error: &Error,
4766) {
4767 warn!(
4768 "Skipping {}function `{fn_name}` because the {error}",
4769 if variadic { "variadic " } else { "" },
4770 );
4771
4772 #[cfg(feature = "experimental")]
4773 if ctx.options().emit_diagnostics {
4774 use crate::diagnostics::{get_line, Diagnostic, Level, Slice};
4775
4776 let mut diag = Diagnostic::default();
4777 diag.with_title(
4778 format!(
4779 "Skipping {}function `{fn_name}` because the {error}",
4780 if variadic { "variadic " } else { "" },
4781 ),
4782 Level::Warning,
4783 )
4784 .add_annotation(
4785 "No code will be generated for this function.",
4786 Level::Warning,
4787 )
4788 .add_annotation(
4789 format!(
4790 "The configured Rust version is {}.",
4791 ctx.options().rust_target
4792 ),
4793 Level::Note,
4794 );
4795
4796 if let Some(loc) = location {
4797 let (file, line, col, _) = loc.location();
4798
4799 if let Some(filename) = file.name() {
4800 if let Ok(Some(source)) = get_line(&filename, line) {
4801 let mut slice = Slice::default();
4802 slice
4803 .with_source(source)
4804 .with_location(filename, line, col);
4805 diag.add_slice(slice);
4806 }
4807 }
4808 }
4809
4810 diag.display();
4811 }
4812}
4813
4814fn variadic_fn_diagnostic(
4815 fn_name: &str,
4816 _location: Option<&crate::clang::SourceLocation>,
4817 _ctx: &BindgenContext,
4818) {
4819 warn!(
4820 "Cannot generate wrapper for the static variadic function `{fn_name}`."
4821 );
4822
4823 #[cfg(feature = "experimental")]
4824 if _ctx.options().emit_diagnostics {
4825 use crate::diagnostics::{get_line, Diagnostic, Level, Slice};
4826
4827 let mut diag = Diagnostic::default();
4828
4829 diag.with_title(format!("Cannot generate wrapper for the static function `{fn_name}`."), Level::Warning)
4830 .add_annotation("The `--wrap-static-fns` feature does not support variadic functions.", Level::Note)
4831 .add_annotation("No code will be generated for this function.", Level::Note);
4832
4833 if let Some(loc) = _location {
4834 let (file, line, col, _) = loc.location();
4835
4836 if let Some(filename) = file.name() {
4837 if let Ok(Some(source)) = get_line(&filename, line) {
4838 let mut slice = Slice::default();
4839 slice
4840 .with_source(source)
4841 .with_location(filename, line, col);
4842 diag.add_slice(slice);
4843 }
4844 }
4845 }
4846
4847 diag.display();
4848 }
4849}
4850
4851fn objc_method_codegen(
4852 ctx: &BindgenContext,
4853 method: &ObjCMethod,
4854 methods: &mut Vec<proc_macro2::TokenStream>,
4855 class_name: Option<&str>,
4856 rust_class_name: &str,
4857 prefix: &str,
4858) {
4859 let name = format!("{rust_class_name}::{prefix}{}", method.rust_name());
4863 if ctx.options().blocklisted_items.matches(name) {
4864 return;
4865 }
4866
4867 let signature = method.signature();
4868 let fn_args = utils::fnsig_arguments(ctx, signature);
4869 let fn_ret = utils::fnsig_return_ty(ctx, signature);
4870
4871 let sig = if method.is_class_method() {
4872 quote! {
4873 ( #( #fn_args ),* ) #fn_ret
4874 }
4875 } else {
4876 let self_arr = [quote! { &self }];
4877 let args = self_arr.iter().chain(fn_args.iter());
4878 quote! {
4879 ( #( #args ),* ) #fn_ret
4880 }
4881 };
4882
4883 let methods_and_args = method.format_method_call(&fn_args);
4884
4885 let body = {
4886 let body = if method.is_class_method() {
4887 let class_name = ctx.rust_ident(
4888 class_name
4889 .expect("Generating a class method without class name?"),
4890 );
4891 quote!(msg_send!(class!(#class_name), #methods_and_args))
4892 } else {
4893 quote!(msg_send!(*self, #methods_and_args))
4894 };
4895
4896 ctx.wrap_unsafe_ops(body)
4897 };
4898
4899 let method_name = ctx.rust_ident(format!("{prefix}{}", method.rust_name()));
4900
4901 methods.push(quote! {
4902 unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
4903 #body
4904 }
4905 });
4906}
4907
4908impl CodeGenerator for ObjCInterface {
4909 type Extra = Item;
4910 type Return = ();
4911
4912 fn codegen(
4913 &self,
4914 ctx: &BindgenContext,
4915 result: &mut CodegenResult<'_>,
4916 item: &Item,
4917 ) {
4918 debug_assert!(item.is_enabled_for_codegen(ctx));
4919
4920 let mut impl_items = vec![];
4921 let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::");
4922
4923 for method in self.methods() {
4924 objc_method_codegen(
4925 ctx,
4926 method,
4927 &mut impl_items,
4928 None,
4929 &rust_class_name,
4930 "",
4931 );
4932 }
4933
4934 for class_method in self.class_methods() {
4935 let ambiquity = self
4936 .methods()
4937 .iter()
4938 .map(|m| m.rust_name())
4939 .any(|x| x == class_method.rust_name());
4940 let prefix = if ambiquity { "class_" } else { "" };
4941 objc_method_codegen(
4942 ctx,
4943 class_method,
4944 &mut impl_items,
4945 Some(self.name()),
4946 &rust_class_name,
4947 prefix,
4948 );
4949 }
4950
4951 let trait_name = ctx.rust_ident(self.rust_name());
4952 let trait_constraints = quote! {
4953 Sized + std::ops::Deref
4954 };
4955 let trait_block = if self.is_template() {
4956 let template_names: Vec<Ident> = self
4957 .template_names
4958 .iter()
4959 .map(|g| ctx.rust_ident(g))
4960 .collect();
4961
4962 quote! {
4963 pub trait #trait_name <#(#template_names:'static),*> : #trait_constraints {
4964 #( #impl_items )*
4965 }
4966 }
4967 } else {
4968 quote! {
4969 pub trait #trait_name : #trait_constraints {
4970 #( #impl_items )*
4971 }
4972 }
4973 };
4974
4975 let class_name = ctx.rust_ident(self.name());
4976 if !self.is_category() && !self.is_protocol() {
4977 let struct_block = quote! {
4978 #[repr(transparent)]
4979 #[derive(Debug, Copy, Clone)]
4980 pub struct #class_name(pub id);
4981 impl std::ops::Deref for #class_name {
4982 type Target = objc::runtime::Object;
4983 fn deref(&self) -> &Self::Target {
4984 unsafe {
4985 &*self.0
4986 }
4987 }
4988 }
4989 unsafe impl objc::Message for #class_name { }
4990 impl #class_name {
4991 pub fn alloc() -> Self {
4992 Self(unsafe {
4993 msg_send!(class!(#class_name), alloc)
4994 })
4995 }
4996 }
4997 };
4998 result.push(struct_block);
4999 let mut protocol_set: HashSet<ItemId> = Default::default();
5000 for protocol_id in &self.conforms_to {
5001 protocol_set.insert(*protocol_id);
5002 let protocol_name = ctx.rust_ident(
5003 ctx.resolve_type(protocol_id.expect_type_id(ctx))
5004 .name()
5005 .unwrap(),
5006 );
5007 let impl_trait = quote! {
5008 impl #protocol_name for #class_name { }
5009 };
5010 result.push(impl_trait);
5011 }
5012 let mut parent_class = self.parent_class;
5013 while let Some(parent_id) = parent_class {
5014 let parent = parent_id
5015 .expect_type_id(ctx)
5016 .into_resolver()
5017 .through_type_refs()
5018 .resolve(ctx)
5019 .expect_type()
5020 .kind();
5021
5022 let TypeKind::ObjCInterface(parent) = parent else {
5023 break;
5024 };
5025 parent_class = parent.parent_class;
5026
5027 let parent_name = ctx.rust_ident(parent.rust_name());
5028 let impl_trait = if parent.is_template() {
5029 let template_names: Vec<Ident> = parent
5030 .template_names
5031 .iter()
5032 .map(|g| ctx.rust_ident(g))
5033 .collect();
5034 quote! {
5035 impl <#(#template_names :'static),*> #parent_name <#(#template_names),*> for #class_name {
5036 }
5037 }
5038 } else {
5039 quote! {
5040 impl #parent_name for #class_name { }
5041 }
5042 };
5043 result.push(impl_trait);
5044 for protocol_id in &parent.conforms_to {
5045 if protocol_set.insert(*protocol_id) {
5046 let protocol_name = ctx.rust_ident(
5047 ctx.resolve_type(protocol_id.expect_type_id(ctx))
5048 .name()
5049 .unwrap(),
5050 );
5051 let impl_trait = quote! {
5052 impl #protocol_name for #class_name { }
5053 };
5054 result.push(impl_trait);
5055 }
5056 }
5057 if !parent.is_template() {
5058 let parent_struct_name = parent.name();
5059 let child_struct_name = self.name();
5060 let parent_struct = ctx.rust_ident(parent_struct_name);
5061 let from_block = quote! {
5062 impl From<#class_name> for #parent_struct {
5063 fn from(child: #class_name) -> #parent_struct {
5064 #parent_struct(child.0)
5065 }
5066 }
5067 };
5068 result.push(from_block);
5069
5070 let error_msg = format!(
5071 "This {parent_struct_name} cannot be downcasted to {child_struct_name}"
5072 );
5073 let try_into_block = quote! {
5074 impl std::convert::TryFrom<#parent_struct> for #class_name {
5075 type Error = &'static str;
5076 fn try_from(parent: #parent_struct) -> Result<#class_name, Self::Error> {
5077 let is_kind_of : bool = unsafe { msg_send!(parent, isKindOfClass:class!(#class_name))};
5078 if is_kind_of {
5079 Ok(#class_name(parent.0))
5080 } else {
5081 Err(#error_msg)
5082 }
5083 }
5084 }
5085 };
5086 result.push(try_into_block);
5087 }
5088 }
5089 }
5090
5091 if !self.is_protocol() {
5092 let impl_block = if self.is_template() {
5093 let template_names: Vec<Ident> = self
5094 .template_names
5095 .iter()
5096 .map(|g| ctx.rust_ident(g))
5097 .collect();
5098 quote! {
5099 impl <#(#template_names :'static),*> #trait_name <#(#template_names),*> for #class_name {
5100 }
5101 }
5102 } else {
5103 quote! {
5104 impl #trait_name for #class_name {
5105 }
5106 }
5107 };
5108 result.push(impl_block);
5109 }
5110
5111 result.push(trait_block);
5112 result.saw_objc();
5113 }
5114}
5115
5116pub(crate) fn codegen(
5117 context: BindgenContext,
5118) -> Result<(proc_macro2::TokenStream, BindgenOptions), CodegenError> {
5119 context.gen(|context| {
5120 let _t = context.timer("codegen");
5121 let counter = Cell::new(0);
5122 let mut result = CodegenResult::new(&counter);
5123
5124 debug!("codegen: {:?}", context.options());
5125
5126 if context.options().emit_ir {
5127 let codegen_items = context.codegen_items();
5128 for (id, item) in context.items() {
5129 if codegen_items.contains(&id) {
5130 println!("ir: {id:?} = {item:#?}");
5131 }
5132 }
5133 }
5134
5135 if let Some(path) = context.options().emit_ir_graphviz.as_ref() {
5136 match dot::write_dot_file(context, path) {
5137 Ok(()) => info!(
5138 "Your dot file was generated successfully into: {path}"
5139 ),
5140 Err(e) => warn!("{e}"),
5141 }
5142 }
5143
5144 if let Some(spec) = context.options().depfile.as_ref() {
5145 match spec.write(context.deps()) {
5146 Ok(()) => info!(
5147 "Your depfile was generated successfully into: {}",
5148 spec.depfile_path.display()
5149 ),
5150 Err(e) => warn!("{e}"),
5151 }
5152 }
5153
5154 context.resolve_item(context.root_module()).codegen(
5155 context,
5156 &mut result,
5157 &(),
5158 );
5159
5160 if let Some(ref lib_name) = context.options().dynamic_library_name {
5161 let lib_ident = context.rust_ident(lib_name);
5162 let dynamic_items_tokens =
5163 result.dynamic_items().get_tokens(lib_ident, context);
5164 result.push(dynamic_items_tokens);
5165 }
5166
5167 utils::serialize_items(&result, context)?;
5168
5169 Ok(postprocessing::postprocessing(
5170 result.items,
5171 context.options(),
5172 ))
5173 })
5174}
5175
5176pub(crate) mod utils {
5177 use super::helpers::BITFIELD_UNIT;
5178 use super::serialize::CSerialize;
5179 use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
5180 use crate::ir::context::BindgenContext;
5181 use crate::ir::context::TypeId;
5182 use crate::ir::function::{Abi, ClangAbi, FunctionSig};
5183 use crate::ir::item::{Item, ItemCanonicalPath};
5184 use crate::ir::ty::TypeKind;
5185 use crate::{args_are_cpp, file_is_cpp};
5186 use std::borrow::Cow;
5187 use std::io::Write;
5188 use std::mem;
5189 use std::path::PathBuf;
5190 use std::str::FromStr;
5191
5192 pub(super) fn serialize_items(
5193 result: &CodegenResult,
5194 context: &BindgenContext,
5195 ) -> Result<(), CodegenError> {
5196 if result.items_to_serialize.is_empty() {
5197 return Ok(());
5198 }
5199
5200 let path = context.options().wrap_static_fns_path.as_ref().map_or_else(
5201 || std::env::temp_dir().join("bindgen").join("extern"),
5202 PathBuf::from,
5203 );
5204
5205 let dir = path.parent().unwrap();
5206
5207 if !dir.exists() {
5208 std::fs::create_dir_all(dir)?;
5209 }
5210
5211 let is_cpp = args_are_cpp(&context.options().clang_args) ||
5212 context
5213 .options()
5214 .input_headers
5215 .iter()
5216 .any(|h| file_is_cpp(h));
5217
5218 let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" });
5219
5220 let mut code = Vec::new();
5221
5222 if !context.options().input_headers.is_empty() {
5223 for header in &context.options().input_headers {
5224 writeln!(code, "#include \"{header}\"")?;
5225 }
5226
5227 writeln!(code)?;
5228 }
5229
5230 if !context.options().input_header_contents.is_empty() {
5231 for (name, contents) in &context.options().input_header_contents {
5232 writeln!(code, "// {name}\n{contents}")?;
5233 }
5234
5235 writeln!(code)?;
5236 }
5237
5238 writeln!(code, "// Static wrappers\n")?;
5239
5240 for (id, wrap_as_variadic) in &result.items_to_serialize {
5241 let item = context.resolve_item(*id);
5242 item.serialize(context, wrap_as_variadic, &mut vec![], &mut code)?;
5243 }
5244
5245 std::fs::write(source_path, code)?;
5246
5247 Ok(())
5248 }
5249
5250 pub(super) fn wrap_as_variadic_fn(
5251 ctx: &BindgenContext,
5252 signature: &FunctionSig,
5253 name: &str,
5254 ) -> Option<super::WrapAsVariadic> {
5255 if signature.argument_types().len() <= 1 {
5259 return None;
5260 }
5261
5262 let mut it = signature.argument_types().iter().enumerate().filter_map(
5263 |(idx, (_name, mut type_id))| {
5264 loop {
5266 let ty = ctx.resolve_type(type_id);
5267 if Some("__builtin_va_list") == ty.name() {
5268 return Some(idx);
5269 }
5270 match ty.kind() {
5271 TypeKind::Alias(type_id_alias) => {
5272 type_id = *type_id_alias;
5273 }
5274 TypeKind::ResolvedTypeRef(type_id_typedef) => {
5275 type_id = *type_id_typedef;
5276 }
5277 _ => break,
5278 }
5279 }
5280 None
5281 },
5282 );
5283
5284 it.next().filter(|_| it.next().is_none()).and_then(|idx| {
5287 #[cfg(feature = "experimental")]
5289 {
5290 ctx.options()
5291 .last_callback(|c| c.wrap_as_variadic_fn(name))
5292 .map(|new_name| super::WrapAsVariadic {
5293 new_name,
5294 idx_of_va_list_arg: idx,
5295 })
5296 }
5297 #[cfg(not(feature = "experimental"))]
5298 {
5299 let _ = name;
5300 let _ = idx;
5301 None
5302 }
5303 })
5304 }
5305
5306 pub(crate) fn prepend_bitfield_unit_type(
5307 ctx: &BindgenContext,
5308 result: &mut Vec<proc_macro2::TokenStream>,
5309 ) {
5310 if ctx.options().blocklisted_items.matches(BITFIELD_UNIT) ||
5311 ctx.options().blocklisted_types.matches(BITFIELD_UNIT)
5312 {
5313 return;
5314 }
5315
5316 let bitfield_unit_src = if ctx.options().rust_features().raw_ref_macros
5317 {
5318 include_str!("./bitfield_unit_raw_ref_macros.rs")
5319 } else {
5320 include_str!("./bitfield_unit.rs")
5321 };
5322 let bitfield_unit_src = if true {
5323 Cow::Borrowed(bitfield_unit_src)
5324 } else {
5325 Cow::Owned(bitfield_unit_src.replace("const fn ", "fn "))
5326 };
5327 let bitfield_unit_type =
5328 proc_macro2::TokenStream::from_str(&bitfield_unit_src).unwrap();
5329 let bitfield_unit_type = quote!(#bitfield_unit_type);
5330
5331 let items = vec![bitfield_unit_type];
5332 let old_items = mem::replace(result, items);
5333 result.extend(old_items);
5334 }
5335
5336 pub(crate) fn prepend_objc_header(
5337 ctx: &BindgenContext,
5338 result: &mut Vec<proc_macro2::TokenStream>,
5339 ) {
5340 let use_objc = if ctx.options().objc_extern_crate {
5341 quote! {
5342 #[macro_use]
5343 extern crate objc;
5344 }
5345 } else {
5346 quote! {
5347 use objc::{self, msg_send, sel, sel_impl, class};
5348 }
5349 };
5350
5351 let id_type = quote! {
5352 #[allow(non_camel_case_types)]
5353 pub type id = *mut objc::runtime::Object;
5354 };
5355
5356 let items = vec![use_objc, id_type];
5357 let old_items = mem::replace(result, items);
5358 result.extend(old_items);
5359 }
5360
5361 pub(crate) fn prepend_block_header(
5362 ctx: &BindgenContext,
5363 result: &mut Vec<proc_macro2::TokenStream>,
5364 ) {
5365 let use_block = if ctx.options().block_extern_crate {
5366 quote! {
5367 extern crate block;
5368 }
5369 } else {
5370 quote! {
5371 use block;
5372 }
5373 };
5374
5375 let items = vec![use_block];
5376 let old_items = mem::replace(result, items);
5377 result.extend(old_items);
5378 }
5379
5380 pub(crate) fn prepend_union_types(
5381 ctx: &BindgenContext,
5382 result: &mut Vec<proc_macro2::TokenStream>,
5383 ) {
5384 let prefix = ctx.trait_prefix();
5385
5386 let const_fn = if true {
5389 quote! { const fn }
5390 } else {
5391 quote! { fn }
5392 };
5393
5394 let union_field_decl = quote! {
5397 #[repr(C)]
5398 pub struct __BindgenUnionField<T>(::#prefix::marker::PhantomData<T>);
5399 };
5400
5401 let transmute =
5402 ctx.wrap_unsafe_ops(quote!(::#prefix::mem::transmute(self)));
5403
5404 let union_field_impl = quote! {
5405 impl<T> __BindgenUnionField<T> {
5406 #[inline]
5407 pub #const_fn new() -> Self {
5408 __BindgenUnionField(::#prefix::marker::PhantomData)
5409 }
5410
5411 #[inline]
5412 pub unsafe fn as_ref(&self) -> &T {
5413 #transmute
5414 }
5415
5416 #[inline]
5417 pub unsafe fn as_mut(&mut self) -> &mut T {
5418 #transmute
5419 }
5420 }
5421 };
5422
5423 let union_field_default_impl = quote! {
5424 impl<T> ::#prefix::default::Default for __BindgenUnionField<T> {
5425 #[inline]
5426 fn default() -> Self {
5427 Self::new()
5428 }
5429 }
5430 };
5431
5432 let union_field_clone_impl = quote! {
5433 impl<T> ::#prefix::clone::Clone for __BindgenUnionField<T> {
5434 #[inline]
5435 fn clone(&self) -> Self {
5436 *self
5437 }
5438 }
5439 };
5440
5441 let union_field_copy_impl = quote! {
5442 impl<T> ::#prefix::marker::Copy for __BindgenUnionField<T> {}
5443 };
5444
5445 let union_field_debug_impl = quote! {
5446 impl<T> ::#prefix::fmt::Debug for __BindgenUnionField<T> {
5447 fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
5448 -> ::#prefix::fmt::Result {
5449 fmt.write_str("__BindgenUnionField")
5450 }
5451 }
5452 };
5453
5454 let union_field_hash_impl = quote! {
5457 impl<T> ::#prefix::hash::Hash for __BindgenUnionField<T> {
5458 fn hash<H: ::#prefix::hash::Hasher>(&self, _state: &mut H) {
5459 }
5460 }
5461 };
5462
5463 let union_field_partialeq_impl = quote! {
5464 impl<T> ::#prefix::cmp::PartialEq for __BindgenUnionField<T> {
5465 fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
5466 true
5467 }
5468 }
5469 };
5470
5471 let union_field_eq_impl = quote! {
5472 impl<T> ::#prefix::cmp::Eq for __BindgenUnionField<T> {
5473 }
5474 };
5475
5476 let items = vec![
5477 union_field_decl,
5478 union_field_impl,
5479 union_field_default_impl,
5480 union_field_clone_impl,
5481 union_field_copy_impl,
5482 union_field_debug_impl,
5483 union_field_hash_impl,
5484 union_field_partialeq_impl,
5485 union_field_eq_impl,
5486 ];
5487
5488 let old_items = mem::replace(result, items);
5489 result.extend(old_items);
5490 }
5491
5492 pub(crate) fn prepend_incomplete_array_types(
5493 ctx: &BindgenContext,
5494 result: &mut Vec<proc_macro2::TokenStream>,
5495 ) {
5496 let prefix = ctx.trait_prefix();
5497
5498 let const_fn = if true {
5501 quote! { const fn }
5502 } else {
5503 quote! { fn }
5504 };
5505
5506 let incomplete_array_decl = quote! {
5507 #[repr(C)]
5508 #[derive(Default)]
5509 pub struct __IncompleteArrayField<T>(
5510 ::#prefix::marker::PhantomData<T>, [T; 0]);
5511 };
5512
5513 let from_raw_parts = ctx.wrap_unsafe_ops(quote! (
5514 ::#prefix::slice::from_raw_parts(self.as_ptr(), len)
5515 ));
5516 let from_raw_parts_mut = ctx.wrap_unsafe_ops(quote! (
5517 ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
5518 ));
5519
5520 let incomplete_array_impl = quote! {
5521 impl<T> __IncompleteArrayField<T> {
5522 #[inline]
5523 pub #const_fn new() -> Self {
5524 __IncompleteArrayField(::#prefix::marker::PhantomData, [])
5525 }
5526
5527 #[inline]
5528 pub fn as_ptr(&self) -> *const T {
5529 self as *const _ as *const T
5530 }
5531
5532 #[inline]
5533 pub fn as_mut_ptr(&mut self) -> *mut T {
5534 self as *mut _ as *mut T
5535 }
5536
5537 #[inline]
5538 pub unsafe fn as_slice(&self, len: usize) -> &[T] {
5539 #from_raw_parts
5540 }
5541
5542 #[inline]
5543 pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
5544 #from_raw_parts_mut
5545 }
5546 }
5547 };
5548
5549 let incomplete_array_debug_impl = quote! {
5550 impl<T> ::#prefix::fmt::Debug for __IncompleteArrayField<T> {
5551 fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
5552 -> ::#prefix::fmt::Result {
5553 fmt.write_str("__IncompleteArrayField")
5554 }
5555 }
5556 };
5557
5558 let items = vec![
5559 incomplete_array_decl,
5560 incomplete_array_impl,
5561 incomplete_array_debug_impl,
5562 ];
5563
5564 let old_items = mem::replace(result, items);
5565 result.extend(old_items);
5566 }
5567
5568 pub(crate) fn prepend_float16_type(
5569 result: &mut Vec<proc_macro2::TokenStream>,
5570 ) {
5571 let float16_type = quote! {
5572 #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5573 #[repr(transparent)]
5574 pub struct __BindgenFloat16(pub u16);
5575 };
5576
5577 let items = vec![float16_type];
5578 let old_items = mem::replace(result, items);
5579 result.extend(old_items);
5580 }
5581
5582 pub(crate) fn prepend_complex_type(
5583 result: &mut Vec<proc_macro2::TokenStream>,
5584 ) {
5585 let complex_type = quote! {
5586 #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
5587 #[repr(C)]
5588 pub struct __BindgenComplex<T> {
5589 pub re: T,
5590 pub im: T
5591 }
5592 };
5593
5594 let items = vec![complex_type];
5595 let old_items = mem::replace(result, items);
5596 result.extend(old_items);
5597 }
5598
5599 pub(crate) fn prepend_opaque_array_type(
5600 result: &mut Vec<proc_macro2::TokenStream>,
5601 ) {
5602 let ty = quote! {
5603 #[derive(PartialEq, Copy, Clone, Debug, Hash)]
5606 #[repr(C)]
5607 pub struct __BindgenOpaqueArray<T: Copy, const N: usize>(pub [T; N]);
5608 impl<T: Copy + Default, const N: usize> Default for __BindgenOpaqueArray<T, N> {
5609 fn default() -> Self {
5610 Self([<T as Default>::default(); N])
5611 }
5612 }
5613 };
5614
5615 result.insert(0, ty);
5616 }
5617
5618 pub(crate) fn build_path(
5619 item: &Item,
5620 ctx: &BindgenContext,
5621 ) -> error::Result<syn::Type> {
5622 let path = item.namespace_aware_canonical_path(ctx);
5623 let tokens =
5624 proc_macro2::TokenStream::from_str(&path.join("::")).unwrap();
5625
5626 Ok(syn::parse_quote! { #tokens })
5627 }
5628
5629 fn primitive_ty(ctx: &BindgenContext, name: &str) -> syn::Type {
5630 let ident = ctx.rust_ident_raw(name);
5631 syn::parse_quote! { #ident }
5632 }
5633
5634 pub(crate) fn type_from_named(
5635 ctx: &BindgenContext,
5636 name: &str,
5637 ) -> Option<syn::Type> {
5638 Some(match name {
5641 "int8_t" => primitive_ty(ctx, "i8"),
5642 "uint8_t" => primitive_ty(ctx, "u8"),
5643 "int16_t" => primitive_ty(ctx, "i16"),
5644 "uint16_t" => primitive_ty(ctx, "u16"),
5645 "int32_t" => primitive_ty(ctx, "i32"),
5646 "uint32_t" => primitive_ty(ctx, "u32"),
5647 "int64_t" => primitive_ty(ctx, "i64"),
5648 "uint64_t" => primitive_ty(ctx, "u64"),
5649
5650 "size_t" if ctx.options().size_t_is_usize => {
5651 primitive_ty(ctx, "usize")
5652 }
5653 "uintptr_t" => primitive_ty(ctx, "usize"),
5654
5655 "ssize_t" if ctx.options().size_t_is_usize => {
5656 primitive_ty(ctx, "isize")
5657 }
5658 "intptr_t" | "ptrdiff_t" => primitive_ty(ctx, "isize"),
5659 _ => return None,
5660 })
5661 }
5662
5663 fn fnsig_return_ty_internal(
5664 ctx: &BindgenContext,
5665 sig: &FunctionSig,
5666 ) -> syn::Type {
5667 if sig.is_divergent() {
5668 return syn::parse_quote! { ! };
5669 }
5670
5671 let canonical_type_kind = sig
5672 .return_type()
5673 .into_resolver()
5674 .through_type_refs()
5675 .through_type_aliases()
5676 .resolve(ctx)
5677 .kind()
5678 .expect_type()
5679 .kind();
5680
5681 match canonical_type_kind {
5682 TypeKind::Void => syn::parse_quote! { () },
5683 _ => sig.return_type().to_rust_ty_or_opaque(ctx, &()),
5684 }
5685 }
5686
5687 pub(crate) fn fnsig_return_ty(
5688 ctx: &BindgenContext,
5689 sig: &FunctionSig,
5690 ) -> proc_macro2::TokenStream {
5691 match fnsig_return_ty_internal(ctx, sig) {
5692 syn::Type::Tuple(syn::TypeTuple { elems, .. })
5693 if elems.is_empty() =>
5694 {
5695 quote! {}
5696 }
5697 ty => quote! { -> #ty },
5698 }
5699 }
5700
5701 pub(crate) fn fnsig_argument_type(
5702 ctx: &BindgenContext,
5703 ty: &TypeId,
5704 ) -> syn::Type {
5705 use super::ToPtr;
5706
5707 let arg_item = ctx.resolve_item(ty);
5708 let arg_ty = arg_item.kind().expect_type();
5709
5710 match *arg_ty.canonical_type(ctx).kind() {
5719 TypeKind::Array(t, _) => {
5720 let stream = if ctx.options().array_pointers_in_arguments {
5721 arg_ty.to_rust_ty_or_opaque(ctx, arg_item)
5722 } else {
5723 t.to_rust_ty_or_opaque(ctx, &())
5724 };
5725 stream
5726 .to_ptr(ctx.resolve_type(t).is_const() || arg_ty.is_const())
5727 }
5728 TypeKind::Pointer(inner) => {
5729 let inner = ctx.resolve_item(inner);
5730 let inner_ty = inner.expect_type();
5731 if let TypeKind::ObjCInterface(ref interface) =
5732 *inner_ty.canonical_type(ctx).kind()
5733 {
5734 let name = ctx.rust_ident(interface.name());
5735 syn::parse_quote! { #name }
5736 } else {
5737 arg_item.to_rust_ty_or_opaque(ctx, &())
5738 }
5739 }
5740 _ => arg_item.to_rust_ty_or_opaque(ctx, &()),
5741 }
5742 }
5743
5744 pub(crate) fn fnsig_arguments_iter<
5745 'a,
5746 I: Iterator<Item = &'a (Option<String>, TypeId)>,
5747 >(
5748 ctx: &BindgenContext,
5749 args_iter: I,
5750 is_variadic: bool,
5751 ) -> Vec<proc_macro2::TokenStream> {
5752 let mut unnamed_arguments = 0;
5753 let mut args = args_iter
5754 .map(|(name, ty)| {
5755 let arg_ty = fnsig_argument_type(ctx, ty);
5756
5757 let arg_name = if let Some(ref name) = *name {
5758 ctx.rust_mangle(name).into_owned()
5759 } else {
5760 unnamed_arguments += 1;
5761 format!("arg{unnamed_arguments}")
5762 };
5763
5764 assert!(!arg_name.is_empty());
5765 let arg_name = ctx.rust_ident(arg_name);
5766
5767 quote! {
5768 #arg_name : #arg_ty
5769 }
5770 })
5771 .collect::<Vec<_>>();
5772
5773 if is_variadic {
5774 args.push(quote! { ... });
5775 }
5776
5777 args
5778 }
5779
5780 pub(crate) fn fnsig_arguments(
5781 ctx: &BindgenContext,
5782 sig: &FunctionSig,
5783 ) -> Vec<proc_macro2::TokenStream> {
5784 fnsig_arguments_iter(
5785 ctx,
5786 sig.argument_types().iter(),
5787 sig.is_variadic(),
5788 )
5789 }
5790
5791 pub(crate) fn fnsig_argument_identifiers(
5792 ctx: &BindgenContext,
5793 sig: &FunctionSig,
5794 ) -> Vec<proc_macro2::TokenStream> {
5795 let mut unnamed_arguments = 0;
5796 let args = sig
5797 .argument_types()
5798 .iter()
5799 .map(|&(ref name, _ty)| {
5800 let arg_name = if let Some(ref name) = *name {
5801 ctx.rust_mangle(name).into_owned()
5802 } else {
5803 unnamed_arguments += 1;
5804 format!("arg{unnamed_arguments}")
5805 };
5806
5807 assert!(!arg_name.is_empty());
5808 let arg_name = ctx.rust_ident(arg_name);
5809
5810 quote! {
5811 #arg_name
5812 }
5813 })
5814 .collect::<Vec<_>>();
5815
5816 args
5817 }
5818
5819 pub(crate) fn fnsig_block(
5820 ctx: &BindgenContext,
5821 sig: &FunctionSig,
5822 ) -> proc_macro2::TokenStream {
5823 let args = sig.argument_types().iter().map(|&(_, ty)| {
5824 let arg_item = ctx.resolve_item(ty);
5825
5826 arg_item.to_rust_ty_or_opaque(ctx, &())
5827 });
5828
5829 let ret_ty = fnsig_return_ty_internal(ctx, sig);
5830 quote! {
5831 *const ::block::Block<(#(#args,)*), #ret_ty>
5832 }
5833 }
5834
5835 pub(crate) fn names_will_be_identical_after_mangling(
5839 canonical_name: &str,
5840 mangled_name: &str,
5841 call_conv: Option<ClangAbi>,
5842 ) -> bool {
5843 if canonical_name == mangled_name {
5846 return true;
5847 }
5848
5849 let canonical_name = canonical_name.as_bytes();
5851 let mangled_name = mangled_name.as_bytes();
5852
5853 let (mangling_prefix, expect_suffix) = match call_conv {
5854 Some(ClangAbi::Known(Abi::C)) |
5855 None => {
5857 (b'_', false)
5858 }
5859 Some(ClangAbi::Known(Abi::Stdcall)) => (b'_', true),
5860 Some(ClangAbi::Known(Abi::Fastcall)) => (b'@', true),
5861
5862 Some(_) => return false,
5865 };
5866
5867 if mangled_name.len() < canonical_name.len() + 1 {
5870 return false;
5871 }
5872
5873 if mangled_name[0] != mangling_prefix {
5876 return false;
5877 }
5878
5879 if &mangled_name[1..canonical_name.len() + 1] != canonical_name {
5882 return false;
5883 }
5884
5885 if expect_suffix {
5888 let suffix = &mangled_name[canonical_name.len() + 1..];
5889
5890 if suffix.len() < 2 {
5892 return false;
5893 }
5894
5895 if suffix[0] != b'@' || !suffix[1..].iter().all(u8::is_ascii_digit)
5898 {
5899 return false;
5900 }
5901 } else if mangled_name.len() != canonical_name.len() + 1 {
5902 return false;
5905 }
5906
5907 true
5908 }
5909}