Skip to content

Commit 4697c73

Browse files
Generate flexible array members the c99 way instead of the GNU way
There a re three ways to express flexible array members: 1. char fam[0]; 2. char fam[1]; 3. char fam[]; 3. is the only standard way (in c99, but supported in c++ as an extension), the other two are GNU syntax (still supported in clang though). To avoid regression, let's generate the GNU syntax by default, while leaving it possible to use 3. through struct.c99_flexible_array_members Cython only supports the 1. mode.
1 parent 3ed9434 commit 4697c73

15 files changed

+154
-19
lines changed

src/bindgen/cdecl.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum CDeclarator {
2222
is_ref: bool,
2323
},
2424
Array(String),
25+
FlexibleArray(),
2526
Func {
2627
args: Vec<(Option<String>, CDecl)>,
2728
layout: Layout,
@@ -167,6 +168,10 @@ impl CDecl {
167168
self.declarators.push(CDeclarator::Array(len));
168169
self.build_type(t, is_const, config);
169170
}
171+
Type::FlexibleArray(ref t) => {
172+
self.declarators.push(CDeclarator::FlexibleArray());
173+
self.build_type(t, is_const, config);
174+
}
170175
Type::FuncPtr {
171176
ref ret,
172177
ref args,
@@ -254,7 +259,7 @@ impl CDecl {
254259
}
255260
}
256261
}
257-
CDeclarator::Array(..) => {
262+
CDeclarator::Array(..) | CDeclarator::FlexibleArray() => {
258263
if next_is_pointer {
259264
out.write("(");
260265
}
@@ -286,10 +291,26 @@ impl CDecl {
286291
if last_was_pointer {
287292
out.write(")");
288293
}
294+
289295
write!(out, "[{}]", constant);
290296

291297
last_was_pointer = false;
292298
}
299+
CDeclarator::FlexibleArray() => {
300+
if last_was_pointer {
301+
out.write(")");
302+
}
303+
304+
if config.structure.c99_flexible_array_members
305+
&& config.language != Language::Cython
306+
{
307+
write!(out, "[]");
308+
} else {
309+
write!(out, "[0]");
310+
}
311+
312+
last_was_pointer = false;
313+
}
293314
CDeclarator::Func {
294315
ref args,
295316
ref layout,

src/bindgen/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,8 @@ pub struct StructConfig {
499499
pub deprecated: Option<String>,
500500
/// The way to annotation this function as #[deprecated] with notes
501501
pub deprecated_with_note: Option<String>,
502+
/// The way we represent flexible array members, either GNU style or c99 style
503+
pub c99_flexible_array_members: bool,
502504
}
503505

504506
impl StructConfig {

src/bindgen/ir/structure.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl Struct {
7171
layout_config.ensure_safe_to_represent(&align)?;
7272
}
7373

74-
let fields = match item.fields {
74+
let mut fields = match item.fields {
7575
syn::Fields::Unit => Vec::new(),
7676
syn::Fields::Named(ref fields) => fields
7777
.named
@@ -97,6 +97,20 @@ impl Struct {
9797
}
9898
};
9999

100+
match fields.last() {
101+
Some(Field {
102+
name: _,
103+
ty: Type::Array(ty, sz),
104+
cfg: _,
105+
annotations: _,
106+
documentation: _,
107+
}) if sz.as_str() == "0" => {
108+
let last_index = fields.len() - 1;
109+
fields[last_index].ty = Type::FlexibleArray(ty.clone());
110+
}
111+
_ => (),
112+
}
113+
100114
let has_tag_field = false;
101115
let is_enum_variant_body = false;
102116

src/bindgen/ir/ty.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ pub enum Type {
317317
Path(GenericPath),
318318
Primitive(PrimitiveType),
319319
Array(Box<Type>, ConstExpr),
320+
FlexibleArray(Box<Type>),
320321
FuncPtr {
321322
ret: Box<Type>,
322323
args: Vec<(Option<String>, Type)>,
@@ -583,7 +584,9 @@ impl Type {
583584

584585
fn visit_types(&mut self, mut visitor: impl FnMut(&mut Type)) {
585586
match *self {
586-
Type::Array(ref mut ty, ..) | Type::Ptr { ref mut ty, .. } => visitor(ty),
587+
Type::Array(ref mut ty, ..)
588+
| Type::FlexibleArray(ref mut ty)
589+
| Type::Ptr { ref mut ty, .. } => visitor(ty),
587590
Type::Path(ref mut path) => {
588591
for generic in path.generics_mut() {
589592
match *generic {
@@ -617,7 +620,7 @@ impl Type {
617620
Type::Primitive(..) => {
618621
return None;
619622
}
620-
Type::Array(..) => {
623+
Type::Array(..) | Type::FlexibleArray(..) => {
621624
return None;
622625
}
623626
Type::FuncPtr { .. } => {
@@ -664,6 +667,7 @@ impl Type {
664667
Box::new(ty.specialize(mappings)),
665668
constant.specialize(mappings),
666669
),
670+
Type::FlexibleArray(ref ty) => Type::FlexibleArray(Box::new(ty.specialize(mappings))),
667671
Type::FuncPtr {
668672
ref ret,
669673
ref args,
@@ -721,7 +725,7 @@ impl Type {
721725
}
722726
}
723727
Type::Primitive(_) => {}
724-
Type::Array(ref ty, _) => {
728+
Type::Array(ref ty, _) | Type::FlexibleArray(ref ty) => {
725729
ty.add_dependencies_ignoring_generics(generic_params, library, out);
726730
}
727731
Type::FuncPtr {
@@ -757,7 +761,7 @@ impl Type {
757761
}
758762
}
759763
Type::Primitive(_) => {}
760-
Type::Array(ref ty, _) => {
764+
Type::Array(ref ty, _) | Type::FlexibleArray(ref ty) => {
761765
ty.add_monomorphs(library, out);
762766
}
763767
Type::FuncPtr {
@@ -784,6 +788,9 @@ impl Type {
784788
ty.rename_for_config(config, generic_params);
785789
len.rename_for_config(config);
786790
}
791+
Type::FlexibleArray(ref mut ty) => {
792+
ty.rename_for_config(config, generic_params);
793+
}
787794
Type::FuncPtr {
788795
ref mut ret,
789796
ref mut args,
@@ -806,7 +813,7 @@ impl Type {
806813
generic_path.resolve_declaration_types(resolver);
807814
}
808815
Type::Primitive(_) => {}
809-
Type::Array(ref mut ty, _) => {
816+
Type::Array(ref mut ty, _) | Type::FlexibleArray(ref mut ty) => {
810817
ty.resolve_declaration_types(resolver);
811818
}
812819
Type::FuncPtr {
@@ -843,7 +850,7 @@ impl Type {
843850
}
844851
}
845852
Type::Primitive(_) => {}
846-
Type::Array(ref mut ty, _) => {
853+
Type::Array(ref mut ty, _) | Type::FlexibleArray(ref mut ty) => {
847854
ty.mangle_paths(monomorphs);
848855
}
849856
Type::FuncPtr {
@@ -866,6 +873,7 @@ impl Type {
866873
Type::Path(..) => true,
867874
Type::Primitive(ref p) => p.can_cmp_order(),
868875
Type::Array(..) => false,
876+
Type::FlexibleArray(..) => false,
869877
Type::FuncPtr { .. } => false,
870878
}
871879
}
@@ -876,6 +884,7 @@ impl Type {
876884
Type::Path(..) => true,
877885
Type::Primitive(ref p) => p.can_cmp_eq(),
878886
Type::Array(..) => false,
887+
Type::FlexibleArray(..) => false,
879888
Type::FuncPtr { .. } => true,
880889
}
881890
}

src/bindgen/mangle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl<'a> Mangler<'a> {
128128
self.push(Separator::EndFn);
129129
}
130130
}
131-
Type::Array(..) => {
131+
Type::Array(..) | Type::FlexibleArray(..) => {
132132
unimplemented!(
133133
"Unable to mangle generic parameter {:?} for '{}'",
134134
ty,

tests/expectations/struct.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,15 @@ typedef struct {
2525
float y;
2626
} TupleNamed;
2727

28-
void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e);
28+
typedef struct {
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[];
32+
} WithFlexibleArrayMember;
33+
34+
void root(Opaque *a,
35+
Normal b,
36+
NormalWithZST c,
37+
TupleRenamed d,
38+
TupleNamed e,
39+
WithFlexibleArrayMember f);

tests/expectations/struct.compat.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,22 @@ typedef struct {
2525
float y;
2626
} TupleNamed;
2727

28+
typedef struct {
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[];
32+
} WithFlexibleArrayMember;
33+
2834
#ifdef __cplusplus
2935
extern "C" {
3036
#endif // __cplusplus
3137

32-
void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e);
38+
void root(Opaque *a,
39+
Normal b,
40+
NormalWithZST c,
41+
TupleRenamed d,
42+
TupleNamed e,
43+
WithFlexibleArrayMember f);
3344

3445
#ifdef __cplusplus
3546
} // extern "C"

tests/expectations/struct.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,19 @@ struct TupleNamed {
2626
float y;
2727
};
2828

29+
struct WithFlexibleArrayMember {
30+
int32_t x;
31+
int16_t y[0];
32+
int8_t z[];
33+
};
34+
2935
extern "C" {
3036

31-
void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e);
37+
void root(Opaque *a,
38+
Normal b,
39+
NormalWithZST c,
40+
TupleRenamed d,
41+
TupleNamed e,
42+
WithFlexibleArrayMember f);
3243

3344
} // extern "C"

tests/expectations/struct.pyx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,14 @@ cdef extern from *:
2525
int32_t x;
2626
float y;
2727

28-
void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e);
28+
ctypedef struct WithFlexibleArrayMember:
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[0];
32+
33+
void root(Opaque *a,
34+
Normal b,
35+
NormalWithZST c,
36+
TupleRenamed d,
37+
TupleNamed e,
38+
WithFlexibleArrayMember f);

tests/expectations/struct_both.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,15 @@ typedef struct TupleNamed {
2525
float y;
2626
} TupleNamed;
2727

28+
typedef struct WithFlexibleArrayMember {
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[];
32+
} WithFlexibleArrayMember;
33+
2834
void root(struct Opaque *a,
2935
struct Normal b,
3036
struct NormalWithZST c,
3137
struct TupleRenamed d,
32-
struct TupleNamed e);
38+
struct TupleNamed e,
39+
struct WithFlexibleArrayMember f);

tests/expectations/struct_both.compat.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ typedef struct TupleNamed {
2525
float y;
2626
} TupleNamed;
2727

28+
typedef struct WithFlexibleArrayMember {
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[];
32+
} WithFlexibleArrayMember;
33+
2834
#ifdef __cplusplus
2935
extern "C" {
3036
#endif // __cplusplus
@@ -33,7 +39,8 @@ void root(struct Opaque *a,
3339
struct Normal b,
3440
struct NormalWithZST c,
3541
struct TupleRenamed d,
36-
struct TupleNamed e);
42+
struct TupleNamed e,
43+
struct WithFlexibleArrayMember f);
3744

3845
#ifdef __cplusplus
3946
} // extern "C"

tests/expectations/struct_tag.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,15 @@ struct TupleNamed {
2525
float y;
2626
};
2727

28+
struct WithFlexibleArrayMember {
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[];
32+
};
33+
2834
void root(struct Opaque *a,
2935
struct Normal b,
3036
struct NormalWithZST c,
3137
struct TupleRenamed d,
32-
struct TupleNamed e);
38+
struct TupleNamed e,
39+
struct WithFlexibleArrayMember f);

tests/expectations/struct_tag.compat.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ struct TupleNamed {
2525
float y;
2626
};
2727

28+
struct WithFlexibleArrayMember {
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[];
32+
};
33+
2834
#ifdef __cplusplus
2935
extern "C" {
3036
#endif // __cplusplus
@@ -33,7 +39,8 @@ void root(struct Opaque *a,
3339
struct Normal b,
3440
struct NormalWithZST c,
3541
struct TupleRenamed d,
36-
struct TupleNamed e);
42+
struct TupleNamed e,
43+
struct WithFlexibleArrayMember f);
3744

3845
#ifdef __cplusplus
3946
} // extern "C"

tests/expectations/struct_tag.pyx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,14 @@ cdef extern from *:
2525
int32_t x;
2626
float y;
2727

28-
void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e);
28+
cdef struct WithFlexibleArrayMember:
29+
int32_t x;
30+
int16_t y[0];
31+
int8_t z[0];
32+
33+
void root(Opaque *a,
34+
Normal b,
35+
NormalWithZST c,
36+
TupleRenamed d,
37+
TupleNamed e,
38+
WithFlexibleArrayMember f);

tests/rust/struct.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,19 @@ struct TupleRenamed(i32, f32);
2828
#[repr(C)]
2929
struct TupleNamed(i32, f32);
3030

31+
#[repr(C)]
32+
struct WithFlexibleArrayMember {
33+
x: i32,
34+
y: [i16; 0],
35+
z: [i8; 0],
36+
}
37+
3138
#[no_mangle]
3239
pub extern "C" fn root(
3340
a: *mut Opaque,
3441
b: Normal,
3542
c: NormalWithZST,
3643
d: TupleRenamed,
37-
e: TupleNamed
44+
e: TupleNamed,
45+
f: WithFlexibleArrayMember,
3846
) { }

0 commit comments

Comments
 (0)