2018-11-27 00:13:34 +00:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
2018-03-15 16:23:42 +01:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
enum A {
|
|
|
|
a1 = 0,
|
|
|
|
a2 = 2,
|
|
|
|
a3,
|
|
|
|
a4 = 5,
|
|
|
|
};
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef uint64_t A;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
|
|
|
enum B {
|
|
|
|
b1 = 0,
|
|
|
|
b2 = 2,
|
|
|
|
b3,
|
|
|
|
b4 = 5,
|
|
|
|
};
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef uint32_t B;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
|
|
|
enum C {
|
|
|
|
c1 = 0,
|
|
|
|
c2 = 2,
|
|
|
|
c3,
|
|
|
|
c4 = 5,
|
|
|
|
};
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef uint16_t C;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
|
|
|
enum D {
|
|
|
|
d1 = 0,
|
|
|
|
d2 = 2,
|
|
|
|
d3,
|
|
|
|
d4 = 5,
|
|
|
|
};
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef uint8_t D;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
|
|
|
enum E {
|
|
|
|
e1 = 0,
|
|
|
|
e2 = 2,
|
|
|
|
e3,
|
|
|
|
e4 = 5,
|
|
|
|
};
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef uintptr_t E;
|
2018-11-24 19:11:02 +01:00
|
|
|
|
2019-12-22 23:36:56 +11:00
|
|
|
enum F {
|
|
|
|
f1 = 0,
|
|
|
|
f2 = 2,
|
|
|
|
f3,
|
|
|
|
f4 = 5,
|
|
|
|
};
|
|
|
|
typedef intptr_t F;
|
|
|
|
|
|
|
|
typedef enum L {
|
|
|
|
l1,
|
|
|
|
l2,
|
|
|
|
l3,
|
|
|
|
l4,
|
|
|
|
} L;
|
|
|
|
|
|
|
|
enum M {
|
|
|
|
m1 = -1,
|
|
|
|
m2 = 0,
|
|
|
|
m3 = 1,
|
|
|
|
};
|
|
|
|
typedef int8_t M;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
2019-12-29 18:39:12 +13:00
|
|
|
typedef enum N {
|
|
|
|
n1,
|
|
|
|
n2,
|
|
|
|
n3,
|
|
|
|
n4,
|
|
|
|
} N;
|
|
|
|
|
|
|
|
enum O {
|
|
|
|
o1,
|
|
|
|
o2,
|
|
|
|
o3,
|
|
|
|
o4,
|
|
|
|
};
|
|
|
|
typedef int8_t O;
|
|
|
|
|
2018-03-15 16:23:42 +01:00
|
|
|
typedef struct J J;
|
|
|
|
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef struct K K;
|
|
|
|
|
2018-03-15 16:23:42 +01:00
|
|
|
typedef struct Opaque Opaque;
|
|
|
|
|
2019-12-22 23:36:56 +11:00
|
|
|
enum G_Tag {
|
2018-03-15 16:23:42 +01:00
|
|
|
Foo,
|
|
|
|
Bar,
|
|
|
|
Baz,
|
|
|
|
};
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef uint8_t G_Tag;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
|
|
|
typedef struct Foo_Body {
|
2019-12-22 23:36:56 +11:00
|
|
|
G_Tag tag;
|
2018-03-15 16:23:42 +01:00
|
|
|
int16_t _0;
|
|
|
|
} Foo_Body;
|
|
|
|
|
|
|
|
typedef struct Bar_Body {
|
2019-12-22 23:36:56 +11:00
|
|
|
G_Tag tag;
|
2018-03-15 16:23:42 +01:00
|
|
|
uint8_t x;
|
|
|
|
int16_t y;
|
|
|
|
} Bar_Body;
|
|
|
|
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef union G {
|
|
|
|
G_Tag tag;
|
2018-03-15 16:23:42 +01:00
|
|
|
Foo_Body foo;
|
|
|
|
Bar_Body bar;
|
|
|
|
} G;
|
|
|
|
|
2019-12-22 23:36:56 +11:00
|
|
|
typedef enum H_Tag {
|
2018-03-15 16:23:42 +01:00
|
|
|
H_Foo,
|
|
|
|
H_Bar,
|
|
|
|
H_Baz,
|
2019-12-22 23:36:56 +11:00
|
|
|
} H_Tag;
|
2018-03-15 16:23:42 +01:00
|
|
|
|
|
|
|
typedef struct H_Foo_Body {
|
|
|
|
int16_t _0;
|
|
|
|
} H_Foo_Body;
|
|
|
|
|
|
|
|
typedef struct H_Bar_Body {
|
|
|
|
uint8_t x;
|
|
|
|
int16_t y;
|
|
|
|
} H_Bar_Body;
|
|
|
|
|
|
|
|
typedef struct H {
|
|
|
|
H_Tag tag;
|
|
|
|
union {
|
|
|
|
H_Foo_Body foo;
|
|
|
|
H_Bar_Body bar;
|
|
|
|
};
|
|
|
|
} H;
|
|
|
|
|
2019-12-22 23:36:56 +11:00
|
|
|
enum I_Tag {
|
|
|
|
I_Foo,
|
|
|
|
I_Bar,
|
|
|
|
I_Baz,
|
|
|
|
};
|
|
|
|
typedef uint8_t I_Tag;
|
|
|
|
|
|
|
|
typedef struct I_Foo_Body {
|
|
|
|
int16_t _0;
|
|
|
|
} I_Foo_Body;
|
|
|
|
|
|
|
|
typedef struct I_Bar_Body {
|
|
|
|
uint8_t x;
|
|
|
|
int16_t y;
|
|
|
|
} I_Bar_Body;
|
|
|
|
|
|
|
|
typedef struct I {
|
|
|
|
I_Tag tag;
|
|
|
|
union {
|
|
|
|
I_Foo_Body foo;
|
|
|
|
I_Bar_Body bar;
|
|
|
|
};
|
|
|
|
} I;
|
|
|
|
|
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;
2020-01-24 23:28:27 -08:00
|
|
|
enum P_Tag {
|
|
|
|
P0,
|
|
|
|
P1,
|
|
|
|
};
|
|
|
|
typedef uint8_t P_Tag;
|
|
|
|
|
|
|
|
typedef struct P0_Body {
|
|
|
|
uint8_t _0;
|
|
|
|
} P0_Body;
|
|
|
|
|
|
|
|
typedef struct P1_Body {
|
|
|
|
uint8_t _0;
|
|
|
|
uint8_t _1;
|
|
|
|
uint8_t _2;
|
|
|
|
} P1_Body;
|
|
|
|
|
|
|
|
typedef struct P {
|
|
|
|
P_Tag tag;
|
|
|
|
union {
|
|
|
|
P0_Body p0;
|
|
|
|
P1_Body p1;
|
|
|
|
};
|
|
|
|
} P;
|
|
|
|
|
2019-12-29 18:39:12 +13:00
|
|
|
void root(Opaque *opaque,
|
|
|
|
A a,
|
|
|
|
B b,
|
|
|
|
C c,
|
|
|
|
D d,
|
|
|
|
E e,
|
|
|
|
F f,
|
|
|
|
G g,
|
|
|
|
H h,
|
|
|
|
I i,
|
|
|
|
J j,
|
|
|
|
K k,
|
|
|
|
L l,
|
|
|
|
M m,
|
|
|
|
N n,
|
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;
2020-01-24 23:28:27 -08:00
|
|
|
O o,
|
|
|
|
P p);
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "testing-helpers.h"
|
|
|
|
static_assert(offsetof(CBINDGEN_STRUCT(P), tag) == 0, "unexpected offset for tag");
|
|
|
|
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p0");
|
|
|
|
static_assert(offsetof(CBINDGEN_STRUCT(P), p0) == 1, "unexpected offset for p1");
|
|
|
|
static_assert(sizeof(CBINDGEN_STRUCT(P)) == 4, "unexpected size for P");
|