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