[libcxx-commits] [libcxx] bf68a59 - [libc++] Start classifying debug mode features with more granularity

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 15 08:18:27 PST 2022


Author: Louis Dionne
Date: 2022-11-15T11:18:22-05:00
New Revision: bf68a595f6f868393a231aea5f48273a81e650d9

URL: https://github.com/llvm/llvm-project/commit/bf68a595f6f868393a231aea5f48273a81e650d9
DIFF: https://github.com/llvm/llvm-project/commit/bf68a595f6f868393a231aea5f48273a81e650d9.diff

LOG: [libc++] Start classifying debug mode features with more granularity

I am starting to granularize debug-mode checks so they can be controlled
more individually. The goal is for vendors to eventually be able to select
which categories of checks they want embedded in their configuration of
the library with more granularity.

Note that this patch is a bit weird on its own because it does not touch
any of the containers that implement iterator bounds checking through the
__dereferenceable check of the legacy debug mode. However, I added TODOs
to string and vector to change that.

Differential Revision: https://reviews.llvm.org/D138033

Added: 
    

Modified: 
    libcxx/docs/DesignDocs/DebugMode.rst
    libcxx/include/__debug
    libcxx/include/span
    libcxx/include/string
    libcxx/include/vector

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/DesignDocs/DebugMode.rst b/libcxx/docs/DesignDocs/DebugMode.rst
index 9d0e78e7581bd..5c8c4900c88d4 100644
--- a/libcxx/docs/DesignDocs/DebugMode.rst
+++ b/libcxx/docs/DesignDocs/DebugMode.rst
@@ -35,10 +35,23 @@ user-provided comparator to assert that `!comp(y, x)` whenever `comp(x, y)`. Thi
 user-provided comparator to be evaluated up to twice as many times as it would be without the
 debug mode, and causes the library to violate some of the Standard's complexity clauses.
 
-Iterator debugging checks
--------------------------
-The library contains various assertions to check the validity of iterators used
-by the program. The following containers and classes support iterator debugging:
+Iterator bounds checking
+------------------------
+The library provides iterators that ensure they are within the bounds of their container when dereferenced.
+Arithmetic can be performed on these iterators to create out-of-bounds iterators, but they cannot be dereferenced
+when out-of-bounds. The following classes currently provide iterators that have bounds checking:
+
+- ``std::string``
+- ``std::vector<T>`` (``T != bool``)
+- ``std::span``
+
+.. TODO: Add support for iterator bounds checking in ``std::string_view`` and ``std::array``
+
+Iterator ownership checking
+---------------------------
+The library provides iterator ownership checking, which allows catching cases where e.g.
+an iterator from container ``X`` is used as a position to insert into container ``Y``.
+The following classes support iterator ownership checking:
 
 - ``std::string``
 - ``std::vector<T>`` (``T != bool``)
@@ -48,9 +61,6 @@ by the program. The following containers and classes support iterator debugging:
 - ``std::unordered_set``
 - ``std::unordered_multiset``
 
-The remaining containers do not currently support iterator debugging.
-Patches welcome.
-
 Randomizing unspecified behavior
 --------------------------------
 The library supports the randomization of unspecified behavior. For example, randomizing

diff  --git a/libcxx/include/__debug b/libcxx/include/__debug
index 088b9557d8660..ae0c1a5af06ee 100644
--- a/libcxx/include/__debug
+++ b/libcxx/include/__debug
@@ -23,6 +23,10 @@
 # define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY
 #endif
 
+#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING)
+# define _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
+#endif
+
 #ifdef _LIBCPP_ENABLE_DEBUG_MODE
 #   define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m)
 #else

diff  --git a/libcxx/include/span b/libcxx/include/span
index 8afd1942c1f31..23af04f388390 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -211,7 +211,7 @@ public:
     using const_pointer          = const _Tp *;
     using reference              = _Tp &;
     using const_reference        = const _Tp &;
-#ifdef _LIBCPP_ENABLE_DEBUG_MODE
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
     using iterator               = __bounded_iter<pointer>;
 #else
     using iterator               = __wrap_iter<pointer>;
@@ -355,14 +355,14 @@ public:
 
 // [span.iter], span iterator support
     _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept {
-#ifdef _LIBCPP_ENABLE_DEBUG_MODE
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
         return std::__make_bounded_iter(data(), data(), data() + size());
 #else
         return iterator(this, data());
 #endif
     }
     _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept {
-#ifdef _LIBCPP_ENABLE_DEBUG_MODE
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
         return std::__make_bounded_iter(data() + size(), data(), data() + size());
 #else
         return iterator(this, data() + size());
@@ -394,7 +394,7 @@ public:
     using const_pointer          = const _Tp *;
     using reference              = _Tp &;
     using const_reference        = const _Tp &;
-#ifdef _LIBCPP_ENABLE_DEBUG_MODE
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
     using iterator               = __bounded_iter<pointer>;
 #else
     using iterator               = __wrap_iter<pointer>;
@@ -522,14 +522,14 @@ public:
 
 // [span.iter], span iterator support
     _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept {
-#ifdef _LIBCPP_ENABLE_DEBUG_MODE
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
         return std::__make_bounded_iter(data(), data(), data() + size());
 #else
         return iterator(this, data());
 #endif
     }
     _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept {
-#ifdef _LIBCPP_ENABLE_DEBUG_MODE
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
         return std::__make_bounded_iter(data() + size(), data(), data() + size());
 #else
         return iterator(this, data() + size());

diff  --git a/libcxx/include/string b/libcxx/include/string
index 6aee5a489a754..03bb5ea8ab72d 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -682,6 +682,7 @@ public:
                   "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
                   "original allocator");
 
+    // TODO: Implement iterator bounds checking without requiring the global database.
     typedef __wrap_iter<pointer>                         iterator;
     typedef __wrap_iter<const_pointer>                   const_iterator;
     typedef std::reverse_iterator<iterator>              reverse_iterator;

diff  --git a/libcxx/include/vector b/libcxx/include/vector
index d433f0c8c1969..d9122620c00d4 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -350,6 +350,7 @@ public:
     typedef typename __alloc_traits::
diff erence_type        
diff erence_type;
     typedef typename __alloc_traits::pointer                pointer;
     typedef typename __alloc_traits::const_pointer          const_pointer;
+    // TODO: Implement iterator bounds checking without requiring the global database.
     typedef __wrap_iter<pointer>                            iterator;
     typedef __wrap_iter<const_pointer>                      const_iterator;
     typedef std::reverse_iterator<iterator>               reverse_iterator;


        


More information about the libcxx-commits mailing list