Bug 1465981 - Use memcpy instead of union-arm-punning (which has implementation-defined, desired behavior with gcc and presumably clang, and is not known to have problems on MSVC, but potentially could with other compilers) in BitwiseCast. r=froydnj
authorJeff Walden <jwalden@mit.edu>
Wed, 06 Jun 2018 16:03:47 -0700
changeset 478640 9b5279a09e13b33f1e4e29e40e5aa968ef0f8fa6
parent 478639 08cdcfa7b3f03b4c5911069f0c5922a496de7203
child 478641 b1521154cfec6b35f8266af53efb24ebac260173
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1465981
milestone62.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1465981 - Use memcpy instead of union-arm-punning (which has implementation-defined, desired behavior with gcc and presumably clang, and is not known to have problems on MSVC, but potentially could with other compilers) in BitwiseCast. r=froydnj
mfbt/Casting.h
--- a/mfbt/Casting.h
+++ b/mfbt/Casting.h
@@ -7,17 +7,19 @@
 /* Cast operations to supplement the built-in casting operations. */
 
 #ifndef mozilla_Casting_h
 #define mozilla_Casting_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/TypeTraits.h"
 
+#include <cstring>
 #include <limits.h>
+#include <type_traits>
 
 namespace mozilla {
 
 /**
  * Sets the outparam value of type |To| with the same underlying bit pattern of
  * |aFrom|.
  *
  * |To| and |From| must be types of the same size; be careful of cross-platform
@@ -38,23 +40,29 @@ namespace mozilla {
  * you should use the direct return version.
  */
 template<typename To, typename From>
 inline void
 BitwiseCast(const From aFrom, To* aResult)
 {
   static_assert(sizeof(From) == sizeof(To),
                 "To and From must have the same size");
-  union
-  {
-    From mFrom;
-    To mTo;
-  } u;
-  u.mFrom = aFrom;
-  *aResult = u.mTo;
+
+  // We could maybe downgrade these to std::is_trivially_copyable, but the
+  // various STLs we use don't all provide it.
+  static_assert(std::is_trivial<From>::value,
+                "shouldn't bitwise-copy a type having non-trivial "
+                "initialization");
+  static_assert(std::is_trivial<To>::value,
+                "shouldn't bitwise-copy a type having non-trivial "
+                "initialization");
+
+  std::memcpy(static_cast<void*>(aResult),
+              static_cast<const void*>(&aFrom),
+              sizeof(From));
 }
 
 template<typename To, typename From>
 inline To
 BitwiseCast(const From aFrom)
 {
   To temp;
   BitwiseCast<To, From>(aFrom, &temp);