tint: make utils::Bitcast not trigger gcc warning

When useing Bitcast to or from a class type, gcc warns even if the type
is trivially copyable. Fixed this by static_asserting that both types
are trivially copyable, and casting the pointers to std::byte*.

Change-Id: Ibb420f2dcdd35cfb187d74983fa8ab9b50d10c85
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/115180
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/utils/bitcast.h b/src/tint/utils/bitcast.h
index 4450336..4f72bb8 100644
--- a/src/tint/utils/bitcast.h
+++ b/src/tint/utils/bitcast.h
@@ -15,7 +15,9 @@
 #ifndef SRC_TINT_UTILS_BITCAST_H_
 #define SRC_TINT_UTILS_BITCAST_H_
 
+#include <cstddef>
 #include <cstring>
+#include <type_traits>
 
 namespace tint::utils {
 
@@ -29,8 +31,20 @@
 template <typename TO, typename FROM>
 inline TO Bitcast(FROM&& from) {
     static_assert(sizeof(FROM) == sizeof(TO));
+    // gcc warns in cases where either TO or FROM are classes, even if they are trivially
+    // copyable, with for example:
+    //
+    // error: ‘void* memcpy(void*, const void*, size_t)’ copying an object of
+    // non-trivial type ‘struct tint::Number<unsigned int>’ from an array of ‘float’
+    // [-Werror=class-memaccess]
+    //
+    // We avoid this by asserting that both types are indeed trivially copyable, and casting both
+    // args to std::byte*.
+    static_assert(std::is_trivially_copyable_v<std::decay_t<FROM>>);
+    static_assert(std::is_trivially_copyable_v<std::decay_t<TO>>);
     TO to;
-    memcpy(&to, &from, sizeof(TO));
+    memcpy(reinterpret_cast<std::byte*>(&to), reinterpret_cast<const std::byte*>(&from),
+           sizeof(TO));
     return to;
 }