Description
Originally posted by @kainino0x in #270 (comment)
Currently extended bitflag entries are similar to enums, but I think we should change generation of all bitflag entries to be
static const T N = V
instead of enum, because we need to make them 64bit anyway. Vulkan does the same for 64bit bitflags
Ah... unfortunate. I dug a little to figure out why this was the case in Vulkan. Clang makes it clear - and this is also the reason Force32 is 0x7fffffff instead of 0xffffffff.
warning: ISO C restricts enumerator values to range of 'int' (4294967295 is too large) [-Wpedantic]
C++ seems to have no such complaints for enum class
, so Dawn should still be able to do the thing we do in C++ to make strongly-typed bitflags from enum class
.
C++ also seems to have no complains for enum
, which means we could use enum
behind #ifdef __cplusplus
, for added type safety. Doing so would be consistent with #159, where we were going to do the operator|
thing to make C++ happy with our usage of enum
s as bitflags. But having separate C and C++ definitions of entire enums is annoying, and also sketchy - it almost certainly breaks ABI compatibility between the C and C++ versions.
So I think we are going to have to scrap the operator|
thing and just use 64-bit constants. Too bad.
the downside being we loose exhaustive switches in C++ over new entries
Actually this raises another interesting point - if we extend enums outside the enum definition, then it becomes easy to write a switch that passes the exhaustiveness check, but is not actually exhaustive. Of course, this was always true of bitflags, and generally true if you cast numbers to enums, but those are corner cases.
This is probably fine, it just adds a little bit of a false sense of security. Almost certainly better to get some warnings than no warnings.
Most enums won't be commonly in application code anyway. The enums we do pass out to the application may get extended, but for most enums, we should never start returning new values to existing applications unless we enable some feature, so exhaustivity over the core enum is all that really matters.
For reference, I think the only enums where we may suddenly start passing out new values to the application are FeatureName
(in AdapterEnumerateFeatures, but not DeviceEnumerateFeatures) and WGSLFeatureName
(in GetInstanceFeatures or whatever we end up calling it). Not SType
, I think, if we solve #272.
Maybe... after we stabilize, we should just never change the enum definitions and only extend them using static const
? (maybe even rename Force32 to indicate it's there to make the enum extensible/non-exhaustive, as anyone writing exhaustive switches will end up having to type Force32)
(Aside, apparently there is a gcc/clang flag that checks for exhaustive switches even with default. I am now tempted to try this in Dawn. https://brevzin.github.io/c++/2019/08/01/enums-default/#the-warning-that-exists)