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