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