Skip to content

Commit bf68a59

Browse files
committed
[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
1 parent 2b8917f commit bf68a59

File tree

5 files changed

+29
-13
lines changed

5 files changed

+29
-13
lines changed

libcxx/docs/DesignDocs/DebugMode.rst

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,23 @@ user-provided comparator to assert that `!comp(y, x)` whenever `comp(x, y)`. Thi
3535
user-provided comparator to be evaluated up to twice as many times as it would be without the
3636
debug mode, and causes the library to violate some of the Standard's complexity clauses.
3737

38-
Iterator debugging checks
39-
-------------------------
40-
The library contains various assertions to check the validity of iterators used
41-
by the program. The following containers and classes support iterator debugging:
38+
Iterator bounds checking
39+
------------------------
40+
The library provides iterators that ensure they are within the bounds of their container when dereferenced.
41+
Arithmetic can be performed on these iterators to create out-of-bounds iterators, but they cannot be dereferenced
42+
when out-of-bounds. The following classes currently provide iterators that have bounds checking:
43+
44+
- ``std::string``
45+
- ``std::vector<T>`` (``T != bool``)
46+
- ``std::span``
47+
48+
.. TODO: Add support for iterator bounds checking in ``std::string_view`` and ``std::array``
49+
50+
Iterator ownership checking
51+
---------------------------
52+
The library provides iterator ownership checking, which allows catching cases where e.g.
53+
an iterator from container ``X`` is used as a position to insert into container ``Y``.
54+
The following classes support iterator ownership checking:
4255

4356
- ``std::string``
4457
- ``std::vector<T>`` (``T != bool``)
@@ -48,9 +61,6 @@ by the program. The following containers and classes support iterator debugging:
4861
- ``std::unordered_set``
4962
- ``std::unordered_multiset``
5063

51-
The remaining containers do not currently support iterator debugging.
52-
Patches welcome.
53-
5464
Randomizing unspecified behavior
5565
--------------------------------
5666
The library supports the randomization of unspecified behavior. For example, randomizing

libcxx/include/__debug

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
# define _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY
2424
#endif
2525

26+
#if defined(_LIBCPP_ENABLE_DEBUG_MODE) && !defined(_LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING)
27+
# define _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
28+
#endif
29+
2630
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
2731
# define _LIBCPP_DEBUG_ASSERT(x, m) _LIBCPP_ASSERT(::std::__libcpp_is_constant_evaluated() || (x), m)
2832
#else

libcxx/include/span

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public:
211211
using const_pointer = const _Tp *;
212212
using reference = _Tp &;
213213
using const_reference = const _Tp &;
214-
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
214+
#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
215215
using iterator = __bounded_iter<pointer>;
216216
#else
217217
using iterator = __wrap_iter<pointer>;
@@ -355,14 +355,14 @@ public:
355355

356356
// [span.iter], span iterator support
357357
_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept {
358-
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
358+
#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
359359
return std::__make_bounded_iter(data(), data(), data() + size());
360360
#else
361361
return iterator(this, data());
362362
#endif
363363
}
364364
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept {
365-
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
365+
#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
366366
return std::__make_bounded_iter(data() + size(), data(), data() + size());
367367
#else
368368
return iterator(this, data() + size());
@@ -394,7 +394,7 @@ public:
394394
using const_pointer = const _Tp *;
395395
using reference = _Tp &;
396396
using const_reference = const _Tp &;
397-
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
397+
#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
398398
using iterator = __bounded_iter<pointer>;
399399
#else
400400
using iterator = __wrap_iter<pointer>;
@@ -522,14 +522,14 @@ public:
522522

523523
// [span.iter], span iterator support
524524
_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept {
525-
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
525+
#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
526526
return std::__make_bounded_iter(data(), data(), data() + size());
527527
#else
528528
return iterator(this, data());
529529
#endif
530530
}
531531
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept {
532-
#ifdef _LIBCPP_ENABLE_DEBUG_MODE
532+
#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
533533
return std::__make_bounded_iter(data() + size(), data(), data() + size());
534534
#else
535535
return iterator(this, data() + size());

libcxx/include/string

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ public:
682682
"[allocator.requirements] states that rebinding an allocator to the same type should result in the "
683683
"original allocator");
684684

685+
// TODO: Implement iterator bounds checking without requiring the global database.
685686
typedef __wrap_iter<pointer> iterator;
686687
typedef __wrap_iter<const_pointer> const_iterator;
687688
typedef std::reverse_iterator<iterator> reverse_iterator;

libcxx/include/vector

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ public:
350350
typedef typename __alloc_traits::difference_type difference_type;
351351
typedef typename __alloc_traits::pointer pointer;
352352
typedef typename __alloc_traits::const_pointer const_pointer;
353+
// TODO: Implement iterator bounds checking without requiring the global database.
353354
typedef __wrap_iter<pointer> iterator;
354355
typedef __wrap_iter<const_pointer> const_iterator;
355356
typedef std::reverse_iterator<iterator> reverse_iterator;

0 commit comments

Comments
 (0)