Skip to content

Commit 0958c7d

Browse files
committed
generate helper class to access incomplete array
1 parent a00e8b0 commit 0958c7d

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

src/codegen/mod.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ struct CodegenResult<'a> {
8484
/// Whether an union has been generated at least once.
8585
saw_union: bool,
8686

87+
/// Whether an incomplete array has been generated at least once.
88+
saw_incomplete_array: bool,
89+
8790
items_seen: HashSet<ItemId>,
8891
/// The set of generated function/var names, needed because in C/C++ is
8992
/// legal to do something like:
@@ -115,6 +118,7 @@ impl<'a> CodegenResult<'a> {
115118
CodegenResult {
116119
items: vec![],
117120
saw_union: false,
121+
saw_incomplete_array: false,
118122
codegen_id: codegen_id,
119123
items_seen: Default::default(),
120124
functions_seen: Default::default(),
@@ -132,6 +136,10 @@ impl<'a> CodegenResult<'a> {
132136
self.saw_union = true;
133137
}
134138

139+
fn saw_incomplete_array(&mut self) {
140+
self.saw_incomplete_array = true;
141+
}
142+
135143
fn seen(&self, item: ItemId) -> bool {
136144
self.items_seen.contains(&item)
137145
}
@@ -175,6 +183,7 @@ impl<'a> CodegenResult<'a> {
175183
cb(&mut new);
176184

177185
self.saw_union |= new.saw_union;
186+
self.saw_incomplete_array |= new.saw_incomplete_array;
178187

179188
new.items
180189
}
@@ -344,6 +353,10 @@ impl CodeGenerator for Module {
344353
if saw_union && !ctx.options().unstable_rust {
345354
utils::prepend_union_types(ctx, &mut *result);
346355
}
356+
let saw_incomplete_array = result.saw_incomplete_array;
357+
if saw_incomplete_array && !ctx.options().unstable_rust {
358+
utils::prepend_incomplete_array_types(ctx, &mut *result);
359+
}
347360
if ctx.need_bindegen_complex_type() {
348361
utils::prepend_complex_type(ctx, &mut *result);
349362
}
@@ -1013,6 +1026,16 @@ impl CodeGenerator for CompInfo {
10131026
} else {
10141027
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
10151028
}
1029+
} else if let Some(item) = field_ty.is_incomplete_array(ctx) {
1030+
result.saw_incomplete_array();
1031+
1032+
let inner = item.to_rust_ty(ctx);
1033+
1034+
if ctx.options().enable_cxx_namespaces {
1035+
quote_ty!(ctx.ext_cx(), root::__IncompleteArrayField<$inner>)
1036+
} else {
1037+
quote_ty!(ctx.ext_cx(), __IncompleteArrayField<$inner>)
1038+
}
10161039
} else {
10171040
ty
10181041
};
@@ -2333,6 +2356,59 @@ mod utils {
23332356
result.extend(old_items.into_iter());
23342357
}
23352358

2359+
pub fn prepend_incomplete_array_types(ctx: &BindgenContext,
2360+
result: &mut Vec<P<ast::Item>>) {
2361+
let prefix = ctx.trait_prefix();
2362+
2363+
// TODO(emilio): The fmt::Debug impl could be way nicer with
2364+
// std::intrinsics::type_name, but...
2365+
let incomplete_array_decl = quote_item!(ctx.ext_cx(),
2366+
#[repr(C)]
2367+
pub struct __IncompleteArrayField<T>(
2368+
::$prefix::marker::PhantomData<T>);
2369+
)
2370+
.unwrap();
2371+
2372+
let incomplete_array_impl = quote_item!(&ctx.ext_cx(),
2373+
impl<T> __IncompleteArrayField<T> {
2374+
#[inline]
2375+
pub fn new() -> Self {
2376+
__IncompleteArrayField(::$prefix::marker::PhantomData)
2377+
}
2378+
2379+
#[inline]
2380+
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
2381+
::std::slice::from_raw_parts(::std::mem::transmute(self), len)
2382+
}
2383+
2384+
#[inline]
2385+
pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
2386+
::std::slice::from_raw_parts_mut(::std::mem::transmute(self), len)
2387+
}
2388+
}
2389+
)
2390+
.unwrap();
2391+
2392+
let incomplete_array_debug_impl = quote_item!(ctx.ext_cx(),
2393+
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
2394+
fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
2395+
-> ::std::fmt::Result {
2396+
fmt.write_str("__IncompleteArrayField")
2397+
}
2398+
}
2399+
)
2400+
.unwrap();
2401+
2402+
let items = vec![
2403+
incomplete_array_decl,
2404+
incomplete_array_impl,
2405+
incomplete_array_debug_impl,
2406+
];
2407+
2408+
let old_items = mem::replace(result, items);
2409+
result.extend(old_items.into_iter());
2410+
}
2411+
23362412
pub fn prepend_complex_type(ctx: &BindgenContext,
23372413
result: &mut Vec<P<ast::Item>>) {
23382414
let complex_type = quote_item!(ctx.ext_cx(),

src/ir/ty.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,15 @@ impl Type {
194194
}
195195
}
196196

197+
/// Is this a incomplete array type?
198+
pub fn is_incomplete_array(&self, ctx: &BindgenContext) -> Option<ItemId> {
199+
match self.kind {
200+
TypeKind::Array(item, len) => if len == 0 { Some(item) } else { None },
201+
TypeKind::ResolvedTypeRef(inner) => ctx.resolve_type(inner).is_incomplete_array(ctx),
202+
_ => None,
203+
}
204+
}
205+
197206
/// What is the layout of this type?
198207
pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
199208
use std::mem;

tests/expectations/tests/class.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,27 @@
44
#![allow(non_snake_case)]
55

66

7+
#[repr(C)]
8+
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
9+
impl <T> __IncompleteArrayField<T> {
10+
#[inline]
11+
pub fn new() -> Self {
12+
__IncompleteArrayField(::std::marker::PhantomData)
13+
}
14+
#[inline]
15+
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
16+
::std::slice::from_raw_parts(::std::mem::transmute(self), len)
17+
}
18+
#[inline]
19+
pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
20+
::std::slice::from_raw_parts_mut(::std::mem::transmute(self), len)
21+
}
22+
}
23+
impl <T> ::std::fmt::Debug for __IncompleteArrayField<T> {
24+
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
25+
fmt.write_str("__IncompleteArrayField")
26+
}
27+
}
728
#[repr(C)]
829
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
930
impl <T> __BindgenUnionField<T> {
@@ -32,8 +53,8 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
3253
pub struct C {
3354
pub a: ::std::os::raw::c_int,
3455
pub big_array: [::std::os::raw::c_char; 33usize],
35-
pub zero_length_array: [::std::os::raw::c_char; 0usize],
36-
pub incomplete_array: [::std::os::raw::c_char; 0usize],
56+
pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>,
57+
pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>,
3758
}
3859
#[test]
3960
fn bindgen_test_layout_C() {

0 commit comments

Comments
 (0)