Skip to content

treat incomplete array as zero length array #456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 29, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,15 +816,22 @@ impl Type {
}
// XXX DependentSizedArray is wrong
CXType_VariableArray |
CXType_DependentSizedArray |
CXType_IncompleteArray => {
CXType_DependentSizedArray => {
let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
location,
parent_id,
ctx)
.expect("Not able to resolve array element?");
TypeKind::Pointer(inner)
}
CXType_IncompleteArray => {
let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(),
location,
parent_id,
ctx)
.expect("Not able to resolve array element?");
TypeKind::Array(inner, 0)
}
CXType_FunctionNoProto |
CXType_FunctionProto => {
let signature = try!(FunctionSig::from_ty(ty,
Expand Down
2 changes: 2 additions & 0 deletions tests/expectations/tests/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,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],
}
#[test]
fn bindgen_test_layout_C() {
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/var-tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub struct Baz {
}
extern "C" {
#[link_name = "_ZN3Baz3FOOE"]
pub static mut Baz_FOO: *const Bar;
pub static mut Baz_FOO: [Bar; 0usize];
}
#[test]
fn bindgen_test_layout_Baz() {
Expand Down
2 changes: 2 additions & 0 deletions tests/headers/class.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ class C {
int a;
// More than rust limits (32)
char big_array[33];
char zero_length_array[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is legal C/C++? (the zero_length_array and incomplete_array fields would have the same address).

Could you remove the zero_length_array field from the test?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(or better, test them in two different structs)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, some times, people use zero length array as a mark (another story should be solved), and use incomplete array as the last field

/* define a set of marker types that can be used to refer to set points in the
 * mbuf */
__extension__
typedef void    *MARKER[0];   /**< generic marker for a point in a structure */
__extension__
typedef uint8_t  MARKER8[0];  /**< generic marker with 1B alignment */
__extension__
typedef uint64_t MARKER64[0]; /**< marker that allows us to overwrite 8 bytes
                               * with a single assignment */

/**
 * The generic rte_mbuf, containing a packet mbuf.
 */
struct rte_mbuf {
	MARKER cacheline0;

	void *buf_addr;           /**< Virtual address of segment buffer. */
	phys_addr_t buf_physaddr; /**< Physical address of segment buffer. */

	uint16_t buf_len;         /**< Length of segment buffer. */

	/* next 6 bytes are initialised on RX descriptor rearm */
	MARKER8 rearm_data;
	uint16_t data_off;
struct cmdline_inst {
	/* f(parsed_struct, data) */
	void (*f)(void *, struct cmdline *, void *);
	void *data;
	const char *help_str;
	cmdline_parse_token_hdr_t *tokens[];
};

I have submitted another patch base on a helper class like __BindgenUnionField did

#[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 C {
    pub a: ::std::os::raw::c_int,
    pub big_array: [::std::os::raw::c_char; 33usize],
    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() {
    assert_eq!(::std::mem::size_of::<C>() , 40usize);
    assert_eq!(::std::mem::align_of::<C>() , 4usize);
}

char incomplete_array[];
};

class WithDtor {
Expand Down