Enforce trivially-copyable types on unaligned loads/stores/casts.

These correctness checks were inspired by Chromium's bit_cast:
https://chromium.googlesource.com/chromium/src/base/+/refs/heads/master/bit_cast.h

This also closes out a long-standing TODO in the code.

Change-Id: Iaf570fc564955ba90115a52bcaa743a170bdbdc4
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/305718
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
John Stiles 2020-07-24 10:05:43 -04:00 committed by Skia Commit-Bot
parent 58adb34cda
commit 7109434de0
2 changed files with 8 additions and 4 deletions

View File

@ -83,7 +83,8 @@ namespace SkHexadecimalDigits {
template <typename T, typename P>
static SK_ALWAYS_INLINE T sk_unaligned_load(const P* ptr) {
// TODO: static_assert desirable things about T here so as not to be totally abused.
static_assert(std::is_trivially_copyable<T>::value);
static_assert(std::is_trivially_copyable<P>::value);
T val;
memcpy(&val, ptr, sizeof(val));
return val;
@ -91,13 +92,14 @@ static SK_ALWAYS_INLINE T sk_unaligned_load(const P* ptr) {
template <typename T, typename P>
static SK_ALWAYS_INLINE void sk_unaligned_store(P* ptr, T val) {
// TODO: ditto
static_assert(std::is_trivially_copyable<T>::value);
static_assert(std::is_trivially_copyable<P>::value);
memcpy(ptr, &val, sizeof(val));
}
template <typename Dst, typename Src>
static SK_ALWAYS_INLINE Dst sk_bit_cast(const Src& src) {
static_assert(sizeof(Dst) == sizeof(Src), "");
static_assert(sizeof(Dst) == sizeof(Src));
return sk_unaligned_load<Dst>(&src);
}

View File

@ -22,7 +22,9 @@
template <typename Dst, typename Src>
SI Dst widen_cast(const Src& src) {
static_assert(sizeof(Dst) > sizeof(Src), "");
static_assert(sizeof(Dst) > sizeof(Src));
static_assert(std::is_trivially_copyable<Dst>::value);
static_assert(std::is_trivially_copyable<Src>::value);
Dst dst;
memcpy(&dst, &src, sizeof(Src));
return dst;