From 05cde18f9c87316adaf0e8e6af957482f38ce406 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Thu, 15 Aug 2024 15:03:01 +0200 Subject: [PATCH] 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). Let's generate the standard syntax by default, while leaving it possible to use 1. through struct.gnu_flexible_array_members Cython only supports the 1. mode. --- src/bindgen/cdecl.rs | 13 +++++++++++-- src/bindgen/config.rs | 2 ++ tests/expectations/struct.c | 12 +++++++++++- tests/expectations/struct.compat.c | 12 +++++++++++- tests/expectations/struct.cpp | 12 +++++++++++- tests/expectations/struct.pyx | 11 ++++++++++- tests/expectations/struct_both.c | 8 +++++++- tests/expectations/struct_both.compat.c | 8 +++++++- tests/expectations/struct_tag.c | 8 +++++++- tests/expectations/struct_tag.compat.c | 8 +++++++- tests/expectations/struct_tag.pyx | 11 ++++++++++- tests/rust/struct.rs | 9 ++++++++- 12 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/bindgen/cdecl.rs b/src/bindgen/cdecl.rs index 3ba543ac9..42b0987a0 100644 --- a/src/bindgen/cdecl.rs +++ b/src/bindgen/cdecl.rs @@ -273,7 +273,7 @@ impl CDecl { } // Write the right part of declarators after the identifier - let mut iter = self.declarators.iter(); + let mut iter = self.declarators.iter().peekable(); let mut last_was_pointer = false; #[allow(clippy::while_let_on_iterator)] @@ -286,7 +286,16 @@ impl CDecl { if last_was_pointer { out.write(")"); } - write!(out, "[{}]", constant); + + let is_fam = constant == "0" && iter.peek().is_none(); + if is_fam + && !config.structure.gnu_flexible_array_members + && config.language != Language::Cython + { + write!(out, "[]"); + } else { + write!(out, "[{}]", constant); + } last_was_pointer = false; } diff --git a/src/bindgen/config.rs b/src/bindgen/config.rs index 31316503d..aa2164fec 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 gnu_flexible_array_members: bool, } impl StructConfig { diff --git a/tests/expectations/struct.c b/tests/expectations/struct.c index 207e9a052..ef9730c14 100644 --- a/tests/expectations/struct.c +++ b/tests/expectations/struct.c @@ -25,4 +25,14 @@ typedef struct { float y; } TupleNamed; -void root(Opaque *a, Normal b, NormalWithZST c, TupleRenamed d, TupleNamed e); +typedef struct { + int32_t x; + int8_t y[]; +} 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 fd82fcd1e..01e5d0572 100644 --- a/tests/expectations/struct.compat.c +++ b/tests/expectations/struct.compat.c @@ -25,11 +25,21 @@ typedef struct { float y; } TupleNamed; +typedef struct { + int32_t x; + int8_t y[]; +} 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 4fe03404d..592299f27 100644 --- a/tests/expectations/struct.cpp +++ b/tests/expectations/struct.cpp @@ -26,8 +26,18 @@ struct TupleNamed { float y; }; +struct WithFlexibleArrayMember { + int32_t x; + int8_t y[]; +}; + 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 3342101fa..5d795e11a 100644 --- a/tests/expectations/struct.pyx +++ b/tests/expectations/struct.pyx @@ -25,4 +25,13 @@ 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; + int8_t y[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 5664185f9..25d10bdce 100644 --- a/tests/expectations/struct_both.c +++ b/tests/expectations/struct_both.c @@ -25,8 +25,14 @@ typedef struct TupleNamed { float y; } TupleNamed; +typedef struct WithFlexibleArrayMember { + int32_t x; + int8_t y[]; +} 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 ee0f4c761..ab4c6aa04 100644 --- a/tests/expectations/struct_both.compat.c +++ b/tests/expectations/struct_both.compat.c @@ -25,6 +25,11 @@ typedef struct TupleNamed { float y; } TupleNamed; +typedef struct WithFlexibleArrayMember { + int32_t x; + int8_t y[]; +} WithFlexibleArrayMember; + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -33,7 +38,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 cc5ddaa75..76ac9f21e 100644 --- a/tests/expectations/struct_tag.c +++ b/tests/expectations/struct_tag.c @@ -25,8 +25,14 @@ struct TupleNamed { float y; }; +struct WithFlexibleArrayMember { + int32_t x; + int8_t y[]; +}; + 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 092007c03..5fe2021a3 100644 --- a/tests/expectations/struct_tag.compat.c +++ b/tests/expectations/struct_tag.compat.c @@ -25,6 +25,11 @@ struct TupleNamed { float y; }; +struct WithFlexibleArrayMember { + int32_t x; + int8_t y[]; +}; + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -33,7 +38,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 768f37521..f8fa226e3 100644 --- a/tests/expectations/struct_tag.pyx +++ b/tests/expectations/struct_tag.pyx @@ -25,4 +25,13 @@ 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; + int8_t y[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 7569901a4..c443ced92 100644 --- a/tests/rust/struct.rs +++ b/tests/rust/struct.rs @@ -28,11 +28,18 @@ struct TupleRenamed(i32, f32); #[repr(C)] struct TupleNamed(i32, f32); +#[repr(C)] +struct WithFlexibleArrayMember { + x: i32, + y: [i8; 0], +} + #[no_mangle] pub extern "C" fn root( a: *mut Opaque, b: Normal, c: NormalWithZST, d: TupleRenamed, - e: TupleNamed + e: TupleNamed, + f: WithFlexibleArrayMember, ) { }