aboutsummaryrefslogtreecommitdiff
path: root/libcxx
diff options
context:
space:
mode:
authorNikolas Klauser <nikolasklauser@berlin.de>2025-07-16 10:01:32 +0200
committerGitHub <noreply@github.com>2025-07-16 10:01:32 +0200
commitcee679aa3f2b98b191873ecfeaa3d821a9156431 (patch)
treef81eb35a7b261d71d7c6a975f389609458fd1944 /libcxx
parent7d52b72239caba92a48e2cacbe5758e18efaed1c (diff)
downloadllvm-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/__tree14
-rw-r--r--libcxx/test/extensions/libcxx/always_initialize_iterators.pass.cpp53
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;
+}