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