Skip to content

Commit 3660d4d

Browse files
author
bors-servo
authored
Auto merge of #456 - flier:zero-length-array, r=emilio
treat incomplete array as zero length array fix issue #455
2 parents 7d995d7 + edf7f35 commit 3660d4d

File tree

5 files changed

+187
-3
lines changed

5 files changed

+187
-3
lines changed

src/codegen/mod.rs

+83
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,9 @@ impl CodeGenerator for Module {
344353
if saw_union && !ctx.options().unstable_rust {
345354
utils::prepend_union_types(ctx, &mut *result);
346355
}
356+
if result.saw_incomplete_array {
357+
utils::prepend_incomplete_array_types(ctx, &mut *result);
358+
}
347359
if ctx.need_bindegen_complex_type() {
348360
utils::prepend_complex_type(ctx, &mut *result);
349361
}
@@ -1013,6 +1025,16 @@ impl CodeGenerator for CompInfo {
10131025
} else {
10141026
quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
10151027
}
1028+
} else if let Some(item) = field_ty.is_incomplete_array(ctx) {
1029+
result.saw_incomplete_array();
1030+
1031+
let inner = item.to_rust_ty(ctx);
1032+
1033+
if ctx.options().enable_cxx_namespaces {
1034+
quote_ty!(ctx.ext_cx(), root::__IncompleteArrayField<$inner>)
1035+
} else {
1036+
quote_ty!(ctx.ext_cx(), __IncompleteArrayField<$inner>)
1037+
}
10161038
} else {
10171039
ty
10181040
};
@@ -2333,6 +2355,67 @@ mod utils {
23332355
result.extend(old_items.into_iter());
23342356
}
23352357

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

src/ir/ty.rs

+18-2
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;
@@ -816,15 +825,22 @@ impl Type {
816825
}
817826
// XXX DependentSizedArray is wrong
818827
CXType_VariableArray |
819-
CXType_DependentSizedArray |
820-
CXType_IncompleteArray => {
828+
CXType_DependentSizedArray => {
821829
let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
822830
location,
823831
parent_id,
824832
ctx)
825833
.expect("Not able to resolve array element?");
826834
TypeKind::Pointer(inner)
827835
}
836+
CXType_IncompleteArray => {
837+
let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
838+
location,
839+
parent_id,
840+
ctx)
841+
.expect("Not able to resolve array element?");
842+
TypeKind::Array(inner, 0)
843+
}
828844
CXType_FunctionNoProto |
829845
CXType_FunctionProto => {
830846
let signature = try!(FunctionSig::from_ty(ty,

tests/expectations/tests/class.rs

+63
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,33 @@
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_ptr(&self) -> *const T { ::std::mem::transmute(self) }
16+
#[inline]
17+
pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
18+
::std::mem::transmute(self)
19+
}
20+
#[inline]
21+
pub unsafe fn as_slice(&self, len: usize) -> &[T] {
22+
::std::slice::from_raw_parts(self.as_ptr(), len)
23+
}
24+
#[inline]
25+
pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
26+
::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
27+
}
28+
}
29+
impl <T> ::std::fmt::Debug for __IncompleteArrayField<T> {
30+
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
31+
fmt.write_str("__IncompleteArrayField")
32+
}
33+
}
734
#[repr(C)]
835
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
936
impl <T> __BindgenUnionField<T> {
@@ -39,6 +66,42 @@ fn bindgen_test_layout_C() {
3966
assert_eq!(::std::mem::align_of::<C>() , 4usize);
4067
}
4168
#[repr(C)]
69+
pub struct C_with_zero_length_array {
70+
pub a: ::std::os::raw::c_int,
71+
pub big_array: [::std::os::raw::c_char; 33usize],
72+
pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>,
73+
}
74+
#[test]
75+
fn bindgen_test_layout_C_with_zero_length_array() {
76+
assert_eq!(::std::mem::size_of::<C_with_zero_length_array>() , 40usize);
77+
assert_eq!(::std::mem::align_of::<C_with_zero_length_array>() , 4usize);
78+
}
79+
#[repr(C)]
80+
pub struct C_with_incomplete_array {
81+
pub a: ::std::os::raw::c_int,
82+
pub big_array: [::std::os::raw::c_char; 33usize],
83+
pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>,
84+
}
85+
#[test]
86+
fn bindgen_test_layout_C_with_incomplete_array() {
87+
assert_eq!(::std::mem::size_of::<C_with_incomplete_array>() , 40usize);
88+
assert_eq!(::std::mem::align_of::<C_with_incomplete_array>() , 4usize);
89+
}
90+
#[repr(C)]
91+
pub struct C_with_zero_length_array_and_incomplete_array {
92+
pub a: ::std::os::raw::c_int,
93+
pub big_array: [::std::os::raw::c_char; 33usize],
94+
pub zero_length_array: __IncompleteArrayField<::std::os::raw::c_char>,
95+
pub incomplete_array: __IncompleteArrayField<::std::os::raw::c_char>,
96+
}
97+
#[test]
98+
fn bindgen_test_layout_C_with_zero_length_array_and_incomplete_array() {
99+
assert_eq!(::std::mem::size_of::<C_with_zero_length_array_and_incomplete_array>()
100+
, 40usize);
101+
assert_eq!(::std::mem::align_of::<C_with_zero_length_array_and_incomplete_array>()
102+
, 4usize);
103+
}
104+
#[repr(C)]
42105
#[derive(Debug)]
43106
pub struct WithDtor {
44107
pub b: ::std::os::raw::c_int,

tests/expectations/tests/var-tracing.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub struct Baz {
3636
}
3737
extern "C" {
3838
#[link_name = "_ZN3Baz3FOOE"]
39-
pub static mut Baz_FOO: *const Bar;
39+
pub static mut Baz_FOO: [Bar; 0usize];
4040
}
4141
#[test]
4242
fn bindgen_test_layout_Baz() {

tests/headers/class.hpp

+22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@ class C {
44
char big_array[33];
55
};
66

7+
class C_with_zero_length_array {
8+
int a;
9+
// More than rust limits (32)
10+
char big_array[33];
11+
char zero_length_array[0];
12+
};
13+
14+
class C_with_incomplete_array {
15+
int a;
16+
// More than rust limits (32)
17+
char big_array[33];
18+
char incomplete_array[];
19+
};
20+
21+
class C_with_zero_length_array_and_incomplete_array {
22+
int a;
23+
// More than rust limits (32)
24+
char big_array[33];
25+
char zero_length_array[0];
26+
char incomplete_array[];
27+
};
28+
729
class WithDtor {
830
int b;
931

0 commit comments

Comments
 (0)