Skip to content

Commit 4b931e7

Browse files
committed
Introduce -no-rust-enums (fixes rust-lang#276)
This completely disables translation of C enums to Rust enums, restoring to the old behaviour of translating them to integer constants.
1 parent 87e253d commit 4b931e7

File tree

10 files changed

+157
-56
lines changed

10 files changed

+157
-56
lines changed

src/bin/bindgen.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ fn parse_args(args: &[String]) -> ParseResult {
9797
options.builtins = true;
9898
ix += 1;
9999
}
100+
"-no-rust-enums" => {
101+
options.rust_enums = false;
102+
ix += 1;
103+
}
100104
"-allow-unknown-types" => {
101105
options.fail_on_unknown_type = false;
102106
ix += 1;

src/gen.rs

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use syntax::attr::mk_attr_id;
2020
use syntax::ptr::P;
2121
use syntax::print::pprust::tts_to_string;
2222

23-
use super::LinkType;
23+
use super::{BindgenOptions, LinkType};
2424
use types::*;
2525

2626
struct GenCtx<'r> {
@@ -115,7 +115,11 @@ fn enum_name(name: &str) -> String {
115115
format!("Enum_{}", name)
116116
}
117117

118-
pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) -> Vec<P<ast::Item>> {
118+
pub fn gen_mod(
119+
options: &BindgenOptions,
120+
globs: Vec<Global>,
121+
span: Span)
122+
-> Vec<P<ast::Item>> {
119123
// Create a dummy ExtCtxt. We only need this for string interning and that uses TLS.
120124
let mut features = Features::new();
121125
features.allow_quote = true;
@@ -180,8 +184,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
180184
for g in gs.into_iter() {
181185
match g {
182186
GType(ti) => {
183-
let t = ti.borrow().clone();
184-
defs.extend(ctypedef_to_rs(&mut ctx, t.name.clone(), &t.ty).into_iter())
187+
let t = ti.borrow();
188+
defs.extend(ctypedef_to_rs(
189+
&mut ctx,
190+
options.rust_enums,
191+
t.name.clone(), &t.ty))
185192
},
186193
GCompDecl(ci) => {
187194
{
@@ -214,7 +221,10 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
214221
e.name = unnamed_name(&mut ctx, e.name.clone());
215222
}
216223
let e = ei.borrow();
217-
defs.extend(cenum_to_rs(&mut ctx, enum_name(&e.name), e.kind, e.layout, &e.items).into_iter())
224+
defs.extend(cenum_to_rs(
225+
&mut ctx,
226+
options.rust_enums,
227+
enum_name(&e.name), e.kind, e.layout, &e.items));
218228
},
219229
GVar(vi) => {
220230
let v = vi.borrow();
@@ -269,11 +279,11 @@ pub fn gen_mod(links: &[(String, LinkType)], globs: Vec<Global>, span: Span) ->
269279
};
270280

271281
if !Vec::is_empty(&vars) {
272-
defs.push(mk_extern(&mut ctx, links, vars, abi::Abi::C));
282+
defs.push(mk_extern(&mut ctx, &options.links, vars, abi::Abi::C));
273283
}
274284

275285
for (abi, funcs) in funcs.into_iter() {
276-
defs.push(mk_extern(&mut ctx, links, funcs, abi));
286+
defs.push(mk_extern(&mut ctx, &options.links, funcs, abi));
277287
}
278288

279289
//let attrs = vec!(mk_attr_list(&mut ctx, "allow", ["dead_code", "non_camel_case_types", "uppercase_variables"]));
@@ -439,7 +449,12 @@ fn tag_dup_decl(gs: Vec<Global>) -> Vec<Global> {
439449
res
440450
}
441451

442-
fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, ty: &Type) -> Vec<P<ast::Item>> {
452+
fn ctypedef_to_rs(
453+
ctx: &mut GenCtx,
454+
rust_enums: bool,
455+
name: String,
456+
ty: &Type)
457+
-> Vec<P<ast::Item>> {
443458
fn mk_item(ctx: &mut GenCtx, name: String, ty: &Type) -> P<ast::Item> {
444459
let rust_name = rust_type_id(ctx, name);
445460
let rust_ty = cty_to_rs(ctx, ty);
@@ -478,7 +493,7 @@ fn ctypedef_to_rs(ctx: &mut GenCtx, name: String, ty: &Type) -> Vec<P<ast::Item>
478493
if is_empty {
479494
ei.borrow_mut().name = name.clone();
480495
let e = ei.borrow();
481-
cenum_to_rs(ctx, name, e.kind, e.layout, &e.items)
496+
cenum_to_rs(ctx, rust_enums, name, e.kind, e.layout, &e.items)
482497
} else {
483498
vec!(mk_item(ctx, name, ty))
484499
}
@@ -749,20 +764,41 @@ fn cenum_value_to_int_lit(
749764
}
750765
}
751766

752-
753-
fn cenum_to_rs(ctx: &mut GenCtx,
754-
name: String,
755-
kind: IKind,
756-
layout: Layout,
757-
enum_items: &[EnumItem])
758-
-> Vec<P<ast::Item>> {
767+
fn cenum_to_rs(
768+
ctx: &mut GenCtx,
769+
rust_enums: bool,
770+
name: String,
771+
kind: IKind,
772+
layout: Layout,
773+
enum_items: &[EnumItem])
774+
-> Vec<P<ast::Item>> {
759775
let enum_name = ctx.ext_cx.ident_of(&name);
760776
let enum_ty = ctx.ext_cx.ty_ident(ctx.span, enum_name);
761777
let enum_is_signed = kind.is_signed();
778+
let enum_repr = enum_size_to_rust_type_name(enum_is_signed, layout.size);
779+
let mut items = vec![];
780+
781+
if !rust_enums {
782+
items.push(ctx.ext_cx.item_ty(
783+
ctx.span,
784+
enum_name,
785+
ctx.ext_cx.ty_ident(
786+
ctx.span,
787+
ctx.ext_cx.ident_of(enum_repr))));
788+
for item in enum_items {
789+
let value = cenum_value_to_int_lit(
790+
ctx, enum_is_signed, layout.size, item.val);
791+
items.push(ctx.ext_cx.item_const(
792+
ctx.span,
793+
ctx.ext_cx.ident_of(&item.name),
794+
enum_ty.clone(),
795+
value));
796+
}
797+
return items;
798+
}
762799

763800
let mut variants = vec![];
764801
let mut found_values = HashMap::new();
765-
let mut items = vec![];
766802

767803
for item in enum_items {
768804
let name = ctx.ext_cx.ident_of(&item.name);
@@ -794,7 +830,7 @@ fn cenum_to_rs(ctx: &mut GenCtx,
794830
}));
795831
}
796832

797-
let enum_repr = InternedString::new(enum_size_to_rust_type_name(enum_is_signed, layout.size));
833+
let enum_repr = InternedString::new(enum_repr);
798834

799835
let repr_arg = ctx.ext_cx.meta_word(ctx.span, enum_repr);
800836
let repr_list = ctx.ext_cx.meta_list(ctx.span, InternedString::new("repr"), vec![repr_arg]);

src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ impl<'a> Builder<'a> {
7676
self
7777
}
7878

79+
pub fn rust_enums(&mut self, value: bool) -> &mut Self {
80+
self.options.rust_enums = value;
81+
self
82+
}
83+
7984
pub fn log(&mut self, logger: &'a Logger) -> &mut Self {
8085
self.logger = Some(logger);
8186
self
@@ -100,6 +105,7 @@ impl<'a> Default for Builder<'a> {
100105
pub struct BindgenOptions {
101106
pub match_pat: Vec<String>,
102107
pub builtins: bool,
108+
pub rust_enums: bool,
103109
pub links: Vec<(String, LinkType)>,
104110
pub emit_ast: bool,
105111
pub fail_on_unknown_type: bool,
@@ -112,6 +118,7 @@ impl Default for BindgenOptions {
112118
BindgenOptions {
113119
match_pat: Vec::new(),
114120
builtins: false,
121+
rust_enums: true,
115122
links: Vec::new(),
116123
emit_ast: false,
117124
fail_on_unknown_type: false,
@@ -159,7 +166,7 @@ impl Bindings {
159166

160167
let module = ast::Mod {
161168
inner: span,
162-
items: gen::gen_mod(&options.links[..], globals, span)
169+
items: gen::gen_mod(options, globals, span)
163170
};
164171

165172
Ok(Bindings {

tests/support.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use bindgen;
22
use bindgen::{Logger, BindgenOptions};
33

4-
use std::default::Default;
5-
64
use syntax::ast;
75
use syntax::codemap;
86
use syntax::codemap::DUMMY_SP;
@@ -23,8 +21,9 @@ impl Logger for TestLogger {
2321
}
2422
}
2523

26-
pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> {
27-
let mut options:BindgenOptions = Default::default();
24+
pub fn generate_bindings(mut options: BindgenOptions,
25+
filename: &str)
26+
-> Result<Vec<P<ast::Item>>, ()> {
2827
if filename.ends_with("hpp") {
2928
options.clang_args.push("-std=c++11".to_string());
3029
options.clang_args.push("-Wno-narrowing".to_string());
@@ -35,10 +34,12 @@ pub fn generate_bindings(filename: &str) -> Result<Vec<P<ast::Item>>, ()> {
3534
Ok(try!(bindgen::Bindings::generate(&options, Some(&logger as &Logger), None)).into_ast())
3635
}
3736

38-
pub fn assert_bind_eq(filename: &str, reference_items_str: &str)
39-
{
37+
pub fn assert_bind_eq(options: BindgenOptions,
38+
filename: &str,
39+
reference_items_str: &str) {
4040
let ext_cx = mk_dummy_ext_ctxt();
41-
let generated_items = generate_bindings(&format!("tests/{}", filename)[..]).unwrap();
41+
let generated_items =
42+
generate_bindings(options, &format!("tests/{}", filename)[..]).unwrap();
4243

4344
let mut parser = parse::new_parser_from_source_str(ext_cx.parse_sess(), ext_cx.cfg(), "".to_string(), reference_items_str.to_string());
4445
let mut reference_items = Vec::new();

tests/test_decl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use support::assert_bind_eq;
22

33
#[test]
44
fn ptr_to_array() {
5-
assert_bind_eq("headers/decl_ptr_to_array.h", "
5+
assert_bind_eq(Default::default(), "headers/decl_ptr_to_array.h", "
66
extern \"C\" {
77
pub static mut foo: [::std::os::raw::c_int; 1usize];
88
}

tests/test_enum.rs

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,33 @@
1+
use bindgen::BindgenOptions;
12
use support::assert_bind_eq;
23

4+
fn default_without_rust_enums() -> BindgenOptions {
5+
BindgenOptions { rust_enums: false, .. Default::default() }
6+
}
7+
38
#[test]
49
fn with_simple_enum() {
5-
assert_bind_eq("headers/enum.h", "
10+
assert_bind_eq(Default::default(), "headers/enum.h", "
611
#[derive(Clone, Copy)]
712
#[repr(u32)]
813
pub enum Enum_Foo { Bar = 0, Qux = 1, }
914
#[derive(Clone, Copy)]
1015
#[repr(i32)]
1116
pub enum Enum_Neg { MinusOne = -1, One = 1, }
1217
");
18+
assert_bind_eq(default_without_rust_enums(), "headers/enum.h", "
19+
type Enum_Foo = u32;
20+
const Bar: Enum_Foo = 0;
21+
const Qux: Enum_Foo = 1;
22+
type Enum_Neg = i32;
23+
const MinusOne: Enum_Neg = -1;
24+
const One: Enum_Neg = 1;
25+
");
1326
}
1427

1528
#[test]
1629
fn with_packed_enums() {
17-
assert_bind_eq("headers/enum_packed.h", "
30+
assert_bind_eq(Default::default(), "headers/enum_packed.h", "
1831
#[derive(Clone, Copy)]
1932
#[repr(u8)]
2033
pub enum Enum_Foo { Bar = 0, Qux = 1, }
@@ -25,21 +38,37 @@ fn with_packed_enums() {
2538
#[repr(u16)]
2639
pub enum Enum_Bigger { Much = 255, Larger = 256, }
2740
");
41+
assert_bind_eq(default_without_rust_enums(), "headers/enum_packed.h", "
42+
type Enum_Foo = u8;
43+
const Bar: Enum_Foo = 0;
44+
const Qux: Enum_Foo = 1;
45+
type Enum_Neg = i8;
46+
const MinusOne: Enum_Neg = -1;
47+
const One: Enum_Neg = 1;
48+
type Enum_Bigger = u16;
49+
const Much: Enum_Bigger = 255;
50+
const Larger: Enum_Bigger = 256;
51+
");
2852
}
2953

3054
#[test]
3155
fn with_duplicate_enum_value() {
32-
assert_bind_eq("headers/enum_dupe.h", "
56+
assert_bind_eq(Default::default(), "headers/enum_dupe.h", "
3357
pub const Dupe: Enum_Foo = Enum_Foo::Bar;
3458
#[derive(Clone, Copy)]
3559
#[repr(u32)]
3660
pub enum Enum_Foo { Bar = 1, }
3761
");
62+
assert_bind_eq(default_without_rust_enums(), "headers/enum_dupe.h", "
63+
type Enum_Foo = u32;
64+
const Bar: Enum_Foo = 1;
65+
const Dupe: Enum_Foo = 1;
66+
");
3867
}
3968

4069
#[test]
4170
fn with_explicitly_typed_cxx_enum() {
42-
assert_bind_eq("headers/enum_explicit_type.hpp", "
71+
assert_bind_eq(Default::default(), "headers/enum_explicit_type.hpp", "
4372
#[derive(Clone, Copy)]
4473
#[repr(u8)]
4574
pub enum Enum_Foo { Bar = 0, Qux = 1, }
@@ -56,11 +85,26 @@ fn with_explicitly_typed_cxx_enum() {
5685
#[repr(u64)]
5786
pub enum Enum_MuchLongLong { MuchHigh = 4294967296, }
5887
");
88+
assert_bind_eq(default_without_rust_enums(), "headers/enum_explicit_type.hpp", "
89+
type Enum_Foo = u8;
90+
const Bar: Enum_Foo = 0;
91+
const Qux: Enum_Foo = 1;
92+
type Enum_Neg = i8;
93+
const MinusOne: Enum_Neg = -1;
94+
const One: Enum_Neg = 1;
95+
type Enum_Bigger = u16;
96+
const Much: Enum_Bigger = 255;
97+
const Larger: Enum_Bigger = 256;
98+
type Enum_MuchLong = i64;
99+
const MuchLow: Enum_MuchLong = -4294967296;
100+
type Enum_MuchLongLong = u64;
101+
const MuchHigh: Enum_MuchLongLong = 4294967296;
102+
");
59103
}
60104

61105
#[test]
62106
fn with_overflowed_enum_value() {
63-
assert_bind_eq("headers/overflowed_enum.hpp", "
107+
assert_bind_eq(Default::default(), "headers/overflowed_enum.hpp", "
64108
#[derive(Clone, Copy)]
65109
#[repr(u32)]
66110
pub enum Enum_Foo {
@@ -72,4 +116,13 @@ fn with_overflowed_enum_value() {
72116
#[repr(u16)]
73117
pub enum Enum_Bar { One = 1, Big = 2, }
74118
");
119+
assert_bind_eq(default_without_rust_enums(), "headers/overflowed_enum.hpp", "
120+
type Enum_Foo = u32;
121+
const BAP_ARM: Enum_Foo = 9698489;
122+
const BAP_X86: Enum_Foo = 11960045;
123+
const BAP_X86_64: Enum_Foo = 3128633167;
124+
type Enum_Bar = u16;
125+
const One: Enum_Bar = 1;
126+
const Big: Enum_Bar = 2;
127+
");
75128
}

tests/test_extern.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use support::assert_bind_eq;
22

33
#[test]
44
fn extern_c_in_hpp() {
5-
assert_bind_eq("headers/extern.hpp", "
5+
assert_bind_eq(Default::default(), "headers/extern.hpp", "
66
pub type foo = extern \"C\" fn(bar: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
77
");
88
}

0 commit comments

Comments
 (0)