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 476134 9b5279a09e13b33f1e4e29e40e5aa968ef0f8fa6
parent 476133 08cdcfa7b3f03b4c5911069f0c5922a496de7203
child 476135 b1521154cfec6b35f8266af53efb24ebac260173
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [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);