-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix uniform type enum UB regarding extra fragment-bit. #3398
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this... Where exactly is UB?
See here. Copying the excerpt here:
So this would mean that the casts in lines such as: Line 5093 in de56398
are not allowed (since C++17 🤷?), since the cast from the integral type to the enum type is not a value within the range of the enumeration values. |
I must admit that I also don't like this PR. This is just annoying language semantics/rules sitting in the way of doing something efficient AND readable. You may propose an alternative that would also get rid of the UB, which is more to your liking, and I'll take care of it! I like clang's ubsan. I found many bugs in my software already. I think this is good practice to have this turned on for debug builds. |
Alternative is to add annotation around, or special inline function that would do conversion that would turn off asan checks for that particular thing. |
What about something along the lines of: template<typename E, int EnumBits>
struct EnumWithBits {
static constexpr std::underlying_t<E> mask = (1 << EnumBits) - 1;
std::underlying_t<E> value;
inline void set(E eval, int bits) {
assert(eval & mask == eval);
value = static_cast<std::underlying_t<E>>(eval) | (bits << EnumBits);
}
E get_enum() { return static_cast<E>(value & mask) }
int get_extra_bits() { return value >> EnumBits; }
}; The function that cheats and doesn't take a pure enum, but an enum with the extra bit, could look like: void UniformBuffer::writeUniformHandle(EnumWithBits<UniformType::Enum, 3> _type, uint16_t _loc, UniformHandle _handle, uint16_t _num) or potentially with an extra |
🤮 |
Change your PR to use
And I'll accept it. |
0a9e3ee
to
d3f84f7
Compare
Done. I have an alternative PR which tries to preserve the use of the actual enum by separating out those extra type bits, in #3402. Pick whichever you like best. |
Caught with UBSan. It apparently is UB if you start passing Enum values that do not exist in the enumerated enum values.