A u32 bitflags structure should allow a 1<<31 value. However, with
current cbindgen this produces a compiler error with latest clang, because
1<<31 is treated as a signed value (-2147483648) which cannot be narrowed
back into a uint32_t without a cast.
We don't support unnamed arguments, and we give a terrible error
("Parameter has an unsupported type.") when you use them.
They're very simple to implement so we should just do it.
By checking the recursion depth in the crate we are currently parsing,
we can decide on the right module directory to find submodules in. The
added `mod_2018` test fails without the changes to `parser.rs`.
As noted by @Benlitz, Cargo metadata supports directly specifying the
target name instead of using the `#[cfg]` syntax. We can support this by
manually creating the `syn::NestedMeta` node from the target name seen
as a string literal.
This is needed when running tests with clang/clang++, as some of the tests have
errors that clang reports which gcc does not such as unused static const
variables.
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;
This will be useful to add static assertion to some tests like #463 wants to do.
For example, in the case of the test for #463, the test would need something
like:
trailer = """
#include <assert.h>
#if defined(CBINDGEN_STYLE_TAG) && !defined(__cplusplus)
static_assert(sizeof(struct P) == 4, "unexpected size for P");
#else
static_assert(sizeof(P) == 4, "unexpected size for P");
#endif
"""
As more of these tests are added it may be worth just adding a helper header
like this to avoid some duplication:
#include <assert.h>
#if defined(CBINDGEN_STYLE_TAG) && !defined(__cplusplus)
#define CBINDGEN_STRUCT(name) struct name
#else
#define CBINDGEN_STRUCT(name) name
#endif
And so on, so the previous configuration would become just:
trailer = """
#include "testing-helpers.h" // Or whatever
static_assert(sizeof(CBINDGEN_STRUCT(P)) == 4, "unexpected size for P");
"""
That may or may not be overkill to do as part of #463.