Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<functional>: std::function doesn't handle over-aligned types #698

Merged
merged 28 commits into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3453936
#690 , starting with tests to make sure they fail
AlexGuteniev Apr 9, 2020
5af04f7
env.lst
AlexGuteniev Apr 9, 2020
699e6fa
copyrignt, license
AlexGuteniev Apr 9, 2020
93e0665
the fix for #690
AlexGuteniev Apr 9, 2020
7fda7bf
unterse `static_assert`
AlexGuteniev Apr 9, 2020
ec38c3b
improve test condition
AlexGuteniev Apr 9, 2020
6eba7de
guard over-aligned feature
AlexGuteniev Apr 9, 2020
a9455b7
Don't pad then if pre-__cpp_aligned_new
AlexGuteniev Apr 9, 2020
2b9cae1
skip for pre-17 by test matrix, not by ifdef
AlexGuteniev Apr 9, 2020
7aa7d1f
Update tests/std/tests/VSO_1062649_overaligned_function/test.cpp
AlexGuteniev Apr 9, 2020
55371d1
Update tests/std/tests/VSO_1062649_overaligned_function/test.cpp
AlexGuteniev Apr 9, 2020
74f4592
Update tests/std/tests/VSO_1062649_overaligned_function/test.cpp
AlexGuteniev Apr 9, 2020
792994c
#error correctly, simplify checks
AlexGuteniev Apr 9, 2020
c25d0a0
getting back lost const
AlexGuteniev Apr 9, 2020
01e9c0d
Update tests/std/tests/VSO_1062649_overaligned_function/test.cpp
AlexGuteniev Apr 9, 2020
6b6ee27
unconditionally no SFO for over-aligned
AlexGuteniev Apr 9, 2020
d811dbc
integer math instead of (nonstandard) pointer math
AlexGuteniev Apr 9, 2020
d3be4b3
rename the test
AlexGuteniev Apr 9, 2020
cd84b7f
these braces are needed for clang-format
AlexGuteniev Apr 9, 2020
62e2730
runtime check for SFO to happen
AlexGuteniev Apr 9, 2020
c0ed4c6
Update stl/inc/functional
AlexGuteniev Apr 10, 2020
0ae9d8f
Update tests/std/tests/GH_000690_overaligned_function/test.cpp
AlexGuteniev Apr 10, 2020
819a202
Pre-C++17 version of test
AlexGuteniev Apr 10, 2020
76bfccb
Removing macros, now I have ICE
AlexGuteniev Apr 10, 2020
01d8f43
Revert "Removing macros, now I have ICE"
AlexGuteniev Apr 10, 2020
2f46e69
correct condition
AlexGuteniev Apr 10, 2020
ef10a8b
Merge branch 'master' into function_alinged
StephanTLavavej Apr 21, 2020
ec176f2
Small comment changes.
StephanTLavavej Apr 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion stl/inc/functional
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/GH_000690_overaligned_function/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
63 changes: 63 additions & 0 deletions tests/std/tests/GH_000690_overaligned_function/test.cpp
Original file line number Diff line number Diff line change
@@ -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;
}