* add bit_cast and tests
Mirror MSVC-PR-228495
This commit is contained in:
Charlie Barto 2020-03-05 13:57:04 -08:00 коммит произвёл GitHub
Родитель b8917400a9
Коммит 8a6c278743
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 300 добавлений и 0 удалений

Просмотреть файл

@ -25,6 +25,16 @@ _STL_DISABLE_CLANG_WARNINGS
_STD_BEGIN _STD_BEGIN
enum class endian { little = 0, big = 1, native = little }; enum class endian { little = 0, big = 1, native = little };
#ifdef __cpp_lib_bit_cast // TRANSITION, VSO-1041044
template <class _To, class _From,
enable_if_t<conjunction_v<bool_constant<sizeof(_To) == sizeof(_From)>, is_trivially_copyable<_To>,
is_trivially_copyable<_From>>,
int> = 0>
_NODISCARD constexpr _To bit_cast(const _From& _Val) noexcept {
return __builtin_bit_cast(_To, _Val);
}
#endif // TRANSITION, VSO-1041044
#ifdef __cpp_lib_bitops // TRANSITION, VSO-1020212 #ifdef __cpp_lib_bitops // TRANSITION, VSO-1020212
template <class _Ty> template <class _Ty>
inline constexpr bool _Is_standard_unsigned_integer = inline constexpr bool _Is_standard_unsigned_integer =

Просмотреть файл

@ -140,6 +140,7 @@
// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view // P0457R2 starts_with()/ends_with() For basic_string/basic_string_view
// P0458R2 contains() For Ordered And Unordered Associative Containers // P0458R2 contains() For Ordered And Unordered Associative Containers
// P0463R1 endian // P0463R1 endian
// P0476R2 <bit> bit_cast
// P0482R6 Library Support For char8_t // P0482R6 Library Support For char8_t
// (mbrtoc8 and c8rtomb not yet implemented) // (mbrtoc8 and c8rtomb not yet implemented)
// P0487R1 Fixing operator>>(basic_istream&, CharT*) // P0487R1 Fixing operator>>(basic_istream&, CharT*)
@ -1078,6 +1079,10 @@
#define __cpp_lib_atomic_float 201711L #define __cpp_lib_atomic_float 201711L
#define __cpp_lib_bind_front 201907L #define __cpp_lib_bind_front 201907L
#ifndef __EDG__ // TRANSITION, VSO-1041044
#define __cpp_lib_bit_cast 201806L
#endif // __EDG__
#if defined(__clang__) || defined(__EDG__) #if defined(__clang__) || defined(__EDG__)
#define __cpp_lib_bitops 201907L #define __cpp_lib_bitops 201907L
#else // ^^^ Clang and EDG / MSVC vvv #else // ^^^ Clang and EDG / MSVC vvv

Просмотреть файл

@ -210,6 +210,7 @@ tests\P0357R3_supporting_incomplete_types_in_reference_wrapper
tests\P0414R2_shared_ptr_for_arrays tests\P0414R2_shared_ptr_for_arrays
tests\P0426R1_constexpr_char_traits tests\P0426R1_constexpr_char_traits
tests\P0433R2_deduction_guides tests\P0433R2_deduction_guides
tests\P0476R2_bit_cast
tests\P0487R1_fixing_operator_shl_basic_istream_char_pointer tests\P0487R1_fixing_operator_shl_basic_istream_char_pointer
tests\P0513R0_poisoning_the_hash tests\P0513R0_poisoning_the_hash
tests\P0553R4_bit_rotating_and_counting_functions tests\P0553R4_bit_rotating_and_counting_functions

Просмотреть файл

@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
RUNALL_INCLUDE ..\usual_latest_matrix.lst

Просмотреть файл

@ -0,0 +1,266 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifdef __EDG__ // TRANSITION, VSO-1041044
int main() {}
#else // __EDG__ ^^^ / vvv !__EDG__
#include <assert.h>
#include <bit>
#include <cmath>
#include <limits>
#include <stddef.h>
#include <string.h>
#include <type_traits>
#include <utility>
// structure sizing depends on a packing of 8, which is the default
union test_union_1 {
char a;
int b;
};
union test_union_2 {
char a;
float b;
};
struct middle_class_1 {
double d;
virtual void a_member_function_1() {}
};
struct middle_class_2 {
int a;
virtual void a_member_function_2() {}
};
struct derived_class : middle_class_1, middle_class_2 {
virtual void a_member_function_2() override {}
};
struct test_struct_1 {
char a;
// char[3]
int b;
short c;
// char[6]
double d;
void a_member_function() {}
};
struct test_struct_2 {
short a;
// char[2]
float b;
float c;
int d;
unsigned int e;
char f;
// char[1]
short g;
void a_member_function() {}
};
struct test_struct_3_member_fn_pointer {
char a;
// char[3]
int b;
short c;
char d[2];
void (test_struct_1::*fn)();
};
struct test_struct_4_large_member_fn_pointer {
char a;
// char[3]
int b;
double c;
double d;
void (derived_class::*fn)(); // "large" member fn pointers are aligned to 8 on both x64 and x86
};
struct test_struct_5_struct {
char a;
// char[3]
int b;
double c;
double d;
void* e;
size_t f;
};
struct test_struct_6 {
char a;
// char[3]
int b;
int c;
// char[4] on x64
void* v;
};
struct test_struct_7_member_fn_pointer {
char a;
// char[3]
int b;
int c;
void (test_struct_1::*fn)();
};
struct test_struct_1_not_trivially_copyable {
char a;
// char[3]
int b;
short c;
// char[2]
double d;
test_struct_1_not_trivially_copyable& operator=(const test_struct_1_not_trivially_copyable&) {
return *this;
}
};
#pragma pack(push, 1)
struct test_struct_1_packed {
char a;
int b;
short c;
double d;
};
struct test_struct_2_packed {
short a;
float b;
float c;
int d;
unsigned int e;
char f;
short g;
};
#pragma pack(pop)
static_assert(sizeof(test_struct_1) == sizeof(test_struct_2));
template <typename To, typename From, typename = void>
constexpr bool bit_cast_invocable = false;
template <typename To, typename From>
constexpr bool bit_cast_invocable<To, From, std::void_t<decltype(std::bit_cast<To>(std::declval<From>()))>> = true;
template <int zero = 0, int = ((void) std::bit_cast<test_union_1>(test_union_2{}), zero)>
constexpr bool bit_cast_is_constexpr_union(int) {
return true;
}
constexpr bool bit_cast_is_constexpr_union(long) {
return false;
}
template <int zero = 0, int = ((void) std::bit_cast<float*>(nullptr), zero)>
constexpr bool bit_cast_is_constexpr_pointer(int) {
return true;
}
constexpr bool bit_cast_is_constexpr_pointer(long) {
return false;
}
template <int zero = 0,
int = ((void) std::bit_cast<void (test_struct_1::*)()>(&test_struct_2::a_member_function), zero)>
constexpr bool bit_cast_is_constexpr_member_fn_pointer(int) {
return true;
}
constexpr bool bit_cast_is_constexpr_member_fn_pointer(long) {
return false;
}
template <int zero = 0, int = ((void) std::bit_cast<test_struct_6>(test_struct_3_member_fn_pointer{}), zero)>
constexpr bool bit_cast_is_constexpr_pmf_datamember(int) {
return true;
}
constexpr bool bit_cast_is_constexpr_pmf_datamember(long) {
return false;
}
template <int zero = 0,
int = ((void) std::bit_cast<test_struct_5_struct>(test_struct_4_large_member_fn_pointer{}), zero)>
constexpr bool bit_cast_is_constexpr_large_member_fn_pointer(int) {
return true;
}
constexpr bool bit_cast_is_constexpr_large_member_fn_pointer(long) {
return false;
}
template <typename To, typename From>
void zero_initialized_round_trip() {
From before{};
To middle = std::bit_cast<To>(before);
assert(memcmp(&before, &middle, sizeof(From)) == 0);
From after = std::bit_cast<From>(middle);
assert(memcmp(&before, &after, sizeof(From)) == 0);
}
constexpr bool test_float() {
unsigned int as_int = std::bit_cast<unsigned int>(0x0.000002p-126f);
assert(as_int == 1);
assert(std::bit_cast<float>(as_int) == 0x0.000002p-126f);
as_int = std::bit_cast<unsigned int>(0x1.1p1f);
assert(as_int == 0x40080000);
assert(std::bit_cast<float>(as_int) == 0x1.1p1f);
as_int = std::bit_cast<unsigned int>(0x0.0p0f);
assert(as_int == 0);
assert(std::bit_cast<float>(as_int) == 0x0.0p0f);
if (!std::is_constant_evaluated()) {
assert(std::signbit(std::bit_cast<float>(as_int)) == false);
}
as_int = std::bit_cast<unsigned int>(-0x0.0p0f);
assert(as_int == 0x80000000);
assert(std::bit_cast<float>(as_int) == -0x0.0p0f);
if (!std::is_constant_evaluated()) {
assert(std::signbit(std::bit_cast<float>(as_int)) == true);
}
// signaling nan
as_int = 0x7fc00001;
float snan = std::bit_cast<float>(as_int);
assert(as_int == std::bit_cast<unsigned int>(snan));
as_int = std::bit_cast<unsigned int>(std::numeric_limits<float>::infinity());
assert(as_int == 0x7f800000);
assert(std::bit_cast<float>(as_int) == std::numeric_limits<float>::infinity());
return true;
}
int main() {
static_assert(!bit_cast_invocable<test_struct_2_packed, test_struct_1_packed>);
static_assert(!bit_cast_invocable<test_struct_1_not_trivially_copyable, test_struct_1>);
static_assert(!bit_cast_invocable<test_struct_1, test_struct_1_not_trivially_copyable>);
static_assert(!bit_cast_invocable<test_struct_1_not_trivially_copyable, test_struct_1_not_trivially_copyable>);
static_assert(bit_cast_invocable<test_union_1, test_union_2>);
static_assert(bit_cast_invocable<ptrdiff_t, void (test_struct_1::*)()>);
static_assert(bit_cast_invocable<ptrdiff_t, void (*)()>);
static_assert(bit_cast_invocable<test_struct_1, test_struct_2>);
static_assert(bit_cast_invocable<test_struct_4_large_member_fn_pointer, test_struct_5_struct>);
// tests for conditions on constexprness
static_assert(!bit_cast_is_constexpr_union(0));
static_assert(!bit_cast_is_constexpr_pointer(0));
static_assert(!bit_cast_is_constexpr_member_fn_pointer(0));
static_assert(!bit_cast_is_constexpr_pmf_datamember(0));
static_assert(!bit_cast_is_constexpr_large_member_fn_pointer(0));
zero_initialized_round_trip<test_struct_1, test_struct_2>();
zero_initialized_round_trip<test_struct_3_member_fn_pointer, test_struct_3_member_fn_pointer>();
zero_initialized_round_trip<test_struct_3_member_fn_pointer, test_struct_7_member_fn_pointer>();
zero_initialized_round_trip<test_struct_4_large_member_fn_pointer, test_struct_5_struct>();
zero_initialized_round_trip<test_struct_6, test_struct_3_member_fn_pointer>();
zero_initialized_round_trip<float, int>();
zero_initialized_round_trip<double, long long>();
zero_initialized_round_trip<unsigned int, float>();
assert(test_float());
static_assert(test_float());
}
#endif // __EDG__

Просмотреть файл

@ -1513,6 +1513,20 @@ STATIC_ASSERT(__cpp_lib_bind_front == 201907L);
#endif #endif
#endif #endif
#if CXX20_MODE && !defined(__EDG__) // TRANSITION, VSO-1041044
#ifndef __cpp_lib_bit_cast
#error BOOM
#elif __cpp_lib_bit_cast != 201806L
#error BOOM
#else
STATIC_ASSERT(__cpp_lib_bit_cast == 201806L);
#endif
#else
#ifdef __cpp_lib_bit_cast
#error BOOM
#endif
#endif
#if CXX20_MODE && (defined(__clang__) || defined(__EDG__)) // TRANSITION, VSO-1020212 #if CXX20_MODE && (defined(__clang__) || defined(__EDG__)) // TRANSITION, VSO-1020212
#ifndef __cpp_lib_bitops #ifndef __cpp_lib_bitops
#error BOOM #error BOOM