summaryrefslogtreecommitdiff
path: root/src/codegen/mod.rs
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2017-12-08 15:42:59 -0800
committerNick Fitzgerald <fitzgen@gmail.com>2017-12-12 14:13:26 -0600
commit43c43ba80f84704c5dc976e1669edf8e898286b3 (patch)
tree1b90299825aa17b46951b3635e9c5c25141fd252 /src/codegen/mod.rs
parentd9950d4f1c23c4eb5c6e07cab855c2bd985a6ed3 (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.rs43
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"));
}