Merge pull request #1712 from FearlessTobi/port-4426
Port citra-emu/citra#4426: "Common/Bitfield: store value as unsigned type"
This commit is contained in:
		| @@ -117,21 +117,21 @@ private: | |||||||
|     // We don't delete it because we want BitField to be trivially copyable. |     // We don't delete it because we want BitField to be trivially copyable. | ||||||
|     constexpr BitField& operator=(const BitField&) = default; |     constexpr BitField& operator=(const BitField&) = default; | ||||||
|  |  | ||||||
|     // StorageType is T for non-enum types and the underlying type of T if |     // UnderlyingType is T for non-enum types and the underlying type of T if | ||||||
|     // T is an enumeration. Note that T is wrapped within an enable_if in the |     // T is an enumeration. Note that T is wrapped within an enable_if in the | ||||||
|     // former case to workaround compile errors which arise when using |     // former case to workaround compile errors which arise when using | ||||||
|     // std::underlying_type<T>::type directly. |     // std::underlying_type<T>::type directly. | ||||||
|     using StorageType = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>, |     using UnderlyingType = typename std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>, | ||||||
|                                                     std::enable_if<true, T>>::type; |                                                        std::enable_if<true, T>>::type; | ||||||
|  |  | ||||||
|     // Unsigned version of StorageType |     // We store the value as the unsigned type to avoid undefined behaviour on value shifting | ||||||
|     using StorageTypeU = std::make_unsigned_t<StorageType>; |     using StorageType = std::make_unsigned_t<UnderlyingType>; | ||||||
|  |  | ||||||
| public: | public: | ||||||
|     /// Constants to allow limited introspection of fields if needed |     /// Constants to allow limited introspection of fields if needed | ||||||
|     static constexpr std::size_t position = Position; |     static constexpr std::size_t position = Position; | ||||||
|     static constexpr std::size_t bits = Bits; |     static constexpr std::size_t bits = Bits; | ||||||
|     static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position; |     static constexpr StorageType mask = (((StorageType)~0) >> (8 * sizeof(T) - bits)) << position; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Formats a value by masking and shifting it according to the field parameters. A value |      * Formats a value by masking and shifting it according to the field parameters. A value | ||||||
| @@ -148,11 +148,12 @@ public: | |||||||
|      * union in a constexpr context. |      * union in a constexpr context. | ||||||
|      */ |      */ | ||||||
|     static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { |     static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { | ||||||
|         if (std::numeric_limits<T>::is_signed) { |         if constexpr (std::numeric_limits<UnderlyingType>::is_signed) { | ||||||
|             std::size_t shift = 8 * sizeof(T) - bits; |             std::size_t shift = 8 * sizeof(T) - bits; | ||||||
|             return (T)((storage << (shift - position)) >> shift); |             return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >> | ||||||
|  |                                   shift); | ||||||
|         } else { |         } else { | ||||||
|             return (T)((storage & mask) >> position); |             return static_cast<T>((storage & mask) >> position); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user