forked from OSchip/llvm-project
Revert "Revert "[libc++] ADL-proof <vector> by adding _VSTD:: qualification on calls.""
This reverts commit620adacf87
. Fix: unsupport C++03 for the new test, define helpers before __swap_allocator (1) Add _VSTD:: qualification to __swap_allocator. (2) Add _VSTD:: qualification consistently to __to_address. (3) Add some more missing _VSTD:: to <vector>, with a regression test. This part is cleanup afterd9a4f936d0
. Note that a vector whose allocator actually runs afoul of any of these ADL calls will likely also run afoul of simple things like `v1 == v2` (which is also an ADL call). But, still, libc++ should be consistent in qualifying function calls wherever possible. Relevant blog post: https://quuxplusone.github.io/blog/2019/09/26/uglification-doesnt-stop-adl/ Differential Revision: https://reviews.llvm.org/D91708
This commit is contained in:
parent
553e364194
commit
6e965df605
|
@ -2728,9 +2728,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
|
|||
__u.__bucket_list_.reset(__npp);
|
||||
}
|
||||
_VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
|
||||
__swap_allocator(__bucket_list_.get_deleter().__alloc(),
|
||||
_VSTD::__swap_allocator(__bucket_list_.get_deleter().__alloc(),
|
||||
__u.__bucket_list_.get_deleter().__alloc());
|
||||
__swap_allocator(__node_alloc(), __u.__node_alloc());
|
||||
_VSTD::__swap_allocator(__node_alloc(), __u.__node_alloc());
|
||||
_VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
|
||||
__p2_.swap(__u.__p2_);
|
||||
__p3_.swap(__u.__p3_);
|
||||
|
|
|
@ -279,7 +279,7 @@ void
|
|||
__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type)
|
||||
{
|
||||
while (__begin_ != __new_begin)
|
||||
__alloc_traits::destroy(__alloc(), __to_address(__begin_++));
|
||||
__alloc_traits::destroy(__alloc(), _VSTD::__to_address(__begin_++));
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
|
@ -296,7 +296,7 @@ void
|
|||
__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT
|
||||
{
|
||||
while (__new_last != __end_)
|
||||
__alloc_traits::destroy(__alloc(), __to_address(--__end_));
|
||||
__alloc_traits::destroy(__alloc(), _VSTD::__to_address(--__end_));
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
|
@ -416,7 +416,7 @@ __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x)
|
|||
_VSTD::swap(__begin_, __x.__begin_);
|
||||
_VSTD::swap(__end_, __x.__end_);
|
||||
_VSTD::swap(__end_cap(), __x.__end_cap());
|
||||
__swap_allocator(__alloc(), __x.__alloc());
|
||||
_VSTD::__swap_allocator(__alloc(), __x.__alloc());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
|
|
|
@ -1819,7 +1819,7 @@ __tree<_Tp, _Compare, _Allocator>::swap(__tree& __t)
|
|||
using _VSTD::swap;
|
||||
swap(__begin_node_, __t.__begin_node_);
|
||||
swap(__pair1_.first(), __t.__pair1_.first());
|
||||
__swap_allocator(__node_alloc(), __t.__node_alloc());
|
||||
_VSTD::__swap_allocator(__node_alloc(), __t.__node_alloc());
|
||||
__pair3_.swap(__t.__pair3_);
|
||||
if (size() == 0)
|
||||
__begin_node() = __end_node();
|
||||
|
|
|
@ -1237,7 +1237,7 @@ __deque_base<_Tp, _Allocator>::swap(__deque_base& __c)
|
|||
__map_.swap(__c.__map_);
|
||||
_VSTD::swap(__start_, __c.__start_);
|
||||
_VSTD::swap(size(), __c.size());
|
||||
__swap_allocator(__alloc(), __c.__alloc());
|
||||
_VSTD::__swap_allocator(__alloc(), __c.__alloc());
|
||||
}
|
||||
|
||||
template <class _Tp, class _Allocator>
|
||||
|
@ -2376,7 +2376,7 @@ deque<_Tp, _Allocator>::__append(_ForIter __f, _ForIter __l,
|
|||
for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) {
|
||||
_ConstructTransaction __tx(this, __br);
|
||||
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__f) {
|
||||
__alloc_traits::construct(__a, std::__to_address(__tx.__pos_), *__f);
|
||||
__alloc_traits::construct(__a, _VSTD::__to_address(__tx.__pos_), *__f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2393,7 +2393,7 @@ deque<_Tp, _Allocator>::__append(size_type __n)
|
|||
for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) {
|
||||
_ConstructTransaction __tx(this, __br);
|
||||
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
|
||||
__alloc_traits::construct(__a, std::__to_address(__tx.__pos_));
|
||||
__alloc_traits::construct(__a, _VSTD::__to_address(__tx.__pos_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2410,7 +2410,7 @@ deque<_Tp, _Allocator>::__append(size_type __n, const value_type& __v)
|
|||
for (__deque_block_range __br : __deque_range(__base::end(), __base::end() + __n)) {
|
||||
_ConstructTransaction __tx(this, __br);
|
||||
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
|
||||
__alloc_traits::construct(__a, std::__to_address(__tx.__pos_), __v);
|
||||
__alloc_traits::construct(__a, _VSTD::__to_address(__tx.__pos_), __v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2708,7 +2708,7 @@ void
|
|||
deque<_Tp, _Allocator>::pop_front()
|
||||
{
|
||||
allocator_type& __a = __base::__alloc();
|
||||
__alloc_traits::destroy(__a, __to_address(*(__base::__map_.begin() +
|
||||
__alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() +
|
||||
__base::__start_ / __base::__block_size) +
|
||||
__base::__start_ % __base::__block_size));
|
||||
--__base::size();
|
||||
|
@ -2723,7 +2723,7 @@ deque<_Tp, _Allocator>::pop_back()
|
|||
_LIBCPP_ASSERT(!empty(), "deque::pop_back called for empty deque");
|
||||
allocator_type& __a = __base::__alloc();
|
||||
size_type __p = __base::size() + __base::__start_ - 1;
|
||||
__alloc_traits::destroy(__a, __to_address(*(__base::__map_.begin() +
|
||||
__alloc_traits::destroy(__a, _VSTD::__to_address(*(__base::__map_.begin() +
|
||||
__p / __base::__block_size) +
|
||||
__p % __base::__block_size));
|
||||
--__base::size();
|
||||
|
|
|
@ -603,7 +603,7 @@ __forward_list_base<_Tp, _Alloc>::swap(__forward_list_base& __x)
|
|||
__is_nothrow_swappable<__node_allocator>::value)
|
||||
#endif
|
||||
{
|
||||
__swap_allocator(__alloc(), __x.__alloc(),
|
||||
_VSTD::__swap_allocator(__alloc(), __x.__alloc(),
|
||||
integral_constant<bool, __node_traits::propagate_on_container_swap::value>());
|
||||
using _VSTD::swap;
|
||||
swap(__before_begin()->__next_, __x.__before_begin()->__next_);
|
||||
|
|
|
@ -783,7 +783,7 @@ __list_imp<_Tp, _Alloc>::swap(__list_imp& __c)
|
|||
"list::swap: Either propagate_on_container_swap must be true"
|
||||
" or the allocators must compare equal");
|
||||
using _VSTD::swap;
|
||||
__swap_allocator(__node_alloc(), __c.__node_alloc());
|
||||
_VSTD::__swap_allocator(__node_alloc(), __c.__node_alloc());
|
||||
swap(__sz(), __c.__sz());
|
||||
swap(__end_, __c.__end_);
|
||||
if (__sz() == 0)
|
||||
|
|
|
@ -4889,19 +4889,6 @@ undeclare_reachable(_Tp* __p)
|
|||
_LIBCPP_FUNC_VIS void* align(size_t __align, size_t __sz, void*& __ptr, size_t& __space);
|
||||
|
||||
// --- Helper for container swap --
|
||||
template <typename _Alloc>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_allocator(_Alloc & __a1, _Alloc & __a2)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
|
||||
#endif
|
||||
{
|
||||
__swap_allocator(__a1, __a2,
|
||||
integral_constant<bool, _VSTD::allocator_traits<_Alloc>::propagate_on_container_swap::value>());
|
||||
}
|
||||
|
||||
template <typename _Alloc>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_allocator(_Alloc & __a1, _Alloc & __a2, true_type)
|
||||
|
@ -4919,6 +4906,19 @@ template <typename _Alloc>
|
|||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
|
||||
|
||||
template <typename _Alloc>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_allocator(_Alloc & __a1, _Alloc & __a2)
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_(__is_nothrow_swappable<_Alloc>::value)
|
||||
#endif
|
||||
{
|
||||
_VSTD::__swap_allocator(__a1, __a2,
|
||||
integral_constant<bool, _VSTD::allocator_traits<_Alloc>::propagate_on_container_swap::value>());
|
||||
}
|
||||
|
||||
template <typename _Alloc, typename _Traits=allocator_traits<_Alloc> >
|
||||
struct __noexcept_move_assign_container : public integral_constant<bool,
|
||||
_Traits::propagate_on_container_move_assignment::value
|
||||
|
|
|
@ -3438,7 +3438,7 @@ basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str)
|
|||
__alloc_traits::is_always_equal::value ||
|
||||
__alloc() == __str.__alloc(), "swapping non-equal allocators");
|
||||
_VSTD::swap(__r_.first(), __str.__r_.first());
|
||||
__swap_allocator(__alloc(), __str.__alloc());
|
||||
_VSTD::__swap_allocator(__alloc(), __str.__alloc());
|
||||
}
|
||||
|
||||
// find
|
||||
|
|
|
@ -951,7 +951,7 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
|
|||
{
|
||||
|
||||
__annotate_delete();
|
||||
__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
|
||||
_VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
|
||||
_VSTD::swap(this->__begin_, __v.__begin_);
|
||||
_VSTD::swap(this->__end_, __v.__end_);
|
||||
_VSTD::swap(this->__end_cap(), __v.__end_cap());
|
||||
|
@ -966,8 +966,8 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
|
|||
{
|
||||
__annotate_delete();
|
||||
pointer __r = __v.__begin_;
|
||||
__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, __p, __v.__begin_);
|
||||
__construct_forward_with_exception_guarantees(this->__alloc(), __p, this->__end_, __v.__end_);
|
||||
_VSTD::__construct_backward_with_exception_guarantees(this->__alloc(), this->__begin_, __p, __v.__begin_);
|
||||
_VSTD::__construct_forward_with_exception_guarantees(this->__alloc(), __p, this->__end_, __v.__end_);
|
||||
_VSTD::swap(this->__begin_, __v.__begin_);
|
||||
_VSTD::swap(this->__end_, __v.__end_);
|
||||
_VSTD::swap(this->__end_cap(), __v.__end_cap());
|
||||
|
@ -1074,7 +1074,7 @@ typename enable_if
|
|||
vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n)
|
||||
{
|
||||
_ConstructTransaction __tx(*this, __n);
|
||||
__construct_range_forward(this->__alloc(), __first, __last, __tx.__pos_);
|
||||
_VSTD::__construct_range_forward(this->__alloc(), __first, __last, __tx.__pos_);
|
||||
}
|
||||
|
||||
// Default constructs __n objects starting at __end_
|
||||
|
@ -2054,7 +2054,7 @@ vector<_Tp, _Allocator>::swap(vector& __x)
|
|||
_VSTD::swap(this->__begin_, __x.__begin_);
|
||||
_VSTD::swap(this->__end_, __x.__end_);
|
||||
_VSTD::swap(this->__end_cap(), __x.__end_cap());
|
||||
__swap_allocator(this->__alloc(), __x.__alloc(),
|
||||
_VSTD::__swap_allocator(this->__alloc(), __x.__alloc(),
|
||||
integral_constant<bool,__alloc_traits::propagate_on_container_swap::value>());
|
||||
#if _LIBCPP_DEBUG_LEVEL == 2
|
||||
__get_db()->swap(this, &__x);
|
||||
|
@ -3232,7 +3232,7 @@ vector<bool, _Allocator>::swap(vector& __x)
|
|||
_VSTD::swap(this->__begin_, __x.__begin_);
|
||||
_VSTD::swap(this->__size_, __x.__size_);
|
||||
_VSTD::swap(this->__cap(), __x.__cap());
|
||||
__swap_allocator(this->__alloc(), __x.__alloc(),
|
||||
_VSTD::__swap_allocator(this->__alloc(), __x.__alloc(),
|
||||
integral_constant<bool, __alloc_traits::propagate_on_container_swap::value>());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// <vector>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct Incomplete;
|
||||
template<class T> struct Holder { T t; };
|
||||
|
||||
template<class T, class AdlTrap = Holder<Incomplete>>
|
||||
struct MyAlloc {
|
||||
using value_type = T;
|
||||
T *allocate(int n) { return std::allocator<T>().allocate(n); }
|
||||
void deallocate(T *p, int n) { return std::allocator<T>().deallocate(p, n); }
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
std::vector<int, MyAlloc<int>> v;
|
||||
std::vector<int, MyAlloc<int>> w;
|
||||
v.push_back(1);
|
||||
v.insert(v.end(), 2);
|
||||
v.insert(v.end(), w.begin(), w.end());
|
||||
v.pop_back();
|
||||
v.erase(v.begin());
|
||||
v.erase(v.begin(), v.end());
|
||||
#if TEST_STD_VER >= 14
|
||||
v.swap(w);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue