From: JF Bastien Date: Fri, 21 Sep 2018 05:18:49 +0000 (+0000) Subject: [ADT] restrict bit_cast to trivially-constructible To X-Git-Tag: llvmorg-8.0.0-rc1~8271 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=86f732a6a8809799a5e1bbae5911c7c48477cadc;p=platform%2Fupstream%2Fllvm.git [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. Reviewers: dblaikie, rsmith Subscribers: dexonsmith, kristina, llvm-commits Differential Revision: https://reviews.llvm.org/D52332 llvm-svn: 342710 --- diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h index 0e38321..0a3c2ed 100644 --- a/llvm/include/llvm/ADT/bit.h +++ b/llvm/include/llvm/ADT/bit.h @@ -20,8 +20,12 @@ 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 ::type + , typename = typename std::is_trivially_constructible::type #if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ (defined(__GNUC__) && __GNUC__ >= 5) , typename = typename std::enable_if::value>::type @@ -38,17 +42,9 @@ template 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(storage); -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif + To to; + std::memcpy(&to, &from, sizeof(To)); + return to; } } // namespace llvm