diff options
author | Nikolas Klauser <nikolasklauser@berlin.de> | 2025-07-16 10:01:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-16 10:01:32 +0200 |
commit | cee679aa3f2b98b191873ecfeaa3d821a9156431 (patch) | |
tree | f81eb35a7b261d71d7c6a975f389609458fd1944 /libcxx | |
parent | 7d52b72239caba92a48e2cacbe5758e18efaed1c (diff) | |
download | llvm-cee679aa3f2b98b191873ecfeaa3d821a9156431.zip llvm-cee679aa3f2b98b191873ecfeaa3d821a9156431.tar.gz llvm-cee679aa3f2b98b191873ecfeaa3d821a9156431.tar.bz2 |
[libc++] Always initialize __tree::{,const_}iterator (#147167)
This was probably added to support https://wg21.link/n3644 but there's
no reason not to initialize the pointer in all standard modes. This is
technically an extension since n3644 only required value-initialized
iterators to be comparable, but supporting this as an extension should
be uncontroversial since it avoids potential reads of uninitialized
memory in C++03/C++11 without doing any harm.
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/include/__tree | 14 | ||||
-rw-r--r-- | libcxx/test/extensions/libcxx/always_initialize_iterators.pass.cpp | 53 |
2 files changed, 55 insertions, 12 deletions
diff --git a/libcxx/include/__tree b/libcxx/include/__tree index b3c0ece..f29b691 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -646,12 +646,7 @@ public: using reference = value_type&; using pointer = __rebind_pointer_t<_NodePtr, value_type>; - _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER >= 14 - : __ptr_(nullptr) -#endif - { - } + _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {} _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__value_; } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(__get_np()->__value_); } @@ -720,12 +715,7 @@ public: using reference = const value_type&; using pointer = __rebind_pointer_t<_NodePtr, const value_type>; - _LIBCPP_HIDE_FROM_ABI __tree_const_iterator() _NOEXCEPT -#if _LIBCPP_STD_VER >= 14 - : __ptr_(nullptr) -#endif - { - } + _LIBCPP_HIDE_FROM_ABI __tree_const_iterator() _NOEXCEPT : __ptr_(nullptr) {} private: typedef __tree_iterator<_Tp, __node_pointer, difference_type> __non_const_iterator; diff --git a/libcxx/test/extensions/libcxx/always_initialize_iterators.pass.cpp b/libcxx/test/extensions/libcxx/always_initialize_iterators.pass.cpp new file mode 100644 index 0000000..1893ca9 --- /dev/null +++ b/libcxx/test/extensions/libcxx/always_initialize_iterators.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// Make sure that that the iterator types of the associative containers is initialized even when default initialized. +// This is an extension because the standard only requires initialization when an iterator is value initialized, and +// that only since C++14. We guarantee that iterators are always initialized, even in C++11. + +#include <cassert> +#include <map> +#include <set> + +template <class Iter> +void test() { + { + Iter iter1; + Iter iter2; + assert(iter1 == iter2); + } + { + Iter iter1; + Iter iter2{}; + assert(iter1 == iter2); + } + { + Iter iter1{}; + Iter iter2; + assert(iter1 == iter2); + } +} + +template <class Container> +void test_container() { + test<typename Container::iterator>(); + test<typename Container::const_iterator>(); + test<typename Container::reverse_iterator>(); + test<typename Container::const_reverse_iterator>(); +} + +int main(int, char**) { + test_container<std::map<int, int>>(); + test_container<std::multimap<int, int>>(); + test_container<std::set<int>>(); + test_container<std::multiset<int>>(); + + return 0; +} |