diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index 3ba543ac..1b61286f 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -22,6 +22,7 @@ enum CDeclarator { is_ref: bool, }, Array(String), + FlexibleArray(), Func { args: Vec<(Option, CDecl)>, layout: Layout, @@ -167,6 +168,10 @@ impl CDecl { self.declarators.push(CDeclarator::Array(len)); self.build_type(t, is_const, config); } + Type::FlexibleArray(ref t) => { + self.declarators.push(CDeclarator::FlexibleArray()); + self.build_type(t, is_const, config); + } Type::FuncPtr { ref ret, ref args, @@ -254,7 +259,7 @@ impl CDecl { } } } - CDeclarator::Array(..) => { + CDeclarator::Array(..) | CDeclarator::FlexibleArray() => { if next_is_pointer { out.write("("); } @@ -286,10 +291,26 @@ impl CDecl { if last_was_pointer { out.write(")"); } + write!(out, "[{}]", constant); last_was_pointer = false; } + CDeclarator::FlexibleArray() => { + if last_was_pointer { + out.write(")"); + } + + if config.structure.c99_flexible_array_members + && config.language != Language::Cython + { + write!(out, "[]"); + } else { + write!(out, "[0]"); + } + + last_was_pointer = false; + } CDeclarator::Func { ref args, ref layout, diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index 31316503..c98f773e 100644 --- a/src/bindgen/config.rs +++ b/src/bindgen/config.rs @@ -499,6 +499,8 @@ pub struct StructConfig { pub deprecated: Option, /// The way to annotation this function as #[deprecated] with notes pub deprecated_with_note: Option, + /// The way we represent flexible array members, either GNU style or c99 style + pub c99_flexible_array_members: bool, } impl StructConfig { diff --git a/src/bindgen/ir/structure.rs b/src/bindgen/ir/structure.rs index 9b33a15c..d1b1a2b1 100644 --- a/src/bindgen/ir/structure.rs +++ b/src/bindgen/ir/structure.rs @@ -71,7 +71,7 @@ impl Struct { layout_config.ensure_safe_to_represent(&align)?; } - let fields = match item.fields { + let mut fields = match item.fields { syn::Fields::Unit => Vec::new(), syn::Fields::Named(ref fields) => fields .named @@ -97,6 +97,20 @@ impl Struct { } }; + match fields.last() { + Some(Field { + name: _, + ty: Type::Array(ty, sz), + cfg: _, + annotations: _, + documentation: _, + }) if sz.as_str() == "0" => { + let last_index = fields.len() - 1; + fields[last_index].ty = Type::FlexibleArray(ty.clone()); + } + _ => (), + } + let has_tag_field = false; let is_enum_variant_body = false; diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs index 4a41d4cf..9dfd73d8 100644 --- a/src/bindgen/ir/ty.rs +++ b/src/bindgen/ir/ty.rs @@ -317,6 +317,7 @@ pub enum Type { Path(GenericPath), Primitive(PrimitiveType), Array(Box, ConstExpr), + FlexibleArray(Box), FuncPtr { ret: Box, args: Vec<(Option, Type)>, @@ -583,7 +584,9 @@ impl Type { fn visit_types(&mut self, mut visitor: impl FnMut(&mut Type)) { match *self { - Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty), + Type::Array(ref mut ty, ..) + | Type::FlexibleArray(ref mut ty) + | Type::Ptr { ref mut ty, .. } => visitor(ty), Type::Path(ref mut path) => { for generic in path.generics_mut() { match *generic { @@ -617,7 +620,7 @@ impl Type { Type::Primitive(..) => { return None; } - Type::Array(..) => { + Type::Array(..) | Type::FlexibleArray(..) => { return None; } Type::FuncPtr { .. } => { @@ -664,6 +667,7 @@ impl Type { Box::new(ty.specialize(mappings)), constant.specialize(mappings), ), + Type::FlexibleArray(ref ty) => Type::FlexibleArray(Box::new(ty.specialize(mappings))), Type::FuncPtr { ref ret, ref args, @@ -721,7 +725,7 @@ impl Type { } } Type::Primitive(_) => {} - Type::Array(ref ty, _) => { + Type::Array(ref ty, _) | Type::FlexibleArray(ref ty) => { ty.add_dependencies_ignoring_generics(generic_params, library, out); } Type::FuncPtr { @@ -757,7 +761,7 @@ impl Type { } } Type::Primitive(_) => {} - Type::Array(ref ty, _) => { + Type::Array(ref ty, _) | Type::FlexibleArray(ref ty) => { ty.add_monomorphs(library, out); } Type::FuncPtr { @@ -784,6 +788,9 @@ impl Type { ty.rename_for_config(config, generic_params); len.rename_for_config(config); } + Type::FlexibleArray(ref mut ty) => { + ty.rename_for_config(config, generic_params); + } Type::FuncPtr { ref mut ret, ref mut args, @@ -806,7 +813,7 @@ impl Type { generic_path.resolve_declaration_types(resolver); } Type::Primitive(_) => {} - Type::Array(ref mut ty, _) => { + Type::Array(ref mut ty, _) | Type::FlexibleArray(ref mut ty) => { ty.resolve_declaration_types(resolver); } Type::FuncPtr { @@ -843,7 +850,7 @@ impl Type { } } Type::Primitive(_) => {} - Type::Array(ref mut ty, _) => { + Type::Array(ref mut ty, _) | Type::FlexibleArray(ref mut ty) => { ty.mangle_paths(monomorphs); } Type::FuncPtr { @@ -866,6 +873,7 @@ impl Type { Type::Path(..) => true, Type::Primitive(ref p) => p.can_cmp_order(), Type::Array(..) => false, + Type::FlexibleArray(..) => false, Type::FuncPtr { .. } => false, } } @@ -876,6 +884,7 @@ impl Type { Type::Path(..) => true, Type::Primitive(ref p) => p.can_cmp_eq(), Type::Array(..) => false, + Type::FlexibleArray(..) => false, Type::FuncPtr { .. } => true, } } diff --git a/src/bindgen/mangle.rs b/src/bindgen/mangle.rs index 52c3be93..cb0af677 100644 --- a/src/bindgen/mangle.rs +++ b/src/bindgen/mangle.rs @@ -128,7 +128,7 @@ impl<'a> Mangler<'a> { self.push(Separator::EndFn); } } - Type::Array(..) => { + Type::Array(..) | Type::FlexibleArray(..) => { unimplemented!( "Unable to mangle generic parameter {:?} for '{}'", ty, diff --git a/tests/expectations/struct.c b/tests/expectations/struct.c index 207e9a05..655230c2 100644 --- a/tests/expectations/struct.c +++ b/tests/expectations/struct.c @@ -25,4 +25,15 @@ typedef struct { float y; } TupleNamed; -void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); +typedef struct { + int32_t x; + int16_t y[0]; + int8_t z[0]; +} WithFlexibleArrayMember; + +void root(Opaque *a, + Normal b, + NormalWithZST c, + TupleRenamed d, + TupleNamed e, + WithFlexibleArrayMember f); diff --git a/tests/expectations/struct.compat.c b/tests/expectations/struct.compat.c index fd82fcd1..ccf2f907 100644 --- a/tests/expectations/struct.compat.c +++ b/tests/expectations/struct.compat.c @@ -25,11 +25,22 @@ typedef struct { float y; } TupleNamed; +typedef struct { + int32_t x; + int16_t y[0]; + int8_t z[0]; +} WithFlexibleArrayMember; + #ifdef __cplusplus extern "C" { #endif // __cplusplus -void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); +void root(Opaque *a, + Normal b, + NormalWithZST c, + TupleRenamed d, + TupleNamed e, + WithFlexibleArrayMember f); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/struct.cpp b/tests/expectations/struct.cpp index 4fe03404..7ad203e9 100644 --- a/tests/expectations/struct.cpp +++ b/tests/expectations/struct.cpp @@ -26,8 +26,19 @@ struct TupleNamed { float y; }; +struct WithFlexibleArrayMember { + int32_t x; + int16_t y[0]; + int8_t z[0]; +}; + extern "C" { -void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); +void root(Opaque *a, + Normal b, + NormalWithZST c, + TupleRenamed d, + TupleNamed e, + WithFlexibleArrayMember f); } // extern "C" diff --git a/tests/expectations/struct.pyx b/tests/expectations/struct.pyx index 3342101f..0f2fd8be 100644 --- a/tests/expectations/struct.pyx +++ b/tests/expectations/struct.pyx @@ -25,4 +25,14 @@ cdef extern from *: int32_t x; float y; - void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); + ctypedef struct WithFlexibleArrayMember: + int32_t x; + int16_t y[0]; + int8_t z[0]; + + void root(Opaque *a, + Normal b, + NormalWithZST c, + TupleRenamed d, + TupleNamed e, + WithFlexibleArrayMember f); diff --git a/tests/expectations/struct_both.c b/tests/expectations/struct_both.c index 5664185f..7c7cb738 100644 --- a/tests/expectations/struct_both.c +++ b/tests/expectations/struct_both.c @@ -25,8 +25,15 @@ typedef struct TupleNamed { float y; } TupleNamed; +typedef struct WithFlexibleArrayMember { + int32_t x; + int16_t y[0]; + int8_t z[0]; +} WithFlexibleArrayMember; + void root(struct Opaque *a, struct Normal b, struct NormalWithZST c, struct TupleRenamed d, - struct TupleNamed e); + struct TupleNamed e, + struct WithFlexibleArrayMember f); diff --git a/tests/expectations/struct_both.compat.c b/tests/expectations/struct_both.compat.c index ee0f4c76..6ee7d9a9 100644 --- a/tests/expectations/struct_both.compat.c +++ b/tests/expectations/struct_both.compat.c @@ -25,6 +25,12 @@ typedef struct TupleNamed { float y; } TupleNamed; +typedef struct WithFlexibleArrayMember { + int32_t x; + int16_t y[0]; + int8_t z[0]; +} WithFlexibleArrayMember; + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -33,7 +39,8 @@ void root(struct Opaque *a, struct Normal b, struct NormalWithZST c, struct TupleRenamed d, - struct TupleNamed e); + struct TupleNamed e, + struct WithFlexibleArrayMember f); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/struct_tag.c b/tests/expectations/struct_tag.c index cc5ddaa7..dd81d945 100644 --- a/tests/expectations/struct_tag.c +++ b/tests/expectations/struct_tag.c @@ -25,8 +25,15 @@ struct TupleNamed { float y; }; +struct WithFlexibleArrayMember { + int32_t x; + int16_t y[0]; + int8_t z[0]; +}; + void root(struct Opaque *a, struct Normal b, struct NormalWithZST c, struct TupleRenamed d, - struct TupleNamed e); + struct TupleNamed e, + struct WithFlexibleArrayMember f); diff --git a/tests/expectations/struct_tag.compat.c b/tests/expectations/struct_tag.compat.c index 092007c0..f7ecbbbb 100644 --- a/tests/expectations/struct_tag.compat.c +++ b/tests/expectations/struct_tag.compat.c @@ -25,6 +25,12 @@ struct TupleNamed { float y; }; +struct WithFlexibleArrayMember { + int32_t x; + int16_t y[0]; + int8_t z[0]; +}; + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -33,7 +39,8 @@ void root(struct Opaque *a, struct Normal b, struct NormalWithZST c, struct TupleRenamed d, - struct TupleNamed e); + struct TupleNamed e, + struct WithFlexibleArrayMember f); #ifdef __cplusplus } // extern "C" diff --git a/tests/expectations/struct_tag.pyx b/tests/expectations/struct_tag.pyx index 768f3752..bc04de17 100644 --- a/tests/expectations/struct_tag.pyx +++ b/tests/expectations/struct_tag.pyx @@ -25,4 +25,14 @@ cdef extern from *: int32_t x; float y; - void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); + cdef struct WithFlexibleArrayMember: + int32_t x; + int16_t y[0]; + int8_t z[0]; + + void root(Opaque *a, + Normal b, + NormalWithZST c, + TupleRenamed d, + TupleNamed e, + WithFlexibleArrayMember f); diff --git a/tests/rust/struct.rs b/tests/rust/struct.rs index 7569901a..77dda3ea 100644 --- a/tests/rust/struct.rs +++ b/tests/rust/struct.rs @@ -28,11 +28,19 @@ struct TupleRenamed(i32, f32); #[repr(C)] struct TupleNamed(i32, f32); +#[repr(C)] +struct WithFlexibleArrayMember { + x: i32, + y: [i16; 0], + z: [i8; 0], +} + #[no_mangle] pub extern "C" fn root( a: *mut Opaque, b: Normal, c: NormalWithZST, d: TupleRenamed, - e: TupleNamed + e: TupleNamed, + f: WithFlexibleArrayMember, ) { }