summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r--src/codegen/mod.rs87
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
}
}