Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c4e9872

Browse files
committedJun 30, 2023
[libc++] Fix std::copy and std::move for ranges with potentially overlapping tail padding
This fixes thr bug reported in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108846. Reviewed By: ldionne, #libc Spies: mstorsjo, libcxx-commits Differential Revision: https://reviews.llvm.org/D151953
1 parent e8e0f32 commit c4e9872

File tree

22 files changed

+448
-383
lines changed

22 files changed

+448
-383
lines changed
 

‎libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ set(files
707707
__type_traits/conjunction.h
708708
__type_traits/copy_cv.h
709709
__type_traits/copy_cvref.h
710+
__type_traits/datasizeof.h
710711
__type_traits/decay.h
711712
__type_traits/dependent_type.h
712713
__type_traits/disjunction.h

‎libcxx/include/__algorithm/copy_move_common.h

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <__config>
1616
#include <__iterator/iterator_traits.h>
1717
#include <__memory/pointer_traits.h>
18+
#include <__string/constexpr_c_functions.h>
1819
#include <__type_traits/enable_if.h>
1920
#include <__type_traits/is_always_bitcastable.h>
2021
#include <__type_traits/is_constant_evaluated.h>
@@ -61,7 +62,8 @@ template <class _In, class _Out>
6162
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
6263
__copy_trivial_impl(_In* __first, _In* __last, _Out* __result) {
6364
const size_t __n = static_cast<size_t>(__last - __first);
64-
::__builtin_memmove(__result, __first, __n * sizeof(_Out));
65+
66+
std::__constexpr_memmove(__result, __first, __element_count(__n));
6567

6668
return std::make_pair(__last, __result + __n);
6769
}
@@ -72,7 +74,7 @@ __copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) {
7274
const size_t __n = static_cast<size_t>(__last - __first);
7375
__result -= __n;
7476

75-
::__builtin_memmove(__result, __first, __n * sizeof(_Out));
77+
std::__constexpr_memmove(__result, __first, __element_count(__n));
7678

7779
return std::make_pair(__last, __result);
7880
}
@@ -119,16 +121,6 @@ __unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) {
119121
return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first));
120122
}
121123

122-
template <class _IterOps, class _InValue, class _OutIter, class = void>
123-
struct __can_copy_without_conversion : false_type {};
124-
125-
template <class _IterOps, class _InValue, class _OutIter>
126-
struct __can_copy_without_conversion<
127-
_IterOps,
128-
_InValue,
129-
_OutIter,
130-
__enable_if_t<is_same<_InValue, typename _IterOps::template __value_type<_OutIter> >::value> > : true_type {};
131-
132124
template <class _AlgPolicy,
133125
class _NaiveAlgorithm,
134126
class _OptimizedAlgorithm,
@@ -137,23 +129,6 @@ template <class _AlgPolicy,
137129
class _OutIter>
138130
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
139131
__dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) {
140-
#ifdef _LIBCPP_COMPILER_GCC
141-
// GCC doesn't support `__builtin_memmove` during constant evaluation.
142-
if (__libcpp_is_constant_evaluated()) {
143-
return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first));
144-
}
145-
#else
146-
// In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is
147-
// insufficient). Also, conversions are not supported.
148-
if (__libcpp_is_constant_evaluated()) {
149-
using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>;
150-
if (!is_trivially_copyable<_InValue>::value ||
151-
!__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) {
152-
return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first));
153-
}
154-
}
155-
#endif // _LIBCPP_COMPILER_GCC
156-
157132
using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>;
158133
return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first));
159134
}

‎libcxx/include/__string/char_traits.h

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -170,25 +170,6 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha
170170
{return int_type(EOF);}
171171
};
172172

173-
template <class _CharT>
174-
_LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
175-
_CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT
176-
{
177-
#ifdef _LIBCPP_COMPILER_GCC
178-
if (__libcpp_is_constant_evaluated()) {
179-
if (__n == 0)
180-
return __dest;
181-
_CharT* __allocation = new _CharT[__n];
182-
std::copy_n(__source, __n, __allocation);
183-
std::copy_n(static_cast<const _CharT*>(__allocation), __n, __dest);
184-
delete[] __allocation;
185-
return __dest;
186-
}
187-
#endif
188-
::__builtin_memmove(__dest, __source, __n * sizeof(_CharT));
189-
return __dest;
190-
}
191-
192173
// char_traits<char>
193174

194175
template <>
@@ -249,7 +230,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>
249230

250231
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
251232
char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
252-
return std::__char_traits_move(__s1, __s2, __n);
233+
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
253234
}
254235

255236
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -320,7 +301,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
320301

321302
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
322303
char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
323-
return std::__char_traits_move(__s1, __s2, __n);
304+
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
324305
}
325306

326307
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -384,7 +365,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
384365

385366
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
386367
char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
387-
return std::__char_traits_move(__s1, __s2, __n);
368+
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
388369
}
389370

390371
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -468,7 +449,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
468449

469450
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
470451
static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
471-
return std::__char_traits_move(__s1, __s2, __n);
452+
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
472453
}
473454

474455
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -562,7 +543,7 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
562543

563544
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
564545
static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
565-
return std::__char_traits_move(__s1, __s2, __n);
546+
return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
566547
}
567548

568549
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20

‎libcxx/include/__string/constexpr_c_functions.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@
1010
#define _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H
1111

1212
#include <__config>
13+
#include <__type_traits/datasizeof.h>
14+
#include <__type_traits/is_always_bitcastable.h>
1315
#include <__type_traits/is_constant_evaluated.h>
1416
#include <__type_traits/is_equality_comparable.h>
1517
#include <__type_traits/is_same.h>
18+
#include <__type_traits/is_trivially_copyable.h>
1619
#include <__type_traits/is_trivially_lexicographically_comparable.h>
1720
#include <__type_traits/remove_cv.h>
21+
#include <__utility/is_pointer_in_range.h>
1822
#include <cstddef>
1923

2024
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -129,6 +133,30 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp* __constexpr_memchr(_Tp*
129133
}
130134
}
131135

136+
template <class _Tp, class _Up, __enable_if_t<__is_always_bitcastable<_Up, _Tp>::value, int> = 0>
137+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp*
138+
__constexpr_memmove(_Tp* __dest, _Up* __src, __element_count __n) {
139+
size_t __count = static_cast<size_t>(__n);
140+
if (__libcpp_is_constant_evaluated()) {
141+
#ifdef _LIBCPP_COMPILER_CLANG_BASED
142+
if (is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up> >::value) {
143+
::__builtin_memmove(__dest, __src, __count * sizeof(_Tp));
144+
return __dest;
145+
}
146+
#endif
147+
if (std::__is_pointer_in_range(__src, __src + __count, __dest)) {
148+
for (; __count > 0; --__count)
149+
__dest[__count - 1] = __src[__count - 1];
150+
} else {
151+
for (size_t __i = 0; __i != __count; ++__i)
152+
__dest[__i] = __src[__i];
153+
}
154+
} else if (__count > 0) {
155+
::__builtin_memmove(__dest, __src, (__count - 1) * sizeof(_Tp) + __libcpp_datasizeof<_Tp>::value);
156+
}
157+
return __dest;
158+
}
159+
132160
_LIBCPP_END_NAMESPACE_STD
133161

134162
#endif // _LIBCPP___STRING_CONSTEXPR_C_FUNCTIONS_H
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===----------------------------------------------------------------------===//
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+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___TYPE_TRAITS_DATASIZEOF_H
10+
#define _LIBCPP___TYPE_TRAITS_DATASIZEOF_H
11+
12+
#include <__config>
13+
#include <__type_traits/is_class.h>
14+
#include <__type_traits/is_final.h>
15+
#include <cstddef>
16+
17+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18+
# pragma GCC system_header
19+
#endif
20+
21+
// This trait provides the size of a type excluding any tail padding.
22+
//
23+
// It is useful in contexts where performing an operation using the full size of the class (including padding) may
24+
// have unintended side effects, such as overwriting a derived class' member when writing the tail padding of a class
25+
// through a pointer-to-base.
26+
27+
_LIBCPP_BEGIN_NAMESPACE_STD
28+
29+
template <class _Tp>
30+
struct __libcpp_datasizeof {
31+
#if __has_cpp_attribute(__no_unique_address__)
32+
template <class = char>
33+
struct _FirstPaddingByte {
34+
[[__no_unique_address__]] _Tp __v_;
35+
char __first_padding_byte_;
36+
};
37+
#else
38+
template <bool = __libcpp_is_final<_Tp>::value || !is_class<_Tp>::value>
39+
struct _FirstPaddingByte : _Tp {
40+
char __first_padding_byte_;
41+
};
42+
43+
template <>
44+
struct _FirstPaddingByte<true> {
45+
_Tp __v_;
46+
char __first_padding_byte_;
47+
};
48+
#endif
49+
50+
static const size_t value = offsetof(_FirstPaddingByte<>, __first_padding_byte_);
51+
};
52+
53+
_LIBCPP_END_NAMESPACE_STD
54+
55+
#endif // _LIBCPP___TYPE_TRAITS_DATASIZEOF_H

‎libcxx/include/__utility/is_pointer_in_range.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
#include <__type_traits/enable_if.h>
1616
#include <__type_traits/integral_constant.h>
1717
#include <__type_traits/is_constant_evaluated.h>
18-
#include <__type_traits/is_function.h>
19-
#include <__type_traits/is_member_pointer.h>
2018
#include <__type_traits/void_t.h>
2119
#include <__utility/declval.h>
2220

@@ -26,14 +24,16 @@
2624

2725
_LIBCPP_BEGIN_NAMESPACE_STD
2826

27+
template <class _Tp, class _Up, class = void>
28+
struct __is_less_than_comparable : false_type {};
29+
2930
template <class _Tp, class _Up>
31+
struct __is_less_than_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() < std::declval<_Up>())> > : true_type {
32+
};
33+
34+
template <class _Tp, class _Up, __enable_if_t<__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0>
3035
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range(
3136
const _Tp* __begin, const _Tp* __end, const _Up* __ptr) {
32-
static_assert(!is_function<_Tp>::value && !is_function<_Up>::value,
33-
"__is_pointer_in_range should not be called with function pointers");
34-
static_assert(!is_member_pointer<_Tp>::value && !is_member_pointer<_Up>::value,
35-
"__is_pointer_in_range should not be called with member pointers");
36-
3737
if (__libcpp_is_constant_evaluated()) {
3838
_LIBCPP_ASSERT_UNCATEGORIZED(__builtin_constant_p(__begin <= __end), "__begin and __end do not form a range");
3939

@@ -47,6 +47,16 @@ _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address
4747
return !__less<>()(__ptr, __begin) && __less<>()(__ptr, __end);
4848
}
4949

50+
template <class _Tp, class _Up, __enable_if_t<!__is_less_than_comparable<const _Tp*, const _Up*>::value, int> = 0>
51+
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") bool __is_pointer_in_range(
52+
const _Tp* __begin, const _Tp* __end, const _Up* __ptr) {
53+
if (__libcpp_is_constant_evaluated())
54+
return false;
55+
56+
return reinterpret_cast<const char*>(__begin) <= reinterpret_cast<const char*>(__ptr) &&
57+
reinterpret_cast<const char*>(__ptr) < reinterpret_cast<const char*>(__end);
58+
}
59+
5060
_LIBCPP_END_NAMESPACE_STD
5161

5262
#endif // _LIBCPP___UTILITY_IS_POINTER_IN_RANGE_H

‎libcxx/include/module.modulemap.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,7 @@ module std [system] {
15761576
module conjunction { private header "__type_traits/conjunction.h" }
15771577
module copy_cv { private header "__type_traits/copy_cv.h" }
15781578
module copy_cvref { private header "__type_traits/copy_cvref.h" }
1579+
module datasizeof { private header "__type_traits/datasizeof.h" }
15791580
module decay { private header "__type_traits/decay.h" }
15801581
module dependent_type { private header "__type_traits/dependent_type.h" }
15811582
module disjunction { private header "__type_traits/disjunction.h" }

‎libcxx/include/string

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,6 @@ struct __can_be_converted_to_string_view : public _BoolConstant<
663663

664664
struct __uninitialized_size_tag {};
665665

666-
template <class _Tp, class _Up, class = void>
667-
struct __is_less_than_comparable : false_type {};
668-
669-
template <class _Tp, class _Up>
670-
struct __is_less_than_comparable<_Tp, _Up, __void_t<decltype(std::declval<_Tp>() < std::declval<_Up>())> > : true_type {
671-
};
672-
673666
template<class _CharT, class _Traits, class _Allocator>
674667
class basic_string
675668
{
@@ -1910,25 +1903,11 @@ private:
19101903
return *this;
19111904
}
19121905

1913-
template <
1914-
class _Tp,
1915-
__enable_if_t<__is_less_than_comparable<const __remove_cvref_t<_Tp>*, const value_type*>::value, int> = 0>
1906+
template <class _Tp>
19161907
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const {
19171908
return std::__is_pointer_in_range(data(), data() + size() + 1, std::addressof(__v));
19181909
}
19191910

1920-
template <
1921-
class _Tp,
1922-
__enable_if_t<!__is_less_than_comparable<const __remove_cvref_t<_Tp>*, const value_type*>::value, int> = 0>
1923-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __addr_in_range(const _Tp& __v) const {
1924-
if (__libcpp_is_constant_evaluated())
1925-
return false;
1926-
1927-
auto __t_ptr = reinterpret_cast<const char*>(std::addressof(__v));
1928-
return reinterpret_cast<const char*>(data()) <= __t_ptr &&
1929-
__t_ptr < reinterpret_cast<const char*>(data() + size() + 1);
1930-
}
1931-
19321911
_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI
19331912
void __throw_length_error() const {
19341913
std::__throw_length_error("basic_string");

‎libcxx/test/libcxx/algorithms/alg.modifying.operations/copy_move_trivial.pass.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,6 @@ void test_one(Func func) {
156156
}
157157
}));
158158
}
159-
160-
// Empty input sequence.
161-
{
162-
const std::size_t N = 0;
163-
164-
From input[1] = {make<From>(1)};
165-
To output[1] = {make<To>(2)};
166-
167-
auto in = InIter(input);
168-
auto in_end = InIter(input + N);
169-
auto sent = SentWrapper<decltype(in_end)>(in_end);
170-
auto out = OutIter(output);
171-
172-
assert(!memmove_called);
173-
func(in, sent, out, N);
174-
175-
assert(memmove_called);
176-
memmove_called = false;
177-
assert(output[0] == make<To>(2));
178-
}
179159
}
180160

181161
template <class InIter, template <class> class SentWrapper, class OutIter>

‎libcxx/test/libcxx/transitive_includes/cxx03.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ array algorithm
4242
array compare
4343
array concepts
4444
array cstddef
45+
array cstdint
4546
array cstdlib
4647
array initializer_list
4748
array iterator
@@ -506,6 +507,7 @@ locale version
506507
map compare
507508
map concepts
508509
map cstddef
510+
map cstdint
509511
map cstdlib
510512
map functional
511513
map initializer_list
@@ -731,6 +733,7 @@ semaphore version
731733
set compare
732734
set concepts
733735
set cstddef
736+
set cstdint
734737
set cstdlib
735738
set functional
736739
set initializer_list

‎libcxx/test/libcxx/transitive_includes/cxx11.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ array algorithm
4242
array compare
4343
array concepts
4444
array cstddef
45+
array cstdint
4546
array cstdlib
4647
array initializer_list
4748
array iterator
@@ -506,6 +507,7 @@ locale version
506507
map compare
507508
map concepts
508509
map cstddef
510+
map cstdint
509511
map cstdlib
510512
map functional
511513
map initializer_list
@@ -732,6 +734,7 @@ semaphore version
732734
set compare
733735
set concepts
734736
set cstddef
737+
set cstdint
735738
set cstdlib
736739
set functional
737740
set initializer_list

‎libcxx/test/libcxx/transitive_includes/cxx14.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ array algorithm
4242
array compare
4343
array concepts
4444
array cstddef
45+
array cstdint
4546
array cstdlib
4647
array initializer_list
4748
array iterator
@@ -508,6 +509,7 @@ locale version
508509
map compare
509510
map concepts
510511
map cstddef
512+
map cstdint
511513
map cstdlib
512514
map functional
513515
map initializer_list
@@ -734,6 +736,7 @@ semaphore version
734736
set compare
735737
set concepts
736738
set cstddef
739+
set cstdint
737740
set cstdlib
738741
set functional
739742
set initializer_list

‎libcxx/test/libcxx/transitive_includes/cxx17.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ array algorithm
4242
array compare
4343
array concepts
4444
array cstddef
45+
array cstdint
4546
array cstdlib
4647
array initializer_list
4748
array iterator
@@ -508,6 +509,7 @@ locale version
508509
map compare
509510
map concepts
510511
map cstddef
512+
map cstdint
511513
map cstdlib
512514
map functional
513515
map initializer_list
@@ -734,6 +736,7 @@ semaphore version
734736
set compare
735737
set concepts
736738
set cstddef
739+
set cstdint
737740
set cstdlib
738741
set functional
739742
set initializer_list

‎libcxx/test/libcxx/transitive_includes/cxx20.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ array algorithm
4141
array compare
4242
array concepts
4343
array cstddef
44+
array cstdint
4445
array cstdlib
4546
array initializer_list
4647
array iterator
@@ -514,6 +515,7 @@ locale version
514515
map compare
515516
map concepts
516517
map cstddef
518+
map cstdint
517519
map cstdlib
518520
map functional
519521
map initializer_list
@@ -740,6 +742,7 @@ semaphore version
740742
set compare
741743
set concepts
742744
set cstddef
745+
set cstdint
743746
set cstdlib
744747
set functional
745748
set initializer_list

‎libcxx/test/libcxx/transitive_includes/cxx23.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ any typeinfo
2121
any version
2222
array compare
2323
array cstddef
24+
array cstdint
2425
array initializer_list
2526
array limits
2627
array stdexcept
@@ -348,6 +349,7 @@ locale string
348349
locale version
349350
map compare
350351
map cstddef
352+
map cstdint
351353
map initializer_list
352354
map limits
353355
map new
@@ -501,6 +503,7 @@ semaphore ratio
501503
semaphore version
502504
set compare
503505
set cstddef
506+
set cstdint
504507
set initializer_list
505508
set limits
506509
set new

‎libcxx/test/libcxx/transitive_includes/cxx26.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ any typeinfo
2121
any version
2222
array compare
2323
array cstddef
24+
array cstdint
2425
array initializer_list
2526
array limits
2627
array stdexcept
@@ -348,6 +349,7 @@ locale string
348349
locale version
349350
map compare
350351
map cstddef
352+
map cstdint
351353
map initializer_list
352354
map limits
353355
map new
@@ -501,6 +503,7 @@ semaphore ratio
501503
semaphore version
502504
set compare
503505
set cstddef
506+
set cstdint
504507
set initializer_list
505508
set limits
506509
set new
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===----------------------------------------------------------------------===//
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+
//===----------------------------------------------------------------------===//
8+
9+
// ADDITIONAL_COMPILE_FLAGS: -Wno-private-header
10+
11+
#include <__type_traits/datasizeof.h>
12+
#include <cstdint>
13+
14+
static_assert(std::__libcpp_datasizeof<std::int8_t>::value == 1, "");
15+
static_assert(std::__libcpp_datasizeof<std::int16_t>::value == 2, "");
16+
static_assert(std::__libcpp_datasizeof<std::int32_t>::value == 4, "");
17+
static_assert(std::__libcpp_datasizeof<std::int64_t>::value == 8, "");
18+
19+
struct OneBytePadding {
20+
OneBytePadding() {}
21+
22+
std::int16_t a;
23+
std::int8_t b;
24+
};
25+
26+
#if defined(_WIN32) && !defined(__MINGW32__)
27+
static_assert(std::__libcpp_datasizeof<OneBytePadding>::value == 4, "");
28+
#else
29+
static_assert(std::__libcpp_datasizeof<OneBytePadding>::value == 3, "");
30+
#endif
31+
32+
struct InBetweenPadding {
33+
InBetweenPadding() {}
34+
35+
std::int32_t a;
36+
std::int8_t b;
37+
std::int16_t c;
38+
};
39+
40+
static_assert(std::__libcpp_datasizeof<InBetweenPadding>::value == 8, "");

‎libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp

Lines changed: 57 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,78 +18,74 @@
1818
#include "test_macros.h"
1919
#include "test_iterators.h"
2020

21-
template <class InIter, class OutIter>
22-
TEST_CONSTEXPR_CXX20 void
23-
test_copy()
24-
{
21+
class PaddedBase {
22+
public:
23+
TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
24+
25+
std::int16_t a_;
26+
std::int8_t b_;
27+
};
28+
29+
class Derived : public PaddedBase {
30+
public:
31+
TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
32+
33+
std::int8_t c_;
34+
};
35+
36+
template <class InIter>
37+
struct Test {
38+
template <class OutIter>
39+
TEST_CONSTEXPR_CXX20 void operator()() {
2540
const unsigned N = 1000;
26-
int ia[N] = {};
41+
int ia[N] = {};
2742
for (unsigned i = 0; i < N; ++i)
28-
ia[i] = i;
43+
ia[i] = i;
2944
int ib[N] = {0};
3045

31-
OutIter r = std::copy(InIter(ia), InIter(ia+N), OutIter(ib));
32-
assert(base(r) == ib+N);
46+
OutIter r = std::copy(InIter(ia), InIter(ia + N), OutIter(ib));
47+
assert(base(r) == ib + N);
3348
for (unsigned i = 0; i < N; ++i)
34-
assert(ia[i] == ib[i]);
35-
}
36-
37-
TEST_CONSTEXPR_CXX20 bool
38-
test()
39-
{
40-
test_copy<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
41-
test_copy<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
42-
test_copy<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
43-
test_copy<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
44-
test_copy<cpp17_input_iterator<const int*>, int*>();
45-
46-
test_copy<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
47-
test_copy<forward_iterator<const int*>, forward_iterator<int*> >();
48-
test_copy<forward_iterator<const int*>, bidirectional_iterator<int*> >();
49-
test_copy<forward_iterator<const int*>, random_access_iterator<int*> >();
50-
test_copy<forward_iterator<const int*>, int*>();
51-
52-
test_copy<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
53-
test_copy<bidirectional_iterator<const int*>, forward_iterator<int*> >();
54-
test_copy<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
55-
test_copy<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
56-
test_copy<bidirectional_iterator<const int*>, int*>();
57-
58-
test_copy<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
59-
test_copy<random_access_iterator<const int*>, forward_iterator<int*> >();
60-
test_copy<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
61-
test_copy<random_access_iterator<const int*>, random_access_iterator<int*> >();
62-
test_copy<random_access_iterator<const int*>, int*>();
63-
64-
test_copy<const int*, cpp17_output_iterator<int*> >();
65-
test_copy<const int*, forward_iterator<int*> >();
66-
test_copy<const int*, bidirectional_iterator<int*> >();
67-
test_copy<const int*, random_access_iterator<int*> >();
68-
test_copy<const int*, int*>();
69-
70-
#if TEST_STD_VER > 17
71-
test_copy<cpp17_input_iterator<const int*>, contiguous_iterator<int*>>();
72-
test_copy<forward_iterator<const int*>, contiguous_iterator<int*>>();
73-
test_copy<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
74-
test_copy<random_access_iterator<const int*>, contiguous_iterator<int*>>();
75-
test_copy<const int*, contiguous_iterator<int*>>();
76-
77-
test_copy<contiguous_iterator<const int*>, cpp17_output_iterator<int*>>();
78-
test_copy<contiguous_iterator<const int*>, forward_iterator<int*>>();
79-
test_copy<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
80-
test_copy<contiguous_iterator<const int*>, random_access_iterator<int*>>();
81-
test_copy<contiguous_iterator<const int*>, int*>();
82-
#endif
49+
assert(ia[i] == ib[i]);
50+
}
51+
};
52+
53+
struct TestInIters {
54+
template <class InIter>
55+
TEST_CONSTEXPR_CXX20 void operator()() {
56+
types::for_each(
57+
types::concatenate_t<types::cpp17_input_iterator_list<int*>, types::type_list<cpp17_output_iterator<int*> > >(),
58+
Test<InIter>());
59+
}
60+
};
61+
62+
TEST_CONSTEXPR_CXX20 bool test() {
63+
types::for_each(types::cpp17_input_iterator_list<int*>(), TestInIters());
64+
65+
{ // Make sure that padding bits aren't copied
66+
Derived src(1, 2, 3);
67+
Derived dst(4, 5, 6);
68+
std::copy(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
69+
assert(dst.a_ == 1);
70+
assert(dst.b_ == 2);
71+
assert(dst.c_ == 6);
72+
}
73+
74+
{ // Make sure that overlapping ranges can be copied
75+
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
76+
std::copy(a + 3, a + 10, a);
77+
int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
78+
assert(std::equal(a, a + 10, expected));
79+
}
8380

8481
return true;
8582
}
8683

87-
int main(int, char**)
88-
{
89-
test();
84+
int main(int, char**) {
85+
test();
9086

9187
#if TEST_STD_VER > 17
92-
static_assert(test());
88+
static_assert(test());
9389
#endif
9490

9591
return 0;

‎libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_backward.pass.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,26 @@
2020
#include "test_iterators.h"
2121
#include "user_defined_integral.h"
2222

23+
class PaddedBase {
24+
public:
25+
TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
26+
27+
std::int16_t a_;
28+
std::int8_t b_;
29+
};
30+
31+
class Derived : public PaddedBase {
32+
public:
33+
TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
34+
35+
std::int8_t c_;
36+
};
37+
2338
template <class InIter, class OutIter>
2439
TEST_CONSTEXPR_CXX20 void
2540
test_copy_backward()
2641
{
42+
{
2743
const unsigned N = 1000;
2844
int ia[N] = {};
2945
for (unsigned i = 0; i < N; ++i)
@@ -34,6 +50,7 @@ test_copy_backward()
3450
assert(base(r) == ib);
3551
for (unsigned i = 0; i < N; ++i)
3652
assert(ia[i] == ib[i]);
53+
}
3754
}
3855

3956
TEST_CONSTEXPR_CXX20 bool
@@ -62,6 +79,23 @@ test()
6279
test_copy_backward<const int*, contiguous_iterator<int*>>();
6380
#endif
6481

82+
{ // Make sure that padding bits aren't copied
83+
Derived src(1, 2, 3);
84+
Derived dst(4, 5, 6);
85+
std::copy_backward(
86+
static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
87+
assert(dst.a_ == 1);
88+
assert(dst.b_ == 2);
89+
assert(dst.c_ == 6);
90+
}
91+
92+
{ // Make sure that overlapping ranges can be copied
93+
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
94+
std::copy_backward(a, a + 7, a + 10);
95+
int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
96+
assert(std::equal(a, a + 10, expected));
97+
}
98+
6599
return true;
66100
}
67101

‎libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,26 @@
2121

2222
typedef UserDefinedIntegral<unsigned> UDI;
2323

24+
class PaddedBase {
25+
public:
26+
TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
27+
28+
std::int16_t a_;
29+
std::int8_t b_;
30+
};
31+
32+
class Derived : public PaddedBase {
33+
public:
34+
TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
35+
36+
std::int8_t c_;
37+
};
38+
2439
template <class InIter, class OutIter>
2540
TEST_CONSTEXPR_CXX20 void
2641
test_copy_n()
2742
{
43+
{
2844
const unsigned N = 1000;
2945
int ia[N] = {};
3046
for (unsigned i = 0; i < N; ++i)
@@ -35,6 +51,23 @@ test_copy_n()
3551
assert(base(r) == ib+N/2);
3652
for (unsigned i = 0; i < N/2; ++i)
3753
assert(ia[i] == ib[i]);
54+
}
55+
56+
{ // Make sure that padding bits aren't copied
57+
Derived src(1, 2, 3);
58+
Derived dst(4, 5, 6);
59+
std::copy_n(static_cast<PaddedBase*>(&src), 1, static_cast<PaddedBase*>(&dst));
60+
assert(dst.a_ == 1);
61+
assert(dst.b_ == 2);
62+
assert(dst.c_ == 6);
63+
}
64+
65+
{ // Make sure that overlapping ranges can be copied
66+
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
67+
std::copy_n(a + 3, 7, a);
68+
int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
69+
assert(std::equal(a, a + 10, expected));
70+
}
3871
}
3972

4073
TEST_CONSTEXPR_CXX20 bool

‎libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp

Lines changed: 76 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
// UNSUPPORTED: c++03 && !stdlib=libc++
10+
// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
11+
912
// <algorithm>
1013

1114
// template<InputIterator InIter, typename OutIter>
@@ -20,10 +23,25 @@
2023
#include "test_macros.h"
2124
#include "test_iterators.h"
2225

23-
template <class InIter, class OutIter>
24-
TEST_CONSTEXPR_CXX17 bool
25-
test()
26-
{
26+
class PaddedBase {
27+
public:
28+
TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
29+
30+
std::int16_t a_;
31+
std::int8_t b_;
32+
};
33+
34+
class Derived : public PaddedBase {
35+
public:
36+
TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
37+
38+
std::int8_t c_;
39+
};
40+
41+
template <class InIter>
42+
struct Test {
43+
template <class OutIter>
44+
TEST_CONSTEXPR_CXX20 void operator()() {
2745
const unsigned N = 1000;
2846
int ia[N] = {};
2947
for (unsigned i = 0; i < N; ++i)
@@ -34,15 +52,22 @@ test()
3452
assert(base(r) == ib+N);
3553
for (unsigned i = 0; i < N; ++i)
3654
assert(ia[i] == ib[i]);
37-
38-
return true;
39-
}
40-
41-
#if TEST_STD_VER >= 11
42-
template <class InIter, class OutIter>
43-
void
44-
test1()
45-
{
55+
}
56+
};
57+
58+
struct TestOutIters {
59+
template <class InIter>
60+
TEST_CONSTEXPR_CXX20 void operator()() {
61+
types::for_each(
62+
types::concatenate_t<types::cpp17_input_iterator_list<int*>, types::type_list<cpp17_output_iterator<int*> > >(),
63+
Test<InIter>());
64+
}
65+
};
66+
67+
template <class InIter>
68+
struct Test1 {
69+
template <class OutIter>
70+
TEST_CONSTEXPR_CXX23 void operator()() {
4671
const unsigned N = 100;
4772
std::unique_ptr<int> ia[N];
4873
for (unsigned i = 0; i < N; ++i)
@@ -53,140 +78,48 @@ test1()
5378
assert(base(r) == ib+N);
5479
for (unsigned i = 0; i < N; ++i)
5580
assert(*ib[i] == static_cast<int>(i));
81+
}
82+
};
83+
84+
struct Test1OutIters {
85+
template <class InIter>
86+
TEST_CONSTEXPR_CXX23 void operator()() {
87+
types::for_each(types::concatenate_t<types::cpp17_input_iterator_list<std::unique_ptr<int>*>,
88+
types::type_list<cpp17_output_iterator<std::unique_ptr<int>*> > >(),
89+
Test1<InIter>());
90+
}
91+
};
92+
93+
TEST_CONSTEXPR_CXX20 bool test() {
94+
types::for_each(types::cpp17_input_iterator_list<int*>(), TestOutIters());
95+
if (TEST_STD_VER >= 23 || !TEST_IS_CONSTANT_EVALUATED)
96+
types::for_each(types::cpp17_input_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
97+
98+
{ // Make sure that padding bits aren't copied
99+
Derived src(1, 2, 3);
100+
Derived dst(4, 5, 6);
101+
std::move(static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst));
102+
assert(dst.a_ == 1);
103+
assert(dst.b_ == 2);
104+
assert(dst.c_ == 6);
105+
}
106+
107+
{ // Make sure that overlapping ranges can be copied
108+
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
109+
std::move(a + 3, a + 10, a);
110+
int expected[] = {4, 5, 6, 7, 8, 9, 10, 8, 9, 10};
111+
assert(std::equal(a, a + 10, expected));
112+
}
113+
114+
return true;
56115
}
57-
#endif
58116

59117
int main(int, char**)
60118
{
61-
test<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
62-
test<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
63-
test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
64-
test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
65-
test<cpp17_input_iterator<const int*>, int*>();
66-
67-
test<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
68-
test<forward_iterator<const int*>, forward_iterator<int*> >();
69-
test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
70-
test<forward_iterator<const int*>, random_access_iterator<int*> >();
71-
test<forward_iterator<const int*>, int*>();
72-
73-
test<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
74-
test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
75-
test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
76-
test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
77-
test<bidirectional_iterator<const int*>, int*>();
78-
79-
test<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
80-
test<random_access_iterator<const int*>, forward_iterator<int*> >();
81-
test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
82-
test<random_access_iterator<const int*>, random_access_iterator<int*> >();
83-
test<random_access_iterator<const int*>, int*>();
84-
85-
test<const int*, cpp17_output_iterator<int*> >();
86-
test<const int*, forward_iterator<int*> >();
87-
test<const int*, bidirectional_iterator<int*> >();
88-
test<const int*, random_access_iterator<int*> >();
89-
test<const int*, int*>();
90-
91-
#if TEST_STD_VER >= 11
92-
test1<cpp17_input_iterator<std::unique_ptr<int>*>, cpp17_output_iterator<std::unique_ptr<int>*> >();
93-
test1<cpp17_input_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
94-
test1<cpp17_input_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
95-
test1<cpp17_input_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
96-
test1<cpp17_input_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
97-
98-
test1<forward_iterator<std::unique_ptr<int>*>, cpp17_output_iterator<std::unique_ptr<int>*> >();
99-
test1<forward_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
100-
test1<forward_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
101-
test1<forward_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
102-
test1<forward_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
103-
104-
test1<bidirectional_iterator<std::unique_ptr<int>*>, cpp17_output_iterator<std::unique_ptr<int>*> >();
105-
test1<bidirectional_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
106-
test1<bidirectional_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
107-
test1<bidirectional_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
108-
test1<bidirectional_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
109-
110-
test1<random_access_iterator<std::unique_ptr<int>*>, cpp17_output_iterator<std::unique_ptr<int>*> >();
111-
test1<random_access_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*> >();
112-
test1<random_access_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
113-
test1<random_access_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
114-
test1<random_access_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
115-
116-
test1<std::unique_ptr<int>*, cpp17_output_iterator<std::unique_ptr<int>*> >();
117-
test1<std::unique_ptr<int>*, forward_iterator<std::unique_ptr<int>*> >();
118-
test1<std::unique_ptr<int>*, bidirectional_iterator<std::unique_ptr<int>*> >();
119-
test1<std::unique_ptr<int>*, random_access_iterator<std::unique_ptr<int>*> >();
120-
test1<std::unique_ptr<int>*, std::unique_ptr<int>*>();
121-
#endif // TEST_STD_VER >= 11
122-
123-
#if TEST_STD_VER > 17
124-
test<cpp17_input_iterator<const int*>, contiguous_iterator<int*>>();
125-
test<forward_iterator<const int*>, contiguous_iterator<int*>>();
126-
test<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
127-
test<random_access_iterator<const int*>, contiguous_iterator<int*>>();
128-
test<const int*, contiguous_iterator<int*>>();
129-
test<contiguous_iterator<const int*>, cpp17_output_iterator<int*>>();
130-
test<contiguous_iterator<const int*>, forward_iterator<int*>>();
131-
test<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
132-
test<contiguous_iterator<const int*>, random_access_iterator<int*>>();
133-
test<contiguous_iterator<const int*>, int*>();
134-
test<contiguous_iterator<const int*>, contiguous_iterator<int*>>();
135-
136-
test1<cpp17_input_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
137-
test1<forward_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
138-
test1<bidirectional_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
139-
test1<random_access_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
140-
test1<std::unique_ptr<int>*, contiguous_iterator<std::unique_ptr<int>*>>();
141-
test1<contiguous_iterator<std::unique_ptr<int>*>, cpp17_output_iterator<std::unique_ptr<int>*>>();
142-
test1<contiguous_iterator<std::unique_ptr<int>*>, forward_iterator<std::unique_ptr<int>*>>();
143-
test1<contiguous_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*>>();
144-
test1<contiguous_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*>>();
145-
test1<contiguous_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
146-
test1<contiguous_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
147-
148-
static_assert(test<cpp17_input_iterator<const int*>, cpp17_input_iterator<int*> >());
149-
static_assert(test<cpp17_input_iterator<const int*>, forward_iterator<int*> >());
150-
static_assert(test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >());
151-
static_assert(test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >());
152-
static_assert(test<cpp17_input_iterator<const int*>, contiguous_iterator<int*> >());
153-
static_assert(test<cpp17_input_iterator<const int*>, int*>());
154-
155-
static_assert(test<forward_iterator<const int*>, cpp17_input_iterator<int*> >());
156-
static_assert(test<forward_iterator<const int*>, forward_iterator<int*> >());
157-
static_assert(test<forward_iterator<const int*>, bidirectional_iterator<int*> >());
158-
static_assert(test<forward_iterator<const int*>, random_access_iterator<int*> >());
159-
static_assert(test<forward_iterator<const int*>, contiguous_iterator<int*> >());
160-
static_assert(test<forward_iterator<const int*>, int*>());
161-
162-
static_assert(test<bidirectional_iterator<const int*>, cpp17_input_iterator<int*> >());
163-
static_assert(test<bidirectional_iterator<const int*>, forward_iterator<int*> >());
164-
static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >());
165-
static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >());
166-
static_assert(test<bidirectional_iterator<const int*>, contiguous_iterator<int*> >());
167-
static_assert(test<bidirectional_iterator<const int*>, int*>());
168-
169-
static_assert(test<random_access_iterator<const int*>, cpp17_input_iterator<int*> >());
170-
static_assert(test<random_access_iterator<const int*>, forward_iterator<int*> >());
171-
static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >());
172-
static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >());
173-
static_assert(test<random_access_iterator<const int*>, contiguous_iterator<int*> >());
174-
static_assert(test<random_access_iterator<const int*>, int*>());
175-
176-
static_assert(test<contiguous_iterator<const int*>, cpp17_input_iterator<int*> >());
177-
static_assert(test<contiguous_iterator<const int*>, forward_iterator<int*> >());
178-
static_assert(test<contiguous_iterator<const int*>, bidirectional_iterator<int*> >());
179-
static_assert(test<contiguous_iterator<const int*>, random_access_iterator<int*> >());
180-
static_assert(test<contiguous_iterator<const int*>, contiguous_iterator<int*> >());
181-
static_assert(test<contiguous_iterator<const int*>, int*>());
182-
183-
static_assert(test<const int*, cpp17_input_iterator<int*> >());
184-
static_assert(test<const int*, forward_iterator<int*> >());
185-
static_assert(test<const int*, bidirectional_iterator<int*> >());
186-
static_assert(test<const int*, random_access_iterator<int*> >());
187-
static_assert(test<const int*, contiguous_iterator<int*> >());
188-
static_assert(test<const int*, int*>());
189-
#endif // TEST_STD_VER > 17
119+
test();
120+
#if TEST_STD_VER >= 20
121+
static_assert(test());
122+
#endif
190123

191124
return 0;
192125
}

‎libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp

Lines changed: 75 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
// UNSUPPORTED: c++03 && !stdlib=libc++
10+
911
// <algorithm>
1012

1113
// template<BidirectionalIterator InIter, BidirectionalIterator OutIter>
@@ -20,10 +22,25 @@
2022
#include "test_macros.h"
2123
#include "test_iterators.h"
2224

23-
template <class InIter, class OutIter>
24-
TEST_CONSTEXPR_CXX17 bool
25-
test()
26-
{
25+
class PaddedBase {
26+
public:
27+
TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
28+
29+
std::int16_t a_;
30+
std::int8_t b_;
31+
};
32+
33+
class Derived : public PaddedBase {
34+
public:
35+
TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
36+
37+
std::int8_t c_;
38+
};
39+
40+
template <class InIter>
41+
struct Test {
42+
template <class OutIter>
43+
TEST_CONSTEXPR_CXX20 void operator()() {
2744
const unsigned N = 1000;
2845
int ia[N] = {};
2946
for (unsigned i = 0; i < N; ++i)
@@ -34,15 +51,22 @@ test()
3451
assert(base(r) == ib);
3552
for (unsigned i = 0; i < N; ++i)
3653
assert(ia[i] == ib[i]);
37-
38-
return true;
39-
}
40-
41-
#if TEST_STD_VER >= 11
42-
template <class InIter, class OutIter>
43-
void
44-
test1()
45-
{
54+
}
55+
};
56+
57+
struct TestOutIters {
58+
template <class InIter>
59+
TEST_CONSTEXPR_CXX20 void operator()() {
60+
types::for_each(
61+
types::concatenate_t<types::bidirectional_iterator_list<int*> >(),
62+
Test<InIter>());
63+
}
64+
};
65+
66+
template <class InIter>
67+
struct Test1 {
68+
template <class OutIter>
69+
TEST_CONSTEXPR_CXX23 void operator()() {
4670
const unsigned N = 100;
4771
std::unique_ptr<int> ia[N];
4872
for (unsigned i = 0; i < N; ++i)
@@ -53,74 +77,48 @@ test1()
5377
assert(base(r) == ib);
5478
for (unsigned i = 0; i < N; ++i)
5579
assert(*ib[i] == static_cast<int>(i));
80+
}
81+
};
82+
83+
struct Test1OutIters {
84+
template <class InIter>
85+
TEST_CONSTEXPR_CXX23 void operator()() {
86+
types::for_each(types::concatenate_t<types::bidirectional_iterator_list<std::unique_ptr<int>*> >(),
87+
Test1<InIter>());
88+
}
89+
};
90+
91+
TEST_CONSTEXPR_CXX20 bool test() {
92+
types::for_each(types::bidirectional_iterator_list<int*>(), TestOutIters());
93+
if (TEST_STD_VER >= 23 || !TEST_IS_CONSTANT_EVALUATED)
94+
types::for_each(types::bidirectional_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
95+
96+
{ // Make sure that padding bits aren't copied
97+
Derived src(1, 2, 3);
98+
Derived dst(4, 5, 6);
99+
std::move_backward(
100+
static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
101+
assert(dst.a_ == 1);
102+
assert(dst.b_ == 2);
103+
assert(dst.c_ == 6);
104+
}
105+
106+
{ // Make sure that overlapping ranges can be copied
107+
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
108+
std::move_backward(a, a + 7, a + 10);
109+
int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
110+
assert(std::equal(a, a + 10, expected));
111+
}
112+
113+
return true;
56114
}
57-
#endif
58115

59116
int main(int, char**)
60117
{
61-
test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
62-
test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
63-
test<bidirectional_iterator<const int*>, int*>();
64-
65-
test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
66-
test<random_access_iterator<const int*>, random_access_iterator<int*> >();
67-
test<random_access_iterator<const int*>, int*>();
68-
69-
test<const int*, bidirectional_iterator<int*> >();
70-
test<const int*, random_access_iterator<int*> >();
71-
test<const int*, int*>();
72-
73-
#if TEST_STD_VER >= 11
74-
test1<bidirectional_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
75-
test1<bidirectional_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
76-
test1<bidirectional_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
77-
78-
test1<random_access_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*> >();
79-
test1<random_access_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*> >();
80-
test1<random_access_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
81-
82-
test1<std::unique_ptr<int>*, bidirectional_iterator<std::unique_ptr<int>*> >();
83-
test1<std::unique_ptr<int>*, random_access_iterator<std::unique_ptr<int>*> >();
84-
test1<std::unique_ptr<int>*, std::unique_ptr<int>*>();
85-
#endif // TEST_STD_VER >= 11
86-
87-
#if TEST_STD_VER > 17
88-
test<bidirectional_iterator<const int*>, contiguous_iterator<int*>>();
89-
test<random_access_iterator<const int*>, contiguous_iterator<int*>>();
90-
test<const int*, contiguous_iterator<int*>>();
91-
test<contiguous_iterator<const int*>, bidirectional_iterator<int*>>();
92-
test<contiguous_iterator<const int*>, random_access_iterator<int*>>();
93-
test<contiguous_iterator<const int*>, int*>();
94-
test<contiguous_iterator<const int*>, contiguous_iterator<int*>>();
95-
96-
test1<bidirectional_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
97-
test1<random_access_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
98-
test1<std::unique_ptr<int>*, contiguous_iterator<std::unique_ptr<int>*>>();
99-
test1<contiguous_iterator<std::unique_ptr<int>*>, bidirectional_iterator<std::unique_ptr<int>*>>();
100-
test1<contiguous_iterator<std::unique_ptr<int>*>, random_access_iterator<std::unique_ptr<int>*>>();
101-
test1<contiguous_iterator<std::unique_ptr<int>*>, std::unique_ptr<int>*>();
102-
test1<contiguous_iterator<std::unique_ptr<int>*>, contiguous_iterator<std::unique_ptr<int>*>>();
103-
104-
static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >());
105-
static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >());
106-
static_assert(test<bidirectional_iterator<const int*>, contiguous_iterator<int*> >());
107-
static_assert(test<bidirectional_iterator<const int*>, int*>());
108-
109-
static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >());
110-
static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >());
111-
static_assert(test<random_access_iterator<const int*>, contiguous_iterator<int*> >());
112-
static_assert(test<random_access_iterator<const int*>, int*>());
113-
114-
static_assert(test<contiguous_iterator<const int*>, bidirectional_iterator<int*> >());
115-
static_assert(test<contiguous_iterator<const int*>, random_access_iterator<int*> >());
116-
static_assert(test<contiguous_iterator<const int*>, contiguous_iterator<int*> >());
117-
static_assert(test<contiguous_iterator<const int*>, int*>());
118-
119-
static_assert(test<const int*, bidirectional_iterator<int*> >());
120-
static_assert(test<const int*, random_access_iterator<int*> >());
121-
static_assert(test<const int*, contiguous_iterator<int*> >());
122-
static_assert(test<const int*, int*>());
123-
#endif // TEST_STD_VER > 17
118+
test();
119+
#if TEST_STD_VER >= 20
120+
static_assert(test());
121+
#endif
124122

125123
return 0;
126124
}

0 commit comments

Comments
 (0)
Please sign in to comment.