summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs76
-rw-r--r--src/ir/ty.rs9
-rw-r--r--tests/expectations/tests/class.rs25
3 files changed, 108 insertions, 2 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 7af70e98..4783e821 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -84,6 +84,9 @@ struct CodegenResult<'a> {
/// Whether an union has been generated at least once.
saw_union: bool,
+ /// Whether an incomplete array has been generated at least once.
+ saw_incomplete_array: bool,
+
items_seen: HashSet<ItemId>,
/// The set of generated function/var names, needed because in C/C++ is
/// legal to do something like:
@@ -115,6 +118,7 @@ impl<'a> CodegenResult<'a> {
CodegenResult {
items: vec![],
saw_union: false,
+ saw_incomplete_array: false,
codegen_id: codegen_id,
items_seen: Default::default(),
functions_seen: Default::default(),
@@ -132,6 +136,10 @@ impl<'a> CodegenResult<'a> {
self.saw_union = true;
}
+ fn saw_incomplete_array(&mut self) {
+ self.saw_incomplete_array = true;
+ }
+
fn seen(&self, item: ItemId) -> bool {
self.items_seen.contains(&item)
}
@@ -175,6 +183,7 @@ impl<'a> CodegenResult<'a> {
cb(&mut new);
self.saw_union |= new.saw_union;
+ self.saw_incomplete_array |= new.saw_incomplete_array;
new.items
}
@@ -344,6 +353,10 @@ impl CodeGenerator for Module {
if saw_union && !ctx.options().unstable_rust {
utils::prepend_union_types(ctx, &mut *result);
}
+ let saw_incomplete_array = result.saw_incomplete_array;
+ if saw_incomplete_array && !ctx.options().unstable_rust {
+ utils::prepend_incomplete_array_types(ctx, &mut *result);
+ }
if ctx.need_bindegen_complex_type() {
utils::prepend_complex_type(ctx, &mut *result);
}
@@ -1013,6 +1026,16 @@ impl CodeGenerator for CompInfo {
} else {
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
}
+ } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
+ result.saw_incomplete_array();
+
+ let inner = item.to_rust_ty(ctx);
+
+ if ctx.options().enable_cxx_namespaces {
+ quote_ty!(ctx.ext_cx(), root::__IncompleteArrayField<$inner>)
+ } else {
+ quote_ty!(ctx.ext_cx(), __IncompleteArrayField<$inner>)
+ }
} else {
ty
};
@@ -2333,6 +2356,59 @@ mod utils {
result.extend(old_items.into_iter());
}
+ pub fn prepend_incomplete_array_types(ctx: &BindgenContext,
+ result: &mut Vec<P<ast::Item>>) {
+ let prefix = ctx.trait_prefix();
+
+ // TODO(emilio): The fmt::Debug impl could be way nicer with
+ // std::intrinsics::type_name, but...
+ let incomplete_array_decl = quote_item!(ctx.ext_cx(),
+ #[repr(C)]
+ pub struct __IncompleteArrayField<T>(
+ ::$prefix::marker::PhantomData<T>);
+ )
+ .unwrap();
+
+ let incomplete_array_impl = quote_item!(&ctx.ext_cx(),
+ impl<T> __IncompleteArrayField<T> {
+ #[inline]
+ pub fn new() -> Self {
+ __IncompleteArrayField(::$prefix::marker::PhantomData)
+ }
+
+ #[inline]
+ pub unsafe fn as_slice(&self, len: usize) -> &[T] {
+ ::std::slice::from_raw_parts(::std::mem::transmute(self), len)
+ }
+
+ #[inline]
+ pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
+ ::std::slice::from_raw_parts_mut(::std::mem::transmute(self), len)
+ }
+ }
+ )
+ .unwrap();
+
+ let incomplete_array_debug_impl = quote_item!(ctx.ext_cx(),
+ impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
+ -> ::std::fmt::Result {
+ fmt.write_str("__IncompleteArrayField")
+ }
+ }
+ )
+ .unwrap();
+
+ let items = vec![
+ incomplete_array_decl,
+ incomplete_array_impl,
+ incomplete_array_debug_impl,
+ ];
+
+ let old_items = mem::replace(result, items);
+ result.extend(old_items.into_iter());
+ }
+
pub fn prepend_complex_type(ctx: &BindgenContext,
result: &mut Vec<P<ast::Item>>) {
let complex_type = quote_item!(ctx.ext_cx(),
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 96a6e6a2..f120e180 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -194,6 +194,15 @@ impl Type {
}
}
+ /// Is this a incomplete array type?
+ pub fn is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId> {
+ match self.kind {
+ TypeKind::Array(item, len) => if len == 0 { Some(item) } else { None },
+ TypeKind::ResolvedTypeRef(inner) => ctx.resolve_type(inner).is_incomplete_array(ctx),
+ _ => None,
+ }
+ }
+
/// What is the layout of this type?
pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
use std::mem;
diff --git a/tests/expectations/tests/class.rs b/tests/expectations/tests/class.rs
index 951b259a..3852cc04 100644
--- a/tests/expectations/tests/class.rs
+++ b/tests/expectations/tests/class.rs
@@ -5,6 +5,27 @@
#[repr(C)]
+pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
+impl <T> __IncompleteArrayField<T> {
+ #[inline]
+ pub fn new() -> Self {
+ __IncompleteArrayField(::std::marker::PhantomData)
+ }
+ #[inline]
+ pub unsafe fn as_slice(&self, len: usize) -> &[T] {
+ ::std::slice::from_raw_parts(::std::mem::transmute(self), len)
+ }
+ #[inline]
+ pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
+ ::std::slice::from_raw_parts_mut(::std::mem::transmute(self), len)
+ }
+}
+impl <T> ::std::fmt::Debug for __IncompleteArrayField<T> {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+ fmt.write_str("__IncompleteArrayField")
+ }
+}
+#[repr(C)]
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
impl <T> __BindgenUnionField<T> {
#[inline]
@@ -32,8 +53,8 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
pub struct C {
pub a: ::std::os::raw::c_int,
pub big_array: [::std::os::raw::c_char; 33usize],
- pub zero_length_array: [::std::os::raw::c_char; 0usize],
- pub incomplete_array: [::std::os::raw::c_char; 0usize],
+ pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>,
+ pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>,
}
#[test]
fn bindgen_test_layout_C() {