autocxx_bindgen/codegen/
mod.rs

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