[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / libc / src / __support / CPP / bit.h
blobf6f3131c1ccfd81b3553cd3208b9c6bc21891ae0
1 //===-- Freestanding version of bit_cast -----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
10 #define LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H
12 #include "src/__support/CPP/type_traits.h"
13 #include "src/__support/macros/attributes.h"
14 #include "src/__support/macros/config.h" // LIBC_HAS_BUILTIN
15 #include "src/__support/macros/sanitizer.h"
17 namespace LIBC_NAMESPACE::cpp {
19 #if LIBC_HAS_BUILTIN(__builtin_bit_cast)
20 #define LLVM_LIBC_HAS_BUILTIN_BIT_CAST
21 #endif
23 #if LIBC_HAS_BUILTIN(__builtin_memcpy_inline)
24 #define LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE
25 #endif
27 // This function guarantees the bitcast to be optimized away by the compiler for
28 // GCC >= 8 and Clang >= 6.
29 template <class To, class From>
30 LIBC_INLINE constexpr To bit_cast(const From &from) {
31 static_assert(sizeof(To) == sizeof(From), "To and From must be of same size");
32 static_assert(cpp::is_trivially_copyable<To>::value &&
33 cpp::is_trivially_copyable<From>::value,
34 "Cannot bit-cast instances of non-trivially copyable classes.");
35 MSAN_UNPOISON(&from, sizeof(From));
36 #if defined(LLVM_LIBC_HAS_BUILTIN_BIT_CAST)
37 return __builtin_bit_cast(To, from);
38 #else
39 static_assert(cpp::is_trivially_constructible<To>::value,
40 "This implementation additionally requires destination type to "
41 "be trivially constructible");
42 To to;
43 char *dst = reinterpret_cast<char *>(&to);
44 const char *src = reinterpret_cast<const char *>(&from);
45 #if defined(LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE)
46 __builtin_memcpy_inline(dst, src, sizeof(To));
47 #else
48 for (unsigned i = 0; i < sizeof(To); ++i)
49 dst[i] = src[i];
50 #endif // defined(LLVM_LIBC_HAS_BUILTIN_MEMCPY_INLINE)
51 return to;
52 #endif // defined(LLVM_LIBC_HAS_BUILTIN_BIT_CAST)
55 template <class To, class From>
56 LIBC_INLINE constexpr To bit_or_static_cast(const From &from) {
57 if constexpr (sizeof(To) == sizeof(From)) {
58 return bit_cast<To>(from);
59 } else {
60 return static_cast<To>(from);
64 } // namespace LIBC_NAMESPACE::cpp
66 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_BIT_H