diff options
| author | JF Bastien <jfbastien@apple.com> | 2018-09-21 14:31:25 +0000 | 
|---|---|---|
| committer | JF Bastien <jfbastien@apple.com> | 2018-09-21 14:31:25 +0000 | 
| commit | 19262fc5966ab569f21f3d440f8b001bca666f17 (patch) | |
| tree | be359d81e70325e9e600c2394f24e9ab38181eba /llvm | |
| parent | 2adecff1aad61968c78b4ebeb0a5c2d016ea255f (diff) | |
| download | bcm5719-llvm-19262fc5966ab569f21f3d440f8b001bca666f17.tar.gz bcm5719-llvm-19262fc5966ab569f21f3d440f8b001bca666f17.zip  | |
[ADT] restrict bit_cast to trivially-constructible To
Summary: As discussed in r341853 by blaikie, the reinterpret_cast was technically an aliasing violation. Restrict our bit_cast implementation to To which are trivially-constructible (and note the existing restriction to constexpr). Once we move to C++17 we can use a version of bit_cast without these restrictions, or if we care we can SFINAE a different implementation when To isn't trivially-constructible.
Originally landed in r342710 and reverted in r342711 because is_trivially_copyable is only in GCC 5.1 and later.
Reviewers: dblaikie, rsmith
Subscribers: dexonsmith, kristina, llvm-commits
Differential Revision: https://reviews.llvm.org/D52332
llvm-svn: 342739
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/ADT/bit.h | 25 | 
1 files changed, 14 insertions, 11 deletions
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h index 0e383212712..a4aba7b6a9e 100644 --- a/llvm/include/llvm/ADT/bit.h +++ b/llvm/include/llvm/ADT/bit.h @@ -20,8 +20,19 @@  namespace llvm { +// This implementation of bit_cast is different from the C++17 one in two ways: +//  - It isn't constexpr because that requires compiler support. +//  - It requires trivially-constructible To, to avoid UB in the implementation.  template <typename To, typename From            , typename = typename std::enable_if<sizeof(To) == sizeof(From)>::type +#if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \ +    (defined(__GNUC__) && __GNUC__ >= 5) +          , typename = typename std::is_trivially_constructible<To>::type +#elif __has_feature(is_trivially_constructible) +          , typename = typename std::enable_if<__is_trivially_constructible(To)>::type +#else +  // See comment below. +#endif  #if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \      (defined(__GNUC__) && __GNUC__ >= 5)            , typename = typename std::enable_if<std::is_trivially_copyable<To>::value>::type @@ -38,17 +49,9 @@ template <typename To, typename From  #endif  >  inline To bit_cast(const From &from) noexcept { -  alignas(To) unsigned char storage[sizeof(To)]; -  std::memcpy(&storage, &from, sizeof(To)); -#if defined(__GNUC__) -  // Before GCC 7.2, GCC thought that this violated strict aliasing. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif -  return reinterpret_cast<To &>(storage); -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif +  To to; +  std::memcpy(&to, &from, sizeof(To)); +  return to;  }  } // namespace llvm  | 

