llvm.org GIT mirror llvm / 5538526
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@342739 91177308-0d34-0410-b5e6-96231b3b80d8 JF Bastien 1 year, 10 months ago
1 changed file(s) with 14 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
1919
2020 namespace llvm {
2121
22 // This implementation of bit_cast is different from the C++17 one in two ways:
23 // - It isn't constexpr because that requires compiler support.
24 // - It requires trivially-constructible To, to avoid UB in the implementation.
2225 template
2326 , typename = typename std::enable_if::type
27 #if (__has_feature(is_trivially_constructible) && defined(_LIBCPP_VERSION)) || \
28 (defined(__GNUC__) && __GNUC__ >= 5)
29 , typename = typename std::is_trivially_constructible::type
30 #elif __has_feature(is_trivially_constructible)
31 , typename = typename std::enable_if<__is_trivially_constructible(To)>::type
32 #else
33 // See comment below.
34 #endif
2435 #if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \
2536 (defined(__GNUC__) && __GNUC__ >= 5)
2637 , typename = typename std::enable_if::value>::type
3748 #endif
3849 >
3950 inline To bit_cast(const From &from) noexcept {
40 alignas(To) unsigned char storage[sizeof(To)];
41 std::memcpy(&storage, &from, sizeof(To));
42 #if defined(__GNUC__)
43 // Before GCC 7.2, GCC thought that this violated strict aliasing.
44 #pragma GCC diagnostic push
45 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
46 #endif
47 return reinterpret_cast(storage);
48 #if defined(__GNUC__)
49 #pragma GCC diagnostic pop
50 #endif
51 To to;
52 std::memcpy(&to, &from, sizeof(To));
53 return to;
5154 }
5255
5356 } // namespace llvm