diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-12-08 15:42:59 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-12-12 14:13:26 -0600 |
commit | 43c43ba80f84704c5dc976e1669edf8e898286b3 (patch) | |
tree | 1b90299825aa17b46951b3635e9c5c25141fd252 /src/codegen/mod.rs | |
parent | d9950d4f1c23c4eb5c6e07cab855c2bd985a6ed3 (diff) |
Always add `repr(C)` to rustified enums
If we don't, then eddyb's recent layout optimizations will do unexpected things
to them.
We also need to handle empty `enum`s without variants. When `repr(C)` is on a
Rust `enum`, it cannot be empty, so we need to add a dummy.
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index db8fc4dd..b8893f9c 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2148,7 +2148,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 +2191,10 @@ impl<'a> EnumBuilder<'a> { pub enum #ident }; tokens.append("{"); - EnumBuilder::Rust(tokens) + EnumBuilder::Rust { + tokens, + emitted_any_variants: false, + } } EnumVariation::Consts => { @@ -2229,12 +2235,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 +2304,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, @@ -2432,15 +2444,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")); } |