2020-01-24 06:34:00 +01:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
enum A
|
|
|
|
#ifdef __cplusplus
|
|
|
|
: uint8_t
|
|
|
|
#endif // __cplusplus
|
|
|
|
{
|
|
|
|
A_A1,
|
|
|
|
A_A2,
|
|
|
|
A_A3,
|
|
|
|
/**
|
|
|
|
* Must be last for serialization purposes
|
|
|
|
*/
|
|
|
|
A_Sentinel,
|
|
|
|
};
|
|
|
|
#ifndef __cplusplus
|
|
|
|
typedef uint8_t A;
|
|
|
|
#endif // __cplusplus
|
|
|
|
|
|
|
|
enum B
|
|
|
|
#ifdef __cplusplus
|
|
|
|
: uint8_t
|
|
|
|
#endif // __cplusplus
|
|
|
|
{
|
|
|
|
B_B1,
|
|
|
|
B_B2,
|
|
|
|
B_B3,
|
|
|
|
/**
|
|
|
|
* Must be last for serialization purposes
|
|
|
|
*/
|
|
|
|
B_Sentinel,
|
|
|
|
};
|
|
|
|
#ifndef __cplusplus
|
|
|
|
typedef uint8_t B;
|
|
|
|
#endif // __cplusplus
|
|
|
|
|
|
|
|
enum C_Tag
|
|
|
|
#ifdef __cplusplus
|
|
|
|
: uint8_t
|
|
|
|
#endif // __cplusplus
|
|
|
|
{
|
|
|
|
C_C1,
|
|
|
|
C_C2,
|
|
|
|
C_C3,
|
|
|
|
/**
|
|
|
|
* Must be last for serialization purposes
|
|
|
|
*/
|
|
|
|
C_Sentinel,
|
|
|
|
};
|
|
|
|
#ifndef __cplusplus
|
|
|
|
typedef uint8_t C_Tag;
|
|
|
|
#endif // __cplusplus
|
|
|
|
|
|
|
|
struct C_C1_Body {
|
|
|
|
C_Tag tag;
|
|
|
|
uint32_t a;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct C_C2_Body {
|
|
|
|
C_Tag tag;
|
|
|
|
uint32_t b;
|
|
|
|
};
|
|
|
|
|
|
|
|
union C {
|
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
|
|
|
C_Tag tag;
|
2020-01-24 06:34:00 +01:00
|
|
|
struct C_C1_Body c1;
|
|
|
|
struct C_C2_Body c2;
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif // __cplusplus
|
|
|
|
|
|
|
|
void root(A a, B b, union C c);
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
} // extern "C"
|
|
|
|
#endif // __cplusplus
|