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