[libcxx-commits] [libcxx] [libc++][hardening] Add iterator validity checks on unordered containers (PR #80230)

David Benjamin via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 9 12:14:53 PST 2024


https://github.com/davidben updated https://github.com/llvm/llvm-project/pull/80230

>From f31eb2ed5130ad0ee29a224afdb3f0d91031c16b Mon Sep 17 00:00:00 2001
From: David Benjamin <davidben at google.com>
Date: Wed, 31 Jan 2024 21:46:52 -0500
Subject: [PATCH 1/2] [libc++][hardening] Add iterator validity checks on
 unordered containers

These are simply null checks, so use _LIBCPP_ASSERT_NON_NULL. This
allows us to restore a bunch of the old debug tests. I've extended them
to also cover the const iterators, as those run through different
codepaths than the const ones.

This does the easier (and less important) half of #80212.
---
 libcxx/include/__hash_table                   | 40 +++++++++-
 .../debug.iterator.dereference.pass.cpp       | 51 ++++++++-----
 .../debug.iterator.increment.pass.cpp         | 57 +++++++++------
 .../debug.local_iterator.dereference.pass.cpp | 47 +++++++-----
 .../debug.local_iterator.increment.pass.cpp   | 71 +++++++++++-------
 .../debug.iterator.dereference.pass.cpp       | 51 ++++++++-----
 .../debug.iterator.increment.pass.cpp         | 61 ++++++++++------
 .../debug.local_iterator.dereference.pass.cpp | 47 +++++++-----
 .../debug.local_iterator.increment.pass.cpp   | 73 ++++++++++++-------
 .../debug.iterator.dereference.pass.cpp       | 45 +++++++-----
 .../debug.iterator.increment.pass.cpp         | 63 +++++++++-------
 .../debug.local_iterator.dereference.pass.cpp | 49 +++++++------
 .../debug.local_iterator.increment.pass.cpp   | 73 +++++++++++--------
 .../debug.iterator.dereference.pass.cpp       | 45 +++++++-----
 .../debug.iterator.increment.pass.cpp         | 63 +++++++++-------
 .../debug.local_iterator.dereference.pass.cpp | 49 +++++++------
 .../debug.local_iterator.increment.pass.cpp   | 71 +++++++++++-------
 17 files changed, 585 insertions(+), 371 deletions(-)

diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 13420012006e2d..1e7ed1df5c5264 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -284,13 +284,21 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI __hash_iterator() _NOEXCEPT : __node_(nullptr) {}
 
-  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); }
+  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
+    return __node_->__upcast()->__get_value();
+  }
 
   _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
     return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
   }
 
   _LIBCPP_HIDE_FROM_ABI __hash_iterator& operator++() {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container iterator");
     __node_ = __node_->__next_;
     return *this;
   }
@@ -345,12 +353,20 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) {}
 
-  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); }
+  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+    return __node_->__upcast()->__get_value();
+  }
   _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
     return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
   }
 
   _LIBCPP_HIDE_FROM_ABI __hash_const_iterator& operator++() {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_iterator");
     __node_ = __node_->__next_;
     return *this;
   }
@@ -400,13 +416,21 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {}
 
-  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); }
+  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
+    return __node_->__upcast()->__get_value();
+  }
 
   _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
     return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
   }
 
   _LIBCPP_HIDE_FROM_ABI __hash_local_iterator& operator++() {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container local_iterator");
     __node_ = __node_->__next_;
     if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
       __node_ = nullptr;
@@ -475,13 +499,21 @@ public:
         __bucket_(__x.__bucket_),
         __bucket_count_(__x.__bucket_count_) {}
 
-  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); }
+  _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+    return __node_->__upcast()->__get_value();
+  }
 
   _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
     return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
   }
 
   _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator& operator++() {
+    _LIBCPP_ASSERT_NON_NULL(
+        __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_local_iterator");
     __node_ = __node_->__next_;
     if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
       __node_ = nullptr;
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp
index 5ea7f4d97fcc1b..f57341d64ff390 100644
--- a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <string>
@@ -20,22 +21,32 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_map<int, std::string> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
-    }
-
-    {
-        typedef std::unordered_map<int, std::string, std::hash<int>, std::equal_to<int>,
-                                   min_allocator<std::pair<const int, std::string>>> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_map<int, std::string> C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  {
+    typedef std::unordered_map<int,
+                               std::string,
+                               std::hash<int>,
+                               std::equal_to<int>,
+                               min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp
index 2ed09bc81aaa9c..84c0bedf54c389 100644
--- a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <cassert>
@@ -21,26 +22,38 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_map<int, std::string> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.begin();
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
-    }
-
-    {
-        typedef std::unordered_map<int, std::string, std::hash<int>, std::equal_to<int>,
-                                   min_allocator<std::pair<const int, std::string>>> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.begin();
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
-    }
+  {
+    typedef std::unordered_map<int, std::string> C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.begin();
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
+    C::const_iterator i2 = c.cbegin();
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  {
+    typedef std::unordered_map<int,
+                               std::string,
+                               std::hash<int>,
+                               std::equal_to<int>,
+                               min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.begin();
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
+    C::const_iterator i2 = c.cbegin();
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
 
     return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp
index 2e4e62dbb41f4b..8b47f548955600 100644
--- a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <string>
@@ -20,20 +21,30 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_map<int, std::string> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
-    }
-
-    {
-        typedef std::unordered_map<int, std::string, std::hash<int>, std::equal_to<int>,
-                                   min_allocator<std::pair<const int, std::string>>> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_map<int, std::string> C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  {
+    typedef std::unordered_map<int,
+                               std::string,
+                               std::hash<int>,
+                               std::equal_to<int>,
+                               min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp
index 28599263447a5f..8f8305833e077a 100644
--- a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment local_iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <string>
@@ -21,29 +22,45 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_map<int, std::string> C;
-        C c;
-        c.insert(std::make_pair(42, std::string()));
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
-    }
-
-    {
-        typedef std::unordered_map<int, std::string, std::hash<int>, std::equal_to<int>,
-                                   min_allocator<std::pair<const int, std::string>>> C;
-        C c({{42, std::string()}});
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_map<int, std::string> C;
+    C c;
+    c.insert(std::make_pair(42, std::string()));
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  {
+    typedef std::unordered_map<int,
+                               std::string,
+                               std::hash<int>,
+                               std::equal_to<int>,
+                               min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c({{42, std::string()}});
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp
index 3dad48b3925d12..d295a82a8a1f56 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <string>
 #include <unordered_map>
@@ -20,22 +21,32 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_multimap<int, std::string> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
-    }
-
-    {
-        typedef std::unordered_multimap<int, std::string, std::hash<int>, std::equal_to<int>,
-                                        min_allocator<std::pair<const int, std::string>>> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_multimap<int, std::string> C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  {
+    typedef std::unordered_multimap<int,
+                                    std::string,
+                                    std::hash<int>,
+                                    std::equal_to<int>,
+                                    min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp
index b02bac6022f7ce..4247edc8def97a 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <cassert>
@@ -21,26 +22,38 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_multimap<int, std::string> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.begin();
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
-    }
-
-    {
-        typedef std::unordered_multimap<int, std::string, std::hash<int>, std::equal_to<int>,
-                            min_allocator<std::pair<const int, std::string>>> C;
-        C c;
-        c.insert(std::make_pair(1, "one"));
-        C::iterator i = c.begin();
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_multimap<int, std::string> C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.begin();
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
+    C::const_iterator i2 = c.cbegin();
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  {
+    typedef std::unordered_multimap<int,
+                                    std::string,
+                                    std::hash<int>,
+                                    std::equal_to<int>,
+                                    min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c;
+    c.insert(std::make_pair(1, "one"));
+    C::iterator i = c.begin();
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container iterator");
+    C::const_iterator i2 = c.cbegin();
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp
index 9719ba58897596..7ea87964e05f0e 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <string>
@@ -20,20 +21,30 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_multimap<int, std::string> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
-    }
-
-    {
-        typedef std::unordered_multimap<int, std::string, std::hash<int>, std::equal_to<int>,
-                                        min_allocator<std::pair<const int, std::string>>> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_multimap<int, std::string> C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  {
+    typedef std::unordered_multimap<int,
+                                    std::string,
+                                    std::hash<int>,
+                                    std::equal_to<int>,
+                                    min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp
index 2f74a191e8acdb..ffa3fec0ca1f15 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment local_iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_map>
 #include <cassert>
@@ -21,30 +22,46 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef std::unordered_multimap<int, std::string> C;
-        C c;
-        c.insert(std::make_pair(42, std::string()));
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
-    }
-
-    {
-        typedef std::unordered_multimap<int, std::string, std::hash<int>, std::equal_to<int>,
-                                        min_allocator<std::pair<const int, std::string>>> C;
-        C c({{1, std::string()}});
-        c.insert(std::make_pair(42, std::string()));
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
-    }
-
-    return 0;
+  {
+    typedef std::unordered_multimap<int, std::string> C;
+    C c;
+    c.insert(std::make_pair(42, std::string()));
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  {
+    typedef std::unordered_multimap<int,
+                                    std::string,
+                                    std::hash<int>,
+                                    std::equal_to<int>,
+                                    min_allocator<std::pair<const int, std::string>>>
+        C;
+    C c({{1, std::string()}});
+    c.insert(std::make_pair(42, std::string()));
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp
index 51cb9a6bff6434..31edd6099c965b 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 
@@ -19,21 +20,27 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T> C;
-        C c(1);
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c(1);
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T> C;
+    C c(1);
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c(1);
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp
index 17b8c77aadd1da..0e0e4aab303cd3 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 #include <cassert>
@@ -20,28 +21,38 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T> C;
-        C c;
-        c.insert(42);
-        C::iterator i = c.begin();
-        assert(i != c.end());
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c({42});
-        C::iterator i = c.begin();
-        assert(i != c.end());
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T> C;
+    C c;
+    c.insert(42);
+    C::iterator i = c.begin();
+    assert(i != c.end());
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
+    C::const_iterator i2 = c.cbegin();
+    assert(i2 != c.cend());
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c({42});
+    C::iterator i = c.begin();
+    assert(i != c.end());
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
+    C::const_iterator i2 = c.cbegin();
+    assert(i2 != c.cend());
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp
index 24102a47802fdc..fe833c40bc3515 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 
@@ -19,23 +20,29 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(
-            *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(
-            *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T> C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp
index 3f70ba29715816..142c07f83c0667 100644
--- a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment local_iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 #include <cassert>
@@ -20,32 +21,44 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T> C;
-        C c;
-        c.insert(42);
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i,
-                                "Attempted to increment a non-incrementable unordered container const_local_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c({42});
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i,
-                                "Attempted to increment a non-incrementable unordered container const_local_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T> C;
+    C c;
+    c.insert(42);
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_multiset<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c({42});
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp
index 49663b4f824ae2..8464601f610462 100644
--- a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 
@@ -19,21 +20,27 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_set<T> C;
-        C c(1);
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c(1);
-        C::iterator i = c.end();
-        TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_set<T> C;
+    C c(1);
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c(1);
+    C::iterator i = c.end();
+    TEST_LIBCPP_ASSERT_FAILURE(*i, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+    C::const_iterator i2 = c.cend();
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp
index da3fbdc5a6e8dd..29446880900bc5 100644
--- a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 #include <cassert>
@@ -20,28 +21,38 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_set<T> C;
-        C c;
-        c.insert(42);
-        C::iterator i = c.begin();
-        assert(i != c.end());
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c({42});
-        C::iterator i = c.begin();
-        assert(i != c.end());
-        ++i;
-        assert(i == c.end());
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_set<T> C;
+    C c;
+    c.insert(42);
+    C::iterator i = c.begin();
+    assert(i != c.end());
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
+    C::const_iterator i2 = c.cbegin();
+    assert(i2 != c.cend());
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c({42});
+    C::iterator i = c.begin();
+    assert(i != c.end());
+    ++i;
+    assert(i == c.end());
+    TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_iterator");
+    C::const_iterator i2 = c.cbegin();
+    assert(i2 != c.cend());
+    ++i2;
+    assert(i2 == c.cend());
+    TEST_LIBCPP_ASSERT_FAILURE(++i2, "Attempted to increment a non-incrementable unordered container const_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp
index 912edc2e4bf478..7163e3735cee0d 100644
--- a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp
@@ -10,8 +10,9 @@
 
 // Dereference non-dereferenceable iterator.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 
@@ -19,23 +20,29 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_set<T> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(
-            *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c(1);
-        C::local_iterator i = c.end(0);
-        TEST_LIBCPP_ASSERT_FAILURE(
-            *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_set<T> C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c(1);
+    C::local_iterator i = c.end(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cend(0);
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i2, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
+  }
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp
index 42a62aed472ca5..c9fe5afd097020 100644
--- a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp
+++ b/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp
@@ -10,8 +10,9 @@
 
 // Increment local_iterator past end.
 
-// REQUIRES: has-unix-headers
-// UNSUPPORTED: !libcpp-has-legacy-debug-mode, c++03
+// REQUIRES: has-unix-headers, libcpp-hardening-mode={{extensive|debug}}
+// UNSUPPORTED: c++03
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
 
 #include <unordered_set>
 #include <cassert>
@@ -20,30 +21,44 @@
 #include "min_allocator.h"
 
 int main(int, char**) {
-    {
-        typedef int T;
-        typedef std::unordered_set<T> C;
-        C c;
-        c.insert(42);
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_local_iterator");
-    }
-
-    {
-        typedef int T;
-        typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
-        C c({42});
-        C::size_type b = c.bucket(42);
-        C::local_iterator i = c.begin(b);
-        assert(i != c.end(b));
-        ++i;
-        assert(i == c.end(b));
-        TEST_LIBCPP_ASSERT_FAILURE(++i, "Attempted to increment a non-incrementable unordered container const_local_iterator");
-    }
-
-    return 0;
+  {
+    typedef int T;
+    typedef std::unordered_set<T> C;
+    C c;
+    c.insert(42);
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  {
+    typedef int T;
+    typedef std::unordered_set<T, std::hash<T>, std::equal_to<T>, min_allocator<T>> C;
+    C c({42});
+    C::size_type b      = c.bucket(42);
+    C::local_iterator i = c.begin(b);
+    assert(i != c.end(b));
+    ++i;
+    assert(i == c.end(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+    C::const_local_iterator i2 = c.cbegin(b);
+    assert(i2 != c.cend(b));
+    ++i2;
+    assert(i2 == c.cend(b));
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i2, "Attempted to increment a non-incrementable unordered container const_local_iterator");
+  }
+
+  return 0;
 }

>From b1c1b527a76c4b9e462bdb75112213496a50b9e1 Mon Sep 17 00:00:00 2001
From: David Benjamin <davidben at google.com>
Date: Fri, 9 Feb 2024 15:14:26 -0500
Subject: [PATCH 2/2] Rename tests from debug.* to assert.*

---
 ....dereference.pass.cpp => assert.iterator.dereference.pass.cpp} | 0
 ...ator.increment.pass.cpp => assert.iterator.increment.pass.cpp} | 0
 ...erence.pass.cpp => assert.local_iterator.dereference.pass.cpp} | 0
 ...ncrement.pass.cpp => assert.local_iterator.increment.pass.cpp} | 0
 ....dereference.pass.cpp => assert.iterator.dereference.pass.cpp} | 0
 ...ator.increment.pass.cpp => assert.iterator.increment.pass.cpp} | 0
 ...erence.pass.cpp => assert.local_iterator.dereference.pass.cpp} | 0
 ...ncrement.pass.cpp => assert.local_iterator.increment.pass.cpp} | 0
 ....dereference.pass.cpp => assert.iterator.dereference.pass.cpp} | 0
 ...ator.increment.pass.cpp => assert.iterator.increment.pass.cpp} | 0
 ...erence.pass.cpp => assert.local_iterator.dereference.pass.cpp} | 0
 ...ncrement.pass.cpp => assert.local_iterator.increment.pass.cpp} | 0
 ....dereference.pass.cpp => assert.iterator.dereference.pass.cpp} | 0
 ...ator.increment.pass.cpp => assert.iterator.increment.pass.cpp} | 0
 ...erence.pass.cpp => assert.local_iterator.dereference.pass.cpp} | 0
 ...ncrement.pass.cpp => assert.local_iterator.increment.pass.cpp} | 0
 16 files changed, 0 insertions(+), 0 deletions(-)
 rename libcxx/test/libcxx/containers/unord/unord.map/{debug.iterator.dereference.pass.cpp => assert.iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.map/{debug.iterator.increment.pass.cpp => assert.iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.map/{debug.local_iterator.dereference.pass.cpp => assert.local_iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.map/{debug.local_iterator.increment.pass.cpp => assert.local_iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multimap/{debug.iterator.dereference.pass.cpp => assert.iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multimap/{debug.iterator.increment.pass.cpp => assert.iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multimap/{debug.local_iterator.dereference.pass.cpp => assert.local_iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multimap/{debug.local_iterator.increment.pass.cpp => assert.local_iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multiset/{debug.iterator.dereference.pass.cpp => assert.iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multiset/{debug.iterator.increment.pass.cpp => assert.iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multiset/{debug.local_iterator.dereference.pass.cpp => assert.local_iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.multiset/{debug.local_iterator.increment.pass.cpp => assert.local_iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.set/{debug.iterator.dereference.pass.cpp => assert.iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.set/{debug.iterator.increment.pass.cpp => assert.iterator.increment.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.set/{debug.local_iterator.dereference.pass.cpp => assert.local_iterator.dereference.pass.cpp} (100%)
 rename libcxx/test/libcxx/containers/unord/unord.set/{debug.local_iterator.increment.pass.cpp => assert.local_iterator.increment.pass.cpp} (100%)

diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.map/debug.iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.map/assert.iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.map/debug.local_iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.map/assert.local_iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multimap/debug.iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multimap/assert.iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multimap/debug.local_iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multimap/assert.local_iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multiset/debug.iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multiset/assert.iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.multiset/debug.local_iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.multiset/assert.local_iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.set/debug.iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.set/assert.iterator.increment.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.dereference.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.dereference.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.dereference.pass.cpp
diff --git a/libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp b/libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.increment.pass.cpp
similarity index 100%
rename from libcxx/test/libcxx/containers/unord/unord.set/debug.local_iterator.increment.pass.cpp
rename to libcxx/test/libcxx/containers/unord/unord.set/assert.local_iterator.increment.pass.cpp



More information about the libcxx-commits mailing list