summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <me@emiliocobos.me>2016-05-18 11:54:16 +0200
committerEmilio Cobos Álvarez <me@emiliocobos.me>2016-05-18 11:54:16 +0200
commite24e134a89479149dd6ed4c20e00bb51306dbe06 (patch)
tree16b19eb849687bf6c970980495a32ca2f7c033d3
parentc769d1b3db1753e2cc9089d09383e18c8ae3416e (diff)
Support in-class constants in C++
-rw-r--r--src/gen.rs19
-rw-r--r--src/parser.rs86
-rw-r--r--src/types.rs13
-rw-r--r--tests/expectations/class.rs1
-rw-r--r--tests/expectations/class_static.rs21
-rw-r--r--tests/expectations/class_with_inner_struct.rs1
-rw-r--r--tests/expectations/jsval_layout_opaque.rs1
-rw-r--r--tests/expectations/struct_with_anon_union.rs1
-rw-r--r--tests/expectations/struct_with_anon_unnamed_union.rs1
-rw-r--r--tests/expectations/struct_with_nesting.rs1
-rw-r--r--tests/expectations/union_fields.rs1
-rw-r--r--tests/expectations/union_with_anon_struct.rs1
-rw-r--r--tests/expectations/union_with_anon_struct_bitfield.rs1
-rw-r--r--tests/expectations/union_with_anon_union.rs1
-rw-r--r--tests/expectations/union_with_anon_unnamed_struct.rs1
-rw-r--r--tests/expectations/union_with_anon_unnamed_union.rs1
-rw-r--r--tests/expectations/union_with_big_member.rs1
-rw-r--r--tests/expectations/union_with_nesting.rs1
-rw-r--r--tests/headers/class_static.hpp7
-rwxr-xr-xtests/tools/run-bindgen.py3
20 files changed, 118 insertions, 45 deletions
diff --git a/src/gen.rs b/src/gen.rs
index 6f2d5372..277a8aa1 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -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())