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