mozilla / cbindgen

A project for generating C bindings from Rust code
Mozilla Public License 2.0
2.37k stars 306 forks source link

Enums with `repr(u8)` cause warnings because of the anonymous struct containing the tag. #829

Open ogoffart opened 1 year ago

ogoffart commented 1 year ago

Given an enum with #[repr(u8)], for example

https://github.com/mozilla/cbindgen/blob/52a65e5be3d8c6a2648fbe3bc6a9001a96f0756c/tests/rust/enum.rs#L54-L59

When generating the code for C++, it will generate an anonymous struct

https://github.com/mozilla/cbindgen/blob/52a65e5be3d8c6a2648fbe3bc6a9001a96f0756c/tests/expectations/enum.cpp#L114-L116

But this is not valid C++ and that doesn't compile with -pedantic because anonymous struct is a gnu extension

Gcc:

warning: ISO C++ prohibits anonymous structs [-Wpedantic]

Clang:

warning: anonymous structs are a GNU extension [-Wgnu-anonymous-struct]

MSVC

warning C4201: nonstandard extension used: nameless struct/union

https://godbolt.org/z/f4x7T137T

The anonymous union was added because of #122

One fix would be to generate the struct with a name

struct {
    Tag tag;
} tag;

And then access it with tag.tag. That would unfortunately be a breaking change. Alternative is to revert the fix for #122 . I believe accessing the value directly should be supported as an extension as well by all compiler.

(Reported because of https://github.com/slint-ui/slint/issues/2681 )

emilio commented 1 year ago

Yeah this is tricky. I think the current code is strictly more correct than not generating the anon struct... but I'd rather revert #122 than introducing the breaking change tho. If reverting #122 doesn't cause UBSan or so to complain I think that'd be acceptable, IMO.

As a workaround slint can probably add #pragmas to ignore this warning but yeah, that's not great

ogoffart commented 1 year ago

I couldn't manage to get ubsan generating any warning when accessing wrong member of union (even when it is an obvious UB)