BLI code for enums that are meant to be used as "bit flags" defined
an ENUM_OPERATORS macro in BLI_utildefines.h. This cleans up things
related to said macro:
- Move it out into a separate BLI_enum_flags.hh header, instead of
"random bag of things" that is the current place,
- Update it to no longer need manual indication of highest individual
bit value. This originally was added in a31a87f89 (2020 Oct), in
order to silence some UBSan warnings that were coming
from GPU related structures (looking at current GPU code, I don't
think this is happening anymore). However, that caused actual
user-visible bugs due to incorrectly specified max. enum bit value,
and today 14% of all usages have incorrect highest individual
bit value spelled out.
- I have reviewed all usages of operator ~ and none of them are
used for directly producing a DNA-serialized value; all the
usages are for masking out other bits for which the new ~
behavior that just flips all bits is fine.
- Make the macro define flag_is_set() function to ease check of bits
that are set in C++ enum class cases; update existing cases to use
that instead of three other ways that were used.
Pull Request: https://projects.blender.org/blender/blender/pulls/148230
55 lines
1.7 KiB
C++
55 lines
1.7 KiB
C++
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup bli
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
# include <cstdint>
|
|
|
|
/* Use for enum classes that represent bit flags.
|
|
* Defines logical operators to combine and mask the flag values.
|
|
*
|
|
* Note that negation/inversion operator (~) flips all the bits, so the result can contain
|
|
* set bits that are not part of the enum values. However that is fine in typical
|
|
* inversion operator usage, which is often for masking out bits (`a & ~b`). */
|
|
# define ENUM_OPERATORS(_enum_type) \
|
|
[[nodiscard]] inline constexpr _enum_type operator|(_enum_type a, _enum_type b) \
|
|
{ \
|
|
return (_enum_type)(uint64_t(a) | uint64_t(b)); \
|
|
} \
|
|
[[nodiscard]] inline constexpr _enum_type operator&(_enum_type a, _enum_type b) \
|
|
{ \
|
|
return (_enum_type)(uint64_t(a) & uint64_t(b)); \
|
|
} \
|
|
[[nodiscard]] inline constexpr _enum_type operator~(_enum_type a) \
|
|
{ \
|
|
return (_enum_type)(~uint64_t(a)); \
|
|
} \
|
|
inline _enum_type &operator|=(_enum_type &a, _enum_type b) \
|
|
{ \
|
|
return a = (_enum_type)(uint64_t(a) | uint64_t(b)); \
|
|
} \
|
|
inline _enum_type &operator&=(_enum_type &a, _enum_type b) \
|
|
{ \
|
|
return a = (_enum_type)(uint64_t(a) & uint64_t(b)); \
|
|
} \
|
|
inline _enum_type &operator^=(_enum_type &a, _enum_type b) \
|
|
{ \
|
|
return a = (_enum_type)(uint64_t(a) ^ uint64_t(b)); \
|
|
} \
|
|
[[nodiscard]] inline constexpr bool flag_is_set(_enum_type flags, _enum_type flag_to_test) \
|
|
{ \
|
|
return (uint64_t(flags) & uint64_t(flag_to_test)) != 0; \
|
|
}
|
|
|
|
#else
|
|
|
|
# define ENUM_OPERATORS(_enum_type)
|
|
|
|
#endif
|