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