This addresses the usage of `operator&` in `<vector>`.
I now added tests for the current offending cases. I wonder whether it
would be better to add one addressof test per directory and test all
possible violations. Also to guard against possible future errors?
(Note there are still more headers with the same issue.)
Reviewed By: #libc, ldionne
Differential Revision: https://reviews.llvm.org/D111961
#include <__config>
#include <__debug>
#include <__iterator/iterator_traits.h>
+#include <__memory/addressof.h>
#include <__memory/pointer_traits.h>
#include <type_traits>
: __i(__u.base())
{
#if _LIBCPP_DEBUG_LEVEL == 2
- __get_db()->__iterator_copy(this, &__u);
+ __get_db()->__iterator_copy(this, _VSTD::addressof(__u));
#endif
}
#if _LIBCPP_DEBUG_LEVEL == 2
__wrap_iter(const __wrap_iter& __x)
: __i(__x.base())
{
- __get_db()->__iterator_copy(this, &__x);
+ __get_db()->__iterator_copy(this, _VSTD::addressof(__x));
}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG
__wrap_iter& operator=(const __wrap_iter& __x)
{
- if (this != &__x)
+ if (this != _VSTD::addressof(__x))
{
- __get_db()->__iterator_copy(this, &__x);
+ __get_db()->__iterator_copy(this, _VSTD::addressof(__x));
__i = __x.__i;
}
return *this;
bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y),
+ _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)),
"Attempted to compare incomparable iterators");
#endif
return __x.base() < __y.base();
#endif // C++03
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(&__x, &__y),
+ _LIBCPP_ASSERT(__get_const_db()->__less_than_comparable(_VSTD::addressof(__x), _VSTD::addressof(__y)),
"Attempted to subtract incompatible iterators");
#endif
return __x.base() - __y.base();
{
#if _LIBCPP_DEBUG_LEVEL == 2
__get_db()->__insert_c(this);
- __get_db()->swap(this, &__x);
+ __get_db()->swap(this, _VSTD::addressof(__x));
#endif
this->__begin_ = __x.__begin_;
this->__end_ = __x.__end_;
this->__end_cap() = __x.__end_cap();
__x.__begin_ = __x.__end_ = __x.__end_cap() = nullptr;
#if _LIBCPP_DEBUG_LEVEL == 2
- __get_db()->swap(this, &__x);
+ __get_db()->swap(this, _VSTD::addressof(__x));
#endif
}
else
this->__end_cap() = __c.__end_cap();
__c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr;
#if _LIBCPP_DEBUG_LEVEL == 2
- __get_db()->swap(this, &__c);
+ __get_db()->swap(this, _VSTD::addressof(__c));
#endif
}
vector<_Tp, _Allocator>::erase(const_iterator __position)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::erase(iterator) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__first)) == this,
"vector::erase(iterator, iterator) called with an iterator not"
" referring to this vector");
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__last)) == this,
"vector::erase(iterator, iterator) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::insert(iterator, x) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::insert(iterator, x) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::emplace(iterator, x) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_reference __x)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::insert(iterator, n, x) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::insert(const_iterator __position, _InputIterator __first, _InputIterator __last)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::insert(iterator, range) called with an iterator not"
" referring to this vector");
#endif
vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __first, _ForwardIterator __last)
{
#if _LIBCPP_DEBUG_LEVEL == 2
- _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__position) == this,
+ _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(_VSTD::addressof(__position)) == this,
"vector::insert(iterator, range) called with an iterator not"
" referring to this vector");
#endif
_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);
+ __get_db()->swap(this, _VSTD::addressof(__x));
#endif
}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// vector& operator=(vector&& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> vo;
+ std::vector<operator_hijacker> v;
+ v = std::move(vo);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// vector(vector&& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ {
+ std::vector<operator_hijacker> vo{};
+ std::vector<operator_hijacker> v{std::move(vo)};
+ }
+ {
+ std::vector<operator_hijacker> vo{};
+ std::vector<operator_hijacker> v{std::move(vo), std::allocator<operator_hijacker>{}};
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.emplace(v.end());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.erase(v.end());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.erase(v.begin(), v.end());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class Iter>
+// iterator insert(const_iterator position, Iter first, Iter last);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+#include "test_iterators.h"
+
+void test() {
+ {
+ std::vector<operator_hijacker> v;
+ cpp17_input_iterator<std::vector<operator_hijacker>::iterator> i;
+ v.insert(v.end(), i, i);
+ }
+ {
+ std::vector<operator_hijacker> v;
+ v.insert(v.end(), v.begin(), v.end());
+ }
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// iterator insert(const_iterator position, value_type&& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.insert(v.end(), operator_hijacker{});
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, size_type n, const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ operator_hijacker val;
+ v.insert(v.end(), 1, val);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ operator_hijacker val;
+ v.insert(v.end(), val);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class T, class Alloc>
+// void swap(vector<T,Alloc>& x, vector<T,Alloc>& y);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> vo;
+ std::vector<operator_hijacker> v;
+ v.swap(vo);
+}