зеркало из https://github.com/microsoft/STL.git
<functional>: std::function doesn't handle over-aligned types (#698)
Fixes #690.
This commit is contained in:
Родитель
72c724007c
Коммит
97f9a2ce25
|
@ -795,7 +795,8 @@ private:
|
|||
constexpr size_t _Space_size = (_Small_object_num_ptrs - 1) * sizeof(void*);
|
||||
|
||||
template <class _Impl> // determine whether _Impl must be dynamically allocated
|
||||
_INLINE_VAR constexpr bool _Is_large = (_Space_size < sizeof(_Impl)) || !_Impl::_Nothrow_move::value;
|
||||
_INLINE_VAR constexpr bool _Is_large = sizeof(_Impl) > _Space_size || alignof(_Impl) > alignof(max_align_t)
|
||||
|| !_Impl::_Nothrow_move::value;
|
||||
|
||||
#if _HAS_FUNCTION_ALLOCATOR_SUPPORT
|
||||
// CLASS TEMPLATE _Func_impl
|
||||
|
|
|
@ -157,6 +157,7 @@ tests\Dev11_1158803_regex_thread_safety
|
|||
tests\Dev11_1180290_filesystem_error_code
|
||||
tests\GH_000457_system_error_message
|
||||
tests\GH_000545_include_compare
|
||||
tests\GH_000690_overaligned_function
|
||||
tests\P0024R2_parallel_algorithms_adjacent_difference
|
||||
tests\P0024R2_parallel_algorithms_adjacent_find
|
||||
tests\P0024R2_parallel_algorithms_all_of
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright (c) Microsoft Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
RUNALL_INCLUDE ..\usual_matrix.lst
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#pragma warning(disable : 4324) // structure was padded due to alignment specifier
|
||||
|
||||
// SFO (Small Functor Optimization) should not happen
|
||||
struct alignas(2 * alignof(std::max_align_t)) overaligned_t {
|
||||
char non_empty;
|
||||
|
||||
void operator()(const void* const storage, const std::size_t storage_size) const {
|
||||
const auto storage_ptr_value = reinterpret_cast<std::uintptr_t>(storage);
|
||||
const auto this_ptr_value = reinterpret_cast<std::uintptr_t>(this);
|
||||
|
||||
// Platform-specific behavior not covered by Standard C++, but fine for this test
|
||||
assert(this_ptr_value < storage_ptr_value || this_ptr_value >= storage_ptr_value + storage_size);
|
||||
|
||||
// Before C++17, alignas isn't helpful for aligning allocations via "new"
|
||||
#ifdef __cpp_aligned_new
|
||||
assert(this_ptr_value % alignof(overaligned_t) == 0);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// SFO should happen
|
||||
struct not_overaligned_t {
|
||||
char data[sizeof(overaligned_t)];
|
||||
|
||||
void operator()(const void* const storage, const std::size_t storage_size) const {
|
||||
const auto storage_ptr_value = reinterpret_cast<std::uintptr_t>(storage);
|
||||
const auto this_ptr_value = reinterpret_cast<std::uintptr_t>(this);
|
||||
|
||||
// Platform-specific behavior not covered by Standard C++, but fine for this test
|
||||
assert(this_ptr_value >= storage_ptr_value && this_ptr_value < storage_ptr_value + storage_size);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(alignof(overaligned_t) > alignof(std::max_align_t), "overaligned_t is not overaligned");
|
||||
|
||||
using function_t = std::function<void(const void* storage, std::size_t storage_size)>;
|
||||
|
||||
struct functions_t {
|
||||
function_t first{overaligned_t{}};
|
||||
char smallest_pad;
|
||||
function_t second{overaligned_t{}};
|
||||
function_t third{overaligned_t{}};
|
||||
};
|
||||
|
||||
int main() {
|
||||
functions_t functions;
|
||||
functions.first(&functions.first, sizeof(functions.first));
|
||||
functions.second(&functions.second, sizeof(functions.second));
|
||||
functions.third(&functions.third, sizeof(functions.third));
|
||||
|
||||
function_t sfo{not_overaligned_t{}};
|
||||
sfo(&sfo, sizeof(sfo));
|
||||
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче