2021-06-17 11:30:11 -04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef _LIBCPP___ALGORITHM_STABLE_PARTITION_H
|
|
|
|
#define _LIBCPP___ALGORITHM_STABLE_PARTITION_H
|
|
|
|
|
2022-07-18 21:05:51 -07:00
|
|
|
#include <__algorithm/iterator_operations.h>
|
2021-06-17 11:30:11 -04:00
|
|
|
#include <__algorithm/rotate.h>
|
2022-01-07 09:45:05 -05:00
|
|
|
#include <__config>
|
2024-10-31 02:20:10 +01:00
|
|
|
#include <__cstddef/ptrdiff_t.h>
|
2022-06-10 19:53:10 +02:00
|
|
|
#include <__iterator/advance.h>
|
|
|
|
#include <__iterator/distance.h>
|
2021-06-17 11:30:11 -04:00
|
|
|
#include <__iterator/iterator_traits.h>
|
2025-03-04 09:23:29 +08:00
|
|
|
#include <__memory/construct_at.h>
|
2022-09-05 00:01:15 +02:00
|
|
|
#include <__memory/destruct_n.h>
|
|
|
|
#include <__memory/unique_ptr.h>
|
2024-09-16 23:53:05 +08:00
|
|
|
#include <__memory/unique_temporary_buffer.h>
|
2024-09-16 15:06:20 -04:00
|
|
|
#include <__type_traits/remove_cvref.h>
|
2022-10-17 17:42:00 +02:00
|
|
|
#include <__utility/move.h>
|
2022-09-05 00:01:15 +02:00
|
|
|
#include <__utility/pair.h>
|
2021-06-17 11:30:11 -04:00
|
|
|
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
2022-02-01 20:16:40 -05:00
|
|
|
# pragma GCC system_header
|
2021-06-17 11:30:11 -04:00
|
|
|
#endif
|
|
|
|
|
[libc++] Fix missing and incorrect push/pop macros (#79204)
We recently noticed that the unwrap_iter.h file was pushing macros, but
it was pushing them again instead of popping them at the end of the
file. This led to libc++ basically swallowing any custom definition of
these macros in user code:
#define min HELLO
#include <algorithm>
// min is not HELLO anymore, it's not defined
While investigating this issue, I noticed that our push/pop pragmas were
actually entirely wrong too. Indeed, instead of pushing macros like
`move`, we'd push `move(int, int)` in the pragma, which is not a valid
macro name. As a result, we would not actually push macros like `move`
-- instead we'd simply undefine them. This led to the following code not
working:
#define move HELLO
#include <algorithm>
// move is not HELLO anymore
Fixing the pragma push/pop incantations led to a cascade of issues
because we use identifiers like `move` in a large number of places, and
all of these headers would now need to do the push/pop dance.
This patch fixes all these issues. First, it adds a check that we don't
swallow important names like min, max, move or refresh as explained
above. This is done by augmenting the existing
system_reserved_names.gen.py test to also check that the macros are what
we expect after including each header.
Second, it fixes the push/pop pragmas to work properly and adds missing
pragmas to all the files I could detect a failure in via the newly added
test.
rdar://121365472
2024-01-25 15:48:46 -05:00
|
|
|
_LIBCPP_PUSH_MACROS
|
|
|
|
#include <__undef_macros>
|
|
|
|
|
2021-06-17 11:30:11 -04:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
2022-07-18 21:05:51 -07:00
|
|
|
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
|
2025-03-04 09:23:29 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl(
|
2022-07-18 21:05:51 -07:00
|
|
|
_ForwardIterator __first,
|
|
|
|
_ForwardIterator __last,
|
|
|
|
_Predicate __pred,
|
2021-06-17 11:30:11 -04:00
|
|
|
_Distance __len,
|
|
|
|
_Pair __p,
|
|
|
|
forward_iterator_tag __fit) {
|
2022-07-18 21:05:51 -07:00
|
|
|
using _Ops = _IterOps<_AlgPolicy>;
|
|
|
|
|
2021-06-17 11:30:11 -04:00
|
|
|
// *__first is known to be false
|
|
|
|
// __len >= 1
|
|
|
|
if (__len == 1)
|
|
|
|
return __first;
|
|
|
|
if (__len == 2) {
|
|
|
|
_ForwardIterator __m = __first;
|
|
|
|
if (__pred(*++__m)) {
|
2022-07-18 21:05:51 -07:00
|
|
|
_Ops::iter_swap(__first, __m);
|
2021-06-17 11:30:11 -04:00
|
|
|
return __m;
|
|
|
|
}
|
|
|
|
return __first;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2021-06-17 11:30:11 -04:00
|
|
|
if (__len <= __p.second) { // The buffer is big enough to use
|
|
|
|
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
|
|
|
|
__destruct_n __d(0);
|
|
|
|
unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
|
|
|
|
// Move the falses into the temporary buffer, and the trues to the front of the line
|
|
|
|
// Update __first to always point to the end of the trues
|
|
|
|
value_type* __t = __p.first;
|
2025-03-04 09:23:29 +08:00
|
|
|
std::__construct_at(__t, _Ops::__iter_move(__first));
|
2021-06-17 11:30:11 -04:00
|
|
|
__d.template __incr<value_type>();
|
2023-12-18 14:01:33 -05:00
|
|
|
++__t;
|
2021-06-17 11:30:11 -04:00
|
|
|
_ForwardIterator __i = __first;
|
|
|
|
while (++__i != __last) {
|
|
|
|
if (__pred(*__i)) {
|
2022-07-18 21:05:51 -07:00
|
|
|
*__first = _Ops::__iter_move(__i);
|
2021-06-17 11:30:11 -04:00
|
|
|
++__first;
|
2023-12-18 14:01:33 -05:00
|
|
|
} else {
|
2025-03-04 09:23:29 +08:00
|
|
|
std::__construct_at(__t, _Ops::__iter_move(__i));
|
2021-06-17 11:30:11 -04:00
|
|
|
__d.template __incr<value_type>();
|
|
|
|
++__t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// All trues now at start of range, all falses in buffer
|
|
|
|
// Move falses back into range, but don't mess up __first which points to first false
|
|
|
|
__i = __first;
|
|
|
|
for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
|
2022-07-18 21:05:51 -07:00
|
|
|
*__i = _Ops::__iter_move(__t2);
|
2021-06-17 11:30:11 -04:00
|
|
|
// __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer
|
|
|
|
return __first;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2021-06-17 11:30:11 -04:00
|
|
|
// Else not enough buffer, do in place
|
|
|
|
// __len >= 3
|
|
|
|
_ForwardIterator __m = __first;
|
|
|
|
_Distance __len2 = __len / 2; // __len2 >= 2
|
2022-07-18 21:05:51 -07:00
|
|
|
_Ops::advance(__m, __len2);
|
2021-06-17 11:30:11 -04:00
|
|
|
// recurse on [__first, __m), *__first know to be false
|
|
|
|
// F?????????????????
|
2023-12-18 14:01:33 -05:00
|
|
|
// f m l
|
2022-07-18 21:05:51 -07:00
|
|
|
_ForwardIterator __first_false =
|
|
|
|
std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m, __pred, __len2, __p, __fit);
|
2021-06-17 11:30:11 -04:00
|
|
|
// TTTFFFFF??????????
|
|
|
|
// f ff m l
|
|
|
|
// recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true
|
|
|
|
_ForwardIterator __m1 = __m;
|
|
|
|
_ForwardIterator __second_false = __last;
|
|
|
|
_Distance __len_half = __len - __len2;
|
|
|
|
while (__pred(*__m1)) {
|
|
|
|
if (++__m1 == __last)
|
|
|
|
goto __second_half_done;
|
|
|
|
--__len_half;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2021-06-17 11:30:11 -04:00
|
|
|
// TTTFFFFFTTTF??????
|
|
|
|
// f ff m m1 l
|
2022-07-18 21:05:51 -07:00
|
|
|
__second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __fit);
|
2021-06-17 11:30:11 -04:00
|
|
|
__second_half_done:
|
|
|
|
// TTTFFFFFTTTTTFFFFF
|
|
|
|
// f ff m sf l
|
2022-08-03 16:04:14 -07:00
|
|
|
return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
|
2021-06-17 11:30:11 -04:00
|
|
|
// TTTTTTTTFFFFFFFFFF
|
|
|
|
// |
|
|
|
|
}
|
|
|
|
|
2022-07-18 21:05:51 -07:00
|
|
|
template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
|
2025-03-04 09:23:29 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
|
2022-07-18 21:05:51 -07:00
|
|
|
__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) {
|
2023-06-15 08:40:42 -07:00
|
|
|
typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
|
|
|
|
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
|
|
|
|
|
|
|
|
const difference_type __alloc_limit = 3; // might want to make this a function of trivial assignment
|
2021-06-17 11:30:11 -04:00
|
|
|
// Either prove all true and return __first or point to first false
|
|
|
|
while (true) {
|
|
|
|
if (__first == __last)
|
|
|
|
return __first;
|
|
|
|
if (!__pred(*__first))
|
|
|
|
break;
|
|
|
|
++__first;
|
|
|
|
}
|
|
|
|
// We now have a reduced range [__first, __last)
|
|
|
|
// *__first is known to be false
|
2022-07-18 21:05:51 -07:00
|
|
|
difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last);
|
2024-09-16 23:53:05 +08:00
|
|
|
__unique_temporary_buffer<value_type> __unique_buf;
|
2023-06-29 18:09:58 -04:00
|
|
|
pair<value_type*, ptrdiff_t> __p(0, 0);
|
2021-06-17 11:30:11 -04:00
|
|
|
if (__len >= __alloc_limit) {
|
2024-09-16 23:53:05 +08:00
|
|
|
__unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
|
|
|
|
__p.first = __unique_buf.get();
|
|
|
|
__p.second = __unique_buf.get_deleter().__count_;
|
2023-06-29 18:09:58 -04:00
|
|
|
}
|
2022-07-18 21:05:51 -07:00
|
|
|
return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
|
2023-06-29 18:09:58 -04:00
|
|
|
std::move(__first), std::move(__last), __pred, __len, __p, forward_iterator_tag());
|
2021-06-17 11:30:11 -04:00
|
|
|
}
|
|
|
|
|
2022-07-18 21:05:51 -07:00
|
|
|
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair>
|
2025-03-04 09:23:29 +08:00
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl(
|
2022-07-18 21:05:51 -07:00
|
|
|
_BidirectionalIterator __first,
|
|
|
|
_BidirectionalIterator __last,
|
|
|
|
_Predicate __pred,
|
2021-06-17 11:30:11 -04:00
|
|
|
_Distance __len,
|
|
|
|
_Pair __p,
|
|
|
|
bidirectional_iterator_tag __bit) {
|
2022-07-18 21:05:51 -07:00
|
|
|
using _Ops = _IterOps<_AlgPolicy>;
|
|
|
|
|
2021-06-17 11:30:11 -04:00
|
|
|
// *__first is known to be false
|
|
|
|
// *__last is known to be true
|
|
|
|
// __len >= 2
|
|
|
|
if (__len == 2) {
|
2022-07-18 21:05:51 -07:00
|
|
|
_Ops::iter_swap(__first, __last);
|
2021-06-17 11:30:11 -04:00
|
|
|
return __last;
|
|
|
|
}
|
|
|
|
if (__len == 3) {
|
|
|
|
_BidirectionalIterator __m = __first;
|
|
|
|
if (__pred(*++__m)) {
|
2022-07-18 21:05:51 -07:00
|
|
|
_Ops::iter_swap(__first, __m);
|
2021-06-17 11:30:11 -04:00
|
|
|
_Ops::iter_swap(__m, __last);
|
|
|
|
return __last;
|
|
|
|
}
|
|
|
|
_Ops::iter_swap(__m, __last);
|
2022-07-18 21:05:51 -07:00
|
|
|
_Ops::iter_swap(__first, __m);
|
2021-06-17 11:30:11 -04:00
|
|
|
return __m;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2021-06-17 11:30:11 -04:00
|
|
|
if (__len <= __p.second) { // The buffer is big enough to use
|
|
|
|
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
|
|
|
|
__destruct_n __d(0);
|
|
|
|
unique_ptr<value_type, __destruct_n&> __h(__p.first, __d);
|
|
|
|
// Move the falses into the temporary buffer, and the trues to the front of the line
|
|
|
|
// Update __first to always point to the end of the trues
|
|
|
|
value_type* __t = __p.first;
|
2025-03-04 09:23:29 +08:00
|
|
|
std::__construct_at(__t, _Ops::__iter_move(__first));
|
2021-06-17 11:30:11 -04:00
|
|
|
__d.template __incr<value_type>();
|
2023-12-18 14:01:33 -05:00
|
|
|
++__t;
|
2021-06-17 11:30:11 -04:00
|
|
|
_BidirectionalIterator __i = __first;
|
|
|
|
while (++__i != __last) {
|
|
|
|
if (__pred(*__i)) {
|
2022-07-18 21:05:51 -07:00
|
|
|
*__first = _Ops::__iter_move(__i);
|
2021-06-17 11:30:11 -04:00
|
|
|
++__first;
|
2023-12-18 14:01:33 -05:00
|
|
|
} else {
|
2025-03-04 09:23:29 +08:00
|
|
|
std::__construct_at(__t, _Ops::__iter_move(__i));
|
2021-06-17 11:30:11 -04:00
|
|
|
__d.template __incr<value_type>();
|
|
|
|
++__t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// move *__last, known to be true
|
2022-07-18 21:05:51 -07:00
|
|
|
*__first = _Ops::__iter_move(__i);
|
2021-06-17 11:30:11 -04:00
|
|
|
__i = ++__first;
|
|
|
|
// All trues now at start of range, all falses in buffer
|
|
|
|
// Move falses back into range, but don't mess up __first which points to first false
|
|
|
|
for (value_type* __t2 = __p.first; __t2 < __t; ++__t2, (void)++__i)
|
2022-07-18 21:05:51 -07:00
|
|
|
*__i = _Ops::__iter_move(__t2);
|
2021-06-17 11:30:11 -04:00
|
|
|
// __h destructs moved-from values out of the temp buffer, but doesn't deallocate buffer
|
|
|
|
return __first;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2021-06-17 11:30:11 -04:00
|
|
|
// Else not enough buffer, do in place
|
|
|
|
// __len >= 4
|
|
|
|
_BidirectionalIterator __m = __first;
|
|
|
|
_Distance __len2 = __len / 2; // __len2 >= 2
|
2022-07-18 21:05:51 -07:00
|
|
|
_Ops::advance(__m, __len2);
|
2021-06-17 11:30:11 -04:00
|
|
|
// recurse on [__first, __m-1], except reduce __m-1 until *(__m-1) is true, *__first know to be false
|
|
|
|
// F????????????????T
|
2023-12-18 14:01:33 -05:00
|
|
|
// f m l
|
2021-06-17 11:30:11 -04:00
|
|
|
_BidirectionalIterator __m1 = __m;
|
|
|
|
_BidirectionalIterator __first_false = __first;
|
|
|
|
_Distance __len_half = __len2;
|
|
|
|
while (!__pred(*--__m1)) {
|
|
|
|
if (__m1 == __first)
|
|
|
|
goto __first_half_done;
|
|
|
|
--__len_half;
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2021-06-17 11:30:11 -04:00
|
|
|
// F???TFFF?????????T
|
|
|
|
// f m1 m l
|
2022-07-18 21:05:51 -07:00
|
|
|
__first_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__first, __m1, __pred, __len_half, __p, __bit);
|
2021-06-17 11:30:11 -04:00
|
|
|
__first_half_done:
|
|
|
|
// TTTFFFFF?????????T
|
|
|
|
// f ff m l
|
|
|
|
// recurse on [__m, __last], except increase __m until *(__m) is false, *__last know to be true
|
|
|
|
__m1 = __m;
|
|
|
|
_BidirectionalIterator __second_false = __last;
|
|
|
|
++__second_false;
|
|
|
|
__len_half = __len - __len2;
|
|
|
|
while (__pred(*__m1)) {
|
|
|
|
if (++__m1 == __last)
|
|
|
|
goto __second_half_done;
|
|
|
|
--__len_half;
|
|
|
|
}
|
|
|
|
// TTTFFFFFTTTF?????T
|
|
|
|
// f ff m m1 l
|
2022-07-18 21:05:51 -07:00
|
|
|
__second_false = std::__stable_partition_impl<_AlgPolicy, _Predicate&>(__m1, __last, __pred, __len_half, __p, __bit);
|
2021-06-17 11:30:11 -04:00
|
|
|
__second_half_done:
|
|
|
|
// TTTFFFFFTTTTTFFFFF
|
|
|
|
// f ff m sf l
|
2022-08-03 16:04:14 -07:00
|
|
|
return std::__rotate<_AlgPolicy>(__first_false, __m, __second_false).first;
|
2021-06-17 11:30:11 -04:00
|
|
|
// TTTTTTTTFFFFFFFFFF
|
|
|
|
// |
|
|
|
|
}
|
|
|
|
|
2022-07-18 21:05:51 -07:00
|
|
|
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
|
2025-03-04 09:23:29 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl(
|
2022-07-18 21:05:51 -07:00
|
|
|
_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) {
|
2021-06-17 11:30:11 -04:00
|
|
|
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
|
|
|
|
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
|
|
|
|
const difference_type __alloc_limit = 4; // might want to make this a function of trivial assignment
|
|
|
|
// Either prove all true and return __first or point to first false
|
|
|
|
while (true) {
|
|
|
|
if (__first == __last)
|
|
|
|
return __first;
|
|
|
|
if (!__pred(*__first))
|
|
|
|
break;
|
|
|
|
++__first;
|
|
|
|
}
|
|
|
|
// __first points to first false, everything prior to __first is already set.
|
|
|
|
// Either prove [__first, __last) is all false and return __first, or point __last to last true
|
|
|
|
do {
|
|
|
|
if (__first == --__last)
|
|
|
|
return __first;
|
|
|
|
} while (!__pred(*__last));
|
|
|
|
// We now have a reduced range [__first, __last]
|
|
|
|
// *__first is known to be false
|
|
|
|
// *__last is known to be true
|
|
|
|
// __len >= 2
|
2022-07-18 21:05:51 -07:00
|
|
|
difference_type __len = _IterOps<_AlgPolicy>::distance(__first, __last) + 1;
|
2024-09-16 23:53:05 +08:00
|
|
|
__unique_temporary_buffer<value_type> __unique_buf;
|
2023-06-29 18:09:58 -04:00
|
|
|
pair<value_type*, ptrdiff_t> __p(0, 0);
|
2021-06-17 11:30:11 -04:00
|
|
|
if (__len >= __alloc_limit) {
|
2024-09-16 23:53:05 +08:00
|
|
|
__unique_buf = std::__allocate_unique_temporary_buffer<value_type>(__len);
|
|
|
|
__p.first = __unique_buf.get();
|
|
|
|
__p.second = __unique_buf.get_deleter().__count_;
|
2023-06-29 18:09:58 -04:00
|
|
|
}
|
2022-07-18 21:05:51 -07:00
|
|
|
return std::__stable_partition_impl<_AlgPolicy, _Predicate&>(
|
2023-06-29 18:09:58 -04:00
|
|
|
std::move(__first), std::move(__last), __pred, __len, __p, bidirectional_iterator_tag());
|
2022-07-18 21:05:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory>
|
2025-03-04 09:23:29 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition(
|
2022-07-18 21:05:51 -07:00
|
|
|
_ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
|
2022-09-06 00:33:34 +02:00
|
|
|
return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
|
2022-07-18 21:05:51 -07:00
|
|
|
std::move(__first), std::move(__last), __pred, __iter_category);
|
2021-06-17 11:30:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class _ForwardIterator, class _Predicate>
|
2025-03-04 09:23:29 +08:00
|
|
|
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
|
2021-06-17 11:30:11 -04:00
|
|
|
stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
|
2022-07-18 21:05:51 -07:00
|
|
|
using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
|
|
|
|
return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>(
|
|
|
|
std::move(__first), std::move(__last), __pred, _IterCategory());
|
2021-06-17 11:30:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
[libc++] Fix missing and incorrect push/pop macros (#79204)
We recently noticed that the unwrap_iter.h file was pushing macros, but
it was pushing them again instead of popping them at the end of the
file. This led to libc++ basically swallowing any custom definition of
these macros in user code:
#define min HELLO
#include <algorithm>
// min is not HELLO anymore, it's not defined
While investigating this issue, I noticed that our push/pop pragmas were
actually entirely wrong too. Indeed, instead of pushing macros like
`move`, we'd push `move(int, int)` in the pragma, which is not a valid
macro name. As a result, we would not actually push macros like `move`
-- instead we'd simply undefine them. This led to the following code not
working:
#define move HELLO
#include <algorithm>
// move is not HELLO anymore
Fixing the pragma push/pop incantations led to a cascade of issues
because we use identifiers like `move` in a large number of places, and
all of these headers would now need to do the push/pop dance.
This patch fixes all these issues. First, it adds a check that we don't
swallow important names like min, max, move or refresh as explained
above. This is done by augmenting the existing
system_reserved_names.gen.py test to also check that the macros are what
we expect after including each header.
Second, it fixes the push/pop pragmas to work properly and adds missing
pragmas to all the files I could detect a failure in via the newly added
test.
rdar://121365472
2024-01-25 15:48:46 -05:00
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
|
2021-06-17 11:30:11 -04:00
|
|
|
#endif // _LIBCPP___ALGORITHM_STABLE_PARTITION_H
|