Skip to content

Commit 228f7df

Browse files
committed
Do not emit enum TagName tag when a sized representation is present.
This affected cases where the style was set to `Stle::Tag`. In enumerations, do not emut the tag type name with an `enum` prefix. C treats the `enum` type as an `int` even if the representation should be something else. Here's an example non-C-like-enumeration: #[repr(C, u8)] enum P { P1(u8), P2(u8, u8), P3(u8, u8, u8), } Without this patch, this is what's generated: enum P_Tag { P1, P2, P3, }; typedef uint8_t P_Tag; typedef struct { uint8_t _0; } P1_Body; typedef struct { uint8_t _0; uint8_t _1; } P2_Body; typedef struct { uint8_t _0; uint8_t _1; uint8_t _2; } P3_Body; typedef struct { enum P_Tag tag; union { P1_Body p1; P2_Body p2; P3_Body p3; }; } P; Rust expects the size of the type to be 4 (one for the discriminant, and 3 for the widest alternative. C, however, treats the `enum P_Tag tag` field as an `int` rather than a `uint8_t`. This puts the size (with padding) of of `P` to 8 bytes instead of 4. When passing this type between Rust and C, they will disagree on the size. After the patch is applied, the `P` struct is properly defined: typedef struct { P_Tag tag; union { P1_Body p1; P2_Body p2; P3_Body p3; }; } P;
1 parent 68997fe commit 228f7df

28 files changed

+182
-48
lines changed

src/bindgen/ir/enumeration.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,8 @@ impl Source for Enum {
682682
out.open_brace();
683683
}
684684

685-
if config.language == Language::C && !config.style.generate_typedef() {
685+
if config.language == Language::C && !size.is_some() && !config.style.generate_typedef()
686+
{
686687
out.write("enum ");
687688
}
688689

tests/expectations/both/enum.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,30 @@ typedef struct I {
157157
};
158158
} I;
159159

160+
enum P_Tag {
161+
P0,
162+
P1,
163+
};
164+
typedef uint8_t P_Tag;
165+
166+
typedef struct P0_Body {
167+
uint8_t _0;
168+
} P0_Body;
169+
170+
typedef struct P1_Body {
171+
uint8_t _0;
172+
uint8_t _1;
173+
uint8_t _2;
174+
} P1_Body;
175+
176+
typedef struct P {
177+
P_Tag tag;
178+
union {
179+
P0_Body p0;
180+
P1_Body p1;
181+
};
182+
} P;
183+
160184
void root(Opaque *opaque,
161185
A a,
162186
B b,
@@ -172,4 +196,12 @@ void root(Opaque *opaque,
172196
L l,
173197
M m,
174198
N n,
175-
O o);
199+
O o,
200+
P p);
201+
202+
#include <stddef.h>
203+
#include "testing-helpers.h"
204+
static_assert(offsetof(CBINDGEN_STRUCT(P), tag) == 0, "unexpected offset for tag");
205+
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p0");
206+
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p1");
207+
static_assert(sizeof(CBINDGEN_STRUCT(P)) == 4, "unexpected size for P");

tests/expectations/both/enum.compat.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,36 @@ typedef struct I {
217217
};
218218
} I;
219219

220+
enum P_Tag
221+
#ifdef __cplusplus
222+
: uint8_t
223+
#endif // __cplusplus
224+
{
225+
P0,
226+
P1,
227+
};
228+
#ifndef __cplusplus
229+
typedef uint8_t P_Tag;
230+
#endif // __cplusplus
231+
232+
typedef struct P0_Body {
233+
uint8_t _0;
234+
} P0_Body;
235+
236+
typedef struct P1_Body {
237+
uint8_t _0;
238+
uint8_t _1;
239+
uint8_t _2;
240+
} P1_Body;
241+
242+
typedef struct P {
243+
P_Tag tag;
244+
union {
245+
P0_Body p0;
246+
P1_Body p1;
247+
};
248+
} P;
249+
220250
#ifdef __cplusplus
221251
extern "C" {
222252
#endif // __cplusplus
@@ -236,8 +266,16 @@ void root(Opaque *opaque,
236266
L l,
237267
M m,
238268
N n,
239-
O o);
269+
O o,
270+
P p);
240271

241272
#ifdef __cplusplus
242273
} // extern "C"
243274
#endif // __cplusplus
275+
276+
#include <stddef.h>
277+
#include "testing-helpers.h"
278+
static_assert(offsetof(CBINDGEN_STRUCT(P), tag) == 0, "unexpected offset for tag");
279+
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p0");
280+
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p1");
281+
static_assert(sizeof(CBINDGEN_STRUCT(P)) == 4, "unexpected size for P");

tests/expectations/enum.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,29 @@ struct I {
149149
};
150150
};
151151

152+
struct P {
153+
enum class Tag : uint8_t {
154+
P0,
155+
P1,
156+
};
157+
158+
struct P0_Body {
159+
uint8_t _0;
160+
};
161+
162+
struct P1_Body {
163+
uint8_t _0;
164+
uint8_t _1;
165+
uint8_t _2;
166+
};
167+
168+
Tag tag;
169+
union {
170+
P0_Body p0;
171+
P1_Body p1;
172+
};
173+
};
174+
152175
extern "C" {
153176

154177
void root(Opaque *opaque,
@@ -166,6 +189,14 @@ void root(Opaque *opaque,
166189
L l,
167190
M m,
168191
N n,
169-
O o);
192+
O o,
193+
P p);
170194

171195
} // extern "C"
196+
197+
#include <stddef.h>
198+
#include "testing-helpers.h"
199+
static_assert(offsetof(CBINDGEN_STRUCT(P), tag) == 0, "unexpected offset for tag");
200+
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p0");
201+
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p1");
202+
static_assert(sizeof(CBINDGEN_STRUCT(P)) == 4, "unexpected size for P");

tests/expectations/tag/annotation.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct Bar_Body {
3737
};
3838

3939
union F {
40-
enum F_Tag tag;
40+
F_Tag tag;
4141
struct Foo_Body foo;
4242
struct Bar_Body bar;
4343
};
@@ -59,7 +59,7 @@ struct There_Body {
5959
};
6060

6161
struct H {
62-
enum H_Tag tag;
62+
H_Tag tag;
6363
union {
6464
struct Hello_Body hello;
6565
struct There_Body there;

tests/expectations/tag/annotation.compat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ struct Bar_Body {
4949
};
5050

5151
union F {
52-
enum F_Tag tag;
52+
F_Tag tag;
5353
struct Foo_Body foo;
5454
struct Bar_Body bar;
5555
};
@@ -77,7 +77,7 @@ struct There_Body {
7777
};
7878

7979
struct H {
80-
enum H_Tag tag;
80+
H_Tag tag;
8181
union {
8282
struct Hello_Body hello;
8383
struct There_Body there;

tests/expectations/tag/asserted-cast.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ struct H_Bar_Body {
2525
};
2626

2727
struct H {
28-
enum H_Tag tag;
28+
H_Tag tag;
2929
union {
3030
struct H_Foo_Body foo;
3131
struct H_Bar_Body bar;
@@ -49,7 +49,7 @@ struct J_Bar_Body {
4949
};
5050

5151
struct J {
52-
enum J_Tag tag;
52+
J_Tag tag;
5353
union {
5454
struct J_Foo_Body foo;
5555
struct J_Bar_Body bar;
@@ -75,7 +75,7 @@ struct K_Bar_Body {
7575
};
7676

7777
union K {
78-
enum K_Tag tag;
78+
K_Tag tag;
7979
struct K_Foo_Body foo;
8080
struct K_Bar_Body bar;
8181
};

tests/expectations/tag/asserted-cast.compat.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct H_Bar_Body {
3131
};
3232

3333
struct H {
34-
enum H_Tag tag;
34+
H_Tag tag;
3535
union {
3636
struct H_Foo_Body foo;
3737
struct H_Bar_Body bar;
@@ -61,7 +61,7 @@ struct J_Bar_Body {
6161
};
6262

6363
struct J {
64-
enum J_Tag tag;
64+
J_Tag tag;
6565
union {
6666
struct J_Foo_Body foo;
6767
struct J_Bar_Body bar;
@@ -93,7 +93,7 @@ struct K_Bar_Body {
9393
};
9494

9595
union K {
96-
enum K_Tag tag;
96+
K_Tag tag;
9797
struct K_Foo_Body foo;
9898
struct K_Bar_Body bar;
9999
};

tests/expectations/tag/derive-eq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct FooParen_Body {
3434
};
3535

3636
union Bar {
37-
enum Bar_Tag tag;
37+
Bar_Tag tag;
3838
struct Bazz_Body bazz;
3939
struct FooNamed_Body foo_named;
4040
struct FooParen_Body foo_paren;

tests/expectations/tag/derive-eq.compat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct FooParen_Body {
4040
};
4141

4242
union Bar {
43-
enum Bar_Tag tag;
43+
Bar_Tag tag;
4444
struct Bazz_Body bazz;
4545
struct FooNamed_Body foo_named;
4646
struct FooParen_Body foo_paren;

0 commit comments

Comments
 (0)