diff options
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 87 |
1 files changed, 48 insertions, 39 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 784613ba..16ff79fb 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -26,7 +26,7 @@ use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDerivePartialEq, CanDeriveEq, CanDerive}; use ir::dot; use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue}; -use ir::function::{Abi, Function, FunctionSig, Linkage}; +use ir::function::{Abi, Function, FunctionKind, FunctionSig, Linkage}; use ir::int::IntKind; use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath}; use ir::item_kind::ItemKind; @@ -1878,13 +1878,8 @@ impl CodeGenerator for CompInfo { } if ctx.options().codegen_config.destructors { - if let Some((is_virtual, destructor)) = self.destructor() { - let kind = if is_virtual { - MethodKind::VirtualDestructor - } else { - MethodKind::Destructor - }; - + if let Some((kind, destructor)) = self.destructor() { + debug_assert!(kind.is_destructor()); Method::new(kind, destructor, false).codegen_method( ctx, &mut methods, @@ -1990,9 +1985,9 @@ impl MethodCodegen for Method { match self.kind() { MethodKind::Constructor => cc.constructors, MethodKind::Destructor => cc.destructors, - MethodKind::VirtualDestructor => cc.destructors, + MethodKind::VirtualDestructor { .. } => cc.destructors, MethodKind::Static | MethodKind::Normal | - MethodKind::Virtual => cc.methods, + MethodKind::Virtual { .. } => cc.methods, } }); @@ -2148,7 +2143,10 @@ impl EnumVariation { /// A helper type to construct different enum variations. enum EnumBuilder<'a> { - Rust(quote::Tokens), + Rust { + tokens: quote::Tokens, + emitted_any_variants: bool, + }, Bitfield { canonical_name: &'a str, tokens: quote::Tokens, @@ -2188,7 +2186,10 @@ impl<'a> EnumBuilder<'a> { pub enum #ident }; tokens.append("{"); - EnumBuilder::Rust(tokens) + EnumBuilder::Rust { + tokens, + emitted_any_variants: false, + } } EnumVariation::Consts => { @@ -2229,12 +2230,15 @@ impl<'a> EnumBuilder<'a> { }; match self { - EnumBuilder::Rust(tokens) => { + EnumBuilder::Rust { tokens, emitted_any_variants: _ } => { let name = ctx.rust_ident(variant_name); - EnumBuilder::Rust(quote! { - #tokens - #name = #expr, - }) + EnumBuilder::Rust { + tokens: quote! { + #tokens + #name = #expr, + }, + emitted_any_variants: true, + } } EnumBuilder::Bitfield { .. } => { @@ -2295,9 +2299,12 @@ impl<'a> EnumBuilder<'a> { result: &mut CodegenResult<'b>, ) -> quote::Tokens { match self { - EnumBuilder::Rust(mut t) => { - t.append("}"); - t + EnumBuilder::Rust { mut tokens, emitted_any_variants } => { + if !emitted_any_variants { + tokens.append(quote! { __bindgen_cannot_repr_c_on_empty_enum = 0 }); + } + tokens.append("}"); + tokens } EnumBuilder::Bitfield { canonical_name, @@ -2419,8 +2426,6 @@ impl CodeGenerator for Enum { } }; - // FIXME(emilio): These should probably use the path so it can - // disambiguate between namespaces, just like is_opaque etc. let variation = if self.is_bitfield(ctx, item) { EnumVariation::Bitfield } else if self.is_rustified_enum(ctx, item) { @@ -2434,15 +2439,12 @@ impl CodeGenerator for Enum { let mut attrs = vec![]; - // FIXME: Rust forbids repr with empty enums. Remove this condition when - // this is allowed. - // // TODO(emilio): Delegate this to the builders? if variation.is_rust() { - if !self.variants().is_empty() { - attrs.push(attributes::repr(repr_name)); - } - } else if variation.is_bitfield() { + attrs.push(attributes::repr(repr_name)); + } + + if variation.is_bitfield() || variation.is_rust() { attrs.push(attributes::repr("C")); } @@ -3167,6 +3169,15 @@ impl CodeGenerator for Function { Linkage::External => {} } + // Pure virtual methods have no actual symbol, so we can't generate + // something meaningful for them. + match self.kind() { + FunctionKind::Method(ref method_kind) if method_kind.is_pure_virtual() => { + return; + } + _ => {}, + } + // Similar to static member variables in a class template, we can't // generate bindings to template functions, because the set of // instantiations is open ended and we have no way of knowing which @@ -3238,12 +3249,6 @@ impl CodeGenerator for Function { abi => abi, }; - let variadic = if signature.is_variadic() { - quote! { ... } - } else { - quote! {} - }; - let ident = ctx.rust_ident(canonical_name); let mut tokens = quote! { extern #abi }; tokens.append("{\n"); @@ -3251,8 +3256,6 @@ impl CodeGenerator for Function { tokens.append_separated(attributes, "\n"); tokens.append("\n"); } - let mut args = args; - args.push(variadic); tokens.append(quote! { pub fn #ident ( #( #args ),* ) #ret; }); @@ -3708,7 +3711,7 @@ mod utils { use super::ToPtr; let mut unnamed_arguments = 0; - sig.argument_types().iter().map(|&(ref name, ty)| { + let mut args = sig.argument_types().iter().map(|&(ref name, ty)| { let arg_item = ctx.resolve_item(ty); let arg_ty = arg_item.kind().expect_type(); @@ -3755,6 +3758,12 @@ mod utils { quote! { #arg_name : #arg_ty } - }).collect() + }).collect::<Vec<_>>(); + + if sig.is_variadic() { + args.push(quote! { ... }) + } + + args } } |