diff options
author | Emilio Cobos Álvarez <me@emiliocobos.me> | 2016-05-18 11:54:16 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <me@emiliocobos.me> | 2016-05-18 11:54:16 +0200 |
commit | e24e134a89479149dd6ed4c20e00bb51306dbe06 (patch) | |
tree | 16b19eb849687bf6c970980495a32ca2f7c033d3 | |
parent | c769d1b3db1753e2cc9089d09383e18c8ae3416e (diff) |
Support in-class constants in C++
-rw-r--r-- | src/gen.rs | 19 | ||||
-rw-r--r-- | src/parser.rs | 86 | ||||
-rw-r--r-- | src/types.rs | 13 | ||||
-rw-r--r-- | tests/expectations/class.rs | 1 | ||||
-rw-r--r-- | tests/expectations/class_static.rs | 21 | ||||
-rw-r--r-- | tests/expectations/class_with_inner_struct.rs | 1 | ||||
-rw-r--r-- | tests/expectations/jsval_layout_opaque.rs | 1 | ||||
-rw-r--r-- | tests/expectations/struct_with_anon_union.rs | 1 | ||||
-rw-r--r-- | tests/expectations/struct_with_anon_unnamed_union.rs | 1 | ||||
-rw-r--r-- | tests/expectations/struct_with_nesting.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_fields.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_anon_struct.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_anon_struct_bitfield.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_anon_union.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_anon_unnamed_struct.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_anon_unnamed_union.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_big_member.rs | 1 | ||||
-rw-r--r-- | tests/expectations/union_with_nesting.rs | 1 | ||||
-rw-r--r-- | tests/headers/class_static.hpp | 7 | ||||
-rwxr-xr-x | tests/tools/run-bindgen.py | 3 |
20 files changed, 118 insertions, 45 deletions
@@ -1242,10 +1242,24 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item> _ => unreachable!() } } - if mangledlist.len() > 0 { - items.push(mk_extern(ctx, &vec![], mangledlist, Abi::C)); + if !mangledlist.is_empty() { + items.push(mk_extern(ctx, &[], mangledlist, Abi::C)); items.push(mk_impl(ctx, id_ty, unmangledlist)); } + + if !ci.vars.is_empty() { + let vars = ci.vars.into_iter().map(|v| { + let vi = v.varinfo(); + let v = vi.borrow_mut(); + let mut var_name = v.name.clone(); + if !v.mangled.is_empty() { + var_name = format!("{}_consts_{}", name, v.name); + } + cvar_to_rs(ctx, var_name, v.mangled.clone(), &v.ty, v.is_const) + }).collect(); + + items.push(mk_extern(ctx, &[], vars, Abi::C)); + } items } @@ -2301,6 +2315,7 @@ fn gen_union_field_definitions_if_necessary(ctx: &mut GenCtx, mut root_mod: &mut let union_fields_decl = quote_item!(&ctx.ext_cx, #[derive(Copy, Debug)] + #[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); ).unwrap(); diff --git a/src/parser.rs b/src/parser.rs index 0a40a13e..aa6fcbdb 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -37,6 +37,7 @@ struct ClangParserCtx<'a> { builtin_defs: Vec<Cursor>, module_map: ModuleMap, current_module_id: ModuleId, + current_translation_unit: TranslationUnit, logger: &'a (Logger+'a), err_count: i32, anonymous_modules_found: usize, @@ -185,8 +186,15 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { } CXCursor_VarDecl => { let mangled = cursor.mangling(); - let vi = Rc::new(RefCell::new(VarInfo::new(spelling, mangled, comment, TVoid))); - GVar(vi) + let is_const = ty.is_const(); + let ty = conv_ty_resolving_typedefs(ctx, &ty, &cursor, true); + let mut vi = VarInfo::new(spelling, mangled, comment, ty); + vi.is_const = is_const; + cursor.visit(|c, _: &Cursor| { + vi.val = visit_literal(c, &ctx.current_translation_unit); + CXChildVisit_Continue + }); + GVar(Rc::new(RefCell::new(vi))) } CXCursor_MacroDefinition => { let vi = Rc::new(RefCell::new(VarInfo::new(spelling, String::new(), comment, TVoid))); @@ -972,13 +980,26 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, cursor.location()), false); ci.has_non_type_template_params = true; } + CXCursor_VarDecl => { + let linkage = cursor.linkage(); + if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal { + return CXChildVisit_Continue; + } + + let visibility = cursor.visibility(); + if visibility != CXVisibility_Default { + return CXChildVisit_Continue; + } + + let var = decl_name(ctx, cursor); + ci.vars.push(var); + } // Intentionally not handled CXCursor_CXXAccessSpecifier | CXCursor_CXXFinalAttr | CXCursor_Constructor | CXCursor_FunctionTemplate | - CXCursor_ConversionFunction | - CXCursor_VarDecl => {} + CXCursor_ConversionFunction => {} _ => { // XXX: Some kind of warning would be nice, but this produces far // too many. @@ -1035,8 +1056,7 @@ fn visit_literal(cursor: &Cursor, unit: &TranslationUnit) -> Option<i64> { } fn visit_top(cursor: &Cursor, - mut ctx: &mut ClangParserCtx, - unit: &TranslationUnit) -> Enum_CXVisitorResult { + mut ctx: &mut ClangParserCtx) -> Enum_CXVisitorResult { if !match_pattern(ctx, cursor) { return CXChildVisit_Continue; } @@ -1194,17 +1214,8 @@ fn visit_top(cursor: &Cursor, if visibility != CXVisibility_Default { return CXChildVisit_Continue; } - let ty = conv_ty(ctx, &cursor.cur_type(), cursor); - let var = decl_name(ctx, cursor); - let vi = var.varinfo(); - let mut vi = vi.borrow_mut(); - vi.ty = ty.clone(); - vi.is_const = cursor.cur_type().is_const(); - cursor.visit(|c, _: &Cursor| { - vi.val = visit_literal(c, unit); - CXChildVisit_Continue - }); - ctx.current_module_mut().globals.push(var); + let val = decl_name(ctx, cursor); + ctx.current_module_mut().globals.push(val); CXChildVisit_Continue } @@ -1255,7 +1266,7 @@ fn visit_top(cursor: &Cursor, return CXChildVisit_Recurse; } - let namespace_name = match unit.tokens(cursor) { + let namespace_name = match ctx.current_translation_unit.tokens(cursor) { None => None, Some(tokens) => { if tokens.len() <= 1 { @@ -1292,13 +1303,13 @@ fn visit_top(cursor: &Cursor, let previous_id = ctx.current_module_id; ctx.current_module_id = mod_id; - cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx, &unit)); + cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx)); ctx.current_module_id = previous_id; return CXChildVisit_Continue; } CXCursor_MacroDefinition => { - let val = parse_int_literal_tokens(cursor, unit, 1); + let val = parse_int_literal_tokens(cursor, &ctx.current_translation_unit, 1); if val.is_none() { // Not an integer literal. return CXChildVisit_Continue; @@ -1334,12 +1345,25 @@ fn log_err_warn(ctx: &mut ClangParserCtx, msg: &str, is_err: bool) { } pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap, ()> { + let ix = cx::Index::create(false, true); + if ix.is_null() { + logger.error("Clang failed to create index"); + return Err(()) + } + + let unit = TranslationUnit::parse(&ix, "", &options.clang_args, &[], CXTranslationUnit_DetailedPreprocessingRecord); + if unit.is_null() { + logger.error("No input files given"); + return Err(()) + } + let mut ctx = ClangParserCtx { options: options, name: HashMap::new(), builtin_defs: vec!(), module_map: ModuleMap::new(), current_module_id: ROOT_MODULE_ID, + current_translation_unit: unit, logger: logger, err_count: 0, anonymous_modules_found: 0, @@ -1347,19 +1371,7 @@ pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap, ctx.module_map.insert(ROOT_MODULE_ID, Module::new("root".to_owned(), None)); - let ix = cx::Index::create(false, true); - if ix.is_null() { - ctx.logger.error("Clang failed to create index"); - return Err(()) - } - - let unit = TranslationUnit::parse(&ix, "", &ctx.options.clang_args[..], &[], CXTranslationUnit_DetailedPreprocessingRecord); - if unit.is_null() { - ctx.logger.error("No input files given"); - return Err(()) - } - - let diags = unit.diags(); + let diags = ctx.current_translation_unit.diags(); for d in &diags { let msg = d.format(Diagnostic::default_opts()); let is_err = d.severity() >= CXDiagnostic_Error; @@ -1370,20 +1382,20 @@ pub fn parse(options: ClangParserOptions, logger: &Logger) -> Result<ModuleMap, return Err(()) } - let cursor = unit.cursor(); + let cursor = ctx.current_translation_unit.cursor(); if ctx.options.emit_ast { cursor.visit(|cur, _: &Cursor| ast_dump(cur, 0)); } - cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx, &unit)); + cursor.visit(|cur, _: &Cursor| visit_top(cur, &mut ctx)); while !ctx.builtin_defs.is_empty() { let c = ctx.builtin_defs.remove(0); - visit_top(&c.definition(), &mut ctx, &unit); + visit_top(&c.definition(), &mut ctx); } - unit.dispose(); + ctx.current_translation_unit.dispose(); ix.dispose(); if ctx.err_count > 0 { diff --git a/src/types.rs b/src/types.rs index 15849db9..7d65c7d0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -55,7 +55,7 @@ impl Module { } } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum Global { GType(Rc<RefCell<TypeInfo>>), GComp(Rc<RefCell<CompInfo>>), @@ -435,6 +435,8 @@ pub struct CompInfo { pub has_non_type_template_params: bool, /// If this type was unnamed when parsed pub was_unnamed: bool, + /// Set of static vars declared inside this class. + pub vars: Vec<Global>, /// Used to detect if we've run in a can_derive_debug cycle while /// cycling around the template arguments. detect_derive_debug_cycle: Cell<bool>, @@ -467,9 +469,9 @@ impl CompInfo { filename: filename, comment: comment, members: members, - args: vec!(), - methods: vec!(), - vmethods: vec!(), + args: vec![], + methods: vec![], + vmethods: vec![], ref_template: None, has_vtable: false, has_destructor: false, @@ -479,7 +481,8 @@ impl CompInfo { opaque: false, base_members: 0, layout: layout, - typedefs: vec!(), + typedefs: vec![], + vars: vec![], has_non_type_template_params: false, was_unnamed: was_unnamed, detect_derive_debug_cycle: Cell::new(false), diff --git a/tests/expectations/class.rs b/tests/expectations/class.rs index 244e98a4..560c315c 100644 --- a/tests/expectations/class.rs +++ b/tests/expectations/class.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/class_static.rs b/tests/expectations/class_static.rs new file mode 100644 index 00000000..f97875e9 --- /dev/null +++ b/tests/expectations/class_static.rs @@ -0,0 +1,21 @@ +/* automatically generated by rust-bindgen */ + + +#![feature(const_fn)] +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Struct_MyClass; +impl ::std::clone::Clone for Struct_MyClass { + fn clone(&self) -> Self { *self } +} +extern "C" { + #[link_name = "_ZN7MyClass7exampleE"] + pub static mut Struct_MyClass_consts_example: + *const ::std::os::raw::c_int; + #[link_name = "_ZN7MyClass26example_check_no_collisionE"] + pub static mut Struct_MyClass_consts_example_check_no_collision: + *const ::std::os::raw::c_int; +} diff --git a/tests/expectations/class_with_inner_struct.rs b/tests/expectations/class_with_inner_struct.rs index b8dbf3ac..d045e911 100644 --- a/tests/expectations/class_with_inner_struct.rs +++ b/tests/expectations/class_with_inner_struct.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/jsval_layout_opaque.rs b/tests/expectations/jsval_layout_opaque.rs index b799a3a4..07ad6789 100644 --- a/tests/expectations/jsval_layout_opaque.rs +++ b/tests/expectations/jsval_layout_opaque.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/struct_with_anon_union.rs b/tests/expectations/struct_with_anon_union.rs index ce5d6357..668b1273 100644 --- a/tests/expectations/struct_with_anon_union.rs +++ b/tests/expectations/struct_with_anon_union.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/struct_with_anon_unnamed_union.rs b/tests/expectations/struct_with_anon_unnamed_union.rs index d5871b1a..5df5f61b 100644 --- a/tests/expectations/struct_with_anon_unnamed_union.rs +++ b/tests/expectations/struct_with_anon_unnamed_union.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/struct_with_nesting.rs b/tests/expectations/struct_with_nesting.rs index 2e023c33..787a174d 100644 --- a/tests/expectations/struct_with_nesting.rs +++ b/tests/expectations/struct_with_nesting.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_fields.rs b/tests/expectations/union_fields.rs index cf750844..974a8f71 100644 --- a/tests/expectations/union_fields.rs +++ b/tests/expectations/union_fields.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_anon_struct.rs b/tests/expectations/union_with_anon_struct.rs index 076e263f..3f78fb85 100644 --- a/tests/expectations/union_with_anon_struct.rs +++ b/tests/expectations/union_with_anon_struct.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_anon_struct_bitfield.rs b/tests/expectations/union_with_anon_struct_bitfield.rs index dc96c5c8..3237ded7 100644 --- a/tests/expectations/union_with_anon_struct_bitfield.rs +++ b/tests/expectations/union_with_anon_struct_bitfield.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_anon_union.rs b/tests/expectations/union_with_anon_union.rs index fc354db4..9ea9b841 100644 --- a/tests/expectations/union_with_anon_union.rs +++ b/tests/expectations/union_with_anon_union.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_anon_unnamed_struct.rs b/tests/expectations/union_with_anon_unnamed_struct.rs index d75c120f..80e28512 100644 --- a/tests/expectations/union_with_anon_unnamed_struct.rs +++ b/tests/expectations/union_with_anon_unnamed_struct.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_anon_unnamed_union.rs b/tests/expectations/union_with_anon_unnamed_union.rs index 4f26bfc9..a502f1f3 100644 --- a/tests/expectations/union_with_anon_unnamed_union.rs +++ b/tests/expectations/union_with_anon_unnamed_union.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_big_member.rs b/tests/expectations/union_with_big_member.rs index 44fc317b..122d5a64 100644 --- a/tests/expectations/union_with_big_member.rs +++ b/tests/expectations/union_with_big_member.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/expectations/union_with_nesting.rs b/tests/expectations/union_with_nesting.rs index 0a884d4a..070cc045 100644 --- a/tests/expectations/union_with_nesting.rs +++ b/tests/expectations/union_with_nesting.rs @@ -6,6 +6,7 @@ #[derive(Copy, Debug)] +#[repr(C)] pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); impl <T> __BindgenUnionField<T> { #[inline] diff --git a/tests/headers/class_static.hpp b/tests/headers/class_static.hpp new file mode 100644 index 00000000..21ab2321 --- /dev/null +++ b/tests/headers/class_static.hpp @@ -0,0 +1,7 @@ +class MyClass { +public: + static const int* example; + static const int* example_check_no_collision; +}; + +static const int* example_check_no_collision; diff --git a/tests/tools/run-bindgen.py b/tests/tools/run-bindgen.py index 0e3252ee..5fde6739 100755 --- a/tests/tools/run-bindgen.py +++ b/tests/tools/run-bindgen.py @@ -20,13 +20,14 @@ with open(sys.argv[2]) as f: if line.startswith(BINDGEN_FLAGS_PREFIX): flags = line.strip().split(BINDGEN_FLAGS_PREFIX)[1].split(' ') -base_command = [sys.argv[1], sys.argv[2], "-o", sys.argv[3]] +base_command = [sys.argv[1], "-o", sys.argv[3]] for line in COMMON_PRELUDE.split('\n'): flags.append("-raw-line") flags.append(line) base_command.extend(flags); +base_command.append(sys.argv[2]); subprocess.check_call(base_command, cwd=os.getcwd()) |