Skip to content

Commit f466cf6

Browse files
Partially implement P3697R1
1 parent f015db5 commit f466cf6

File tree

5 files changed

+459
-38
lines changed

5 files changed

+459
-38
lines changed

stl/inc/iterator

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ public:
886886
constexpr common_iterator(const common_iterator<_OIter, _OSe>& _Right)
887887
noexcept(is_nothrow_constructible_v<_Iter, const _OIter&>
888888
&& is_nothrow_constructible_v<_Se, const _OSe&>) // strengthened
889-
: _Val{_Right._Get_val()} {}
889+
: _Val{_Right._Get_val_for_hardened_construction()} {}
890890

891891
template <class _OIter, class _OSe>
892892
requires convertible_to<const _OIter&, _Iter> && convertible_to<const _OSe&, _Se>
@@ -895,25 +895,30 @@ public:
895895
noexcept(is_nothrow_constructible_v<_Iter, const _OIter&> && is_nothrow_constructible_v<_Se, const _OSe&>
896896
&& is_nothrow_assignable_v<_Iter&, const _OIter&>
897897
&& is_nothrow_assignable_v<_Se&, const _OSe&>) /* strengthened */ {
898-
_Val = _Right._Get_val();
898+
auto& _Right_val = _Right._Get_val();
899+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
900+
_STL_VERIFY(_Right_val._Contains != _Variantish_state::_Nothing,
901+
"common_iterator can only be assigned from if it holds a value");
902+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
903+
_Val = _Right_val;
899904
return *this;
900905
}
901906

902907
_NODISCARD constexpr decltype(auto) operator*() {
903-
#if _ITERATOR_DEBUG_LEVEL != 0
908+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
904909
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
905910
"common_iterator can only be dereferenced if it holds an iterator");
906-
#endif // _ITERATOR_DEBUG_LEVEL != 0
911+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
907912
return *_Val._Get_first();
908913
}
909914

910915
_NODISCARD constexpr decltype(auto) operator*() const
911916
requires _Dereferenceable<const _Iter>
912917
{
913-
#if _ITERATOR_DEBUG_LEVEL != 0
918+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
914919
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
915920
"common_iterator can only be dereferenced if it holds an iterator");
916-
#endif // _ITERATOR_DEBUG_LEVEL != 0
921+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
917922
return *_Val._Get_first();
918923
}
919924

@@ -922,10 +927,10 @@ public:
922927
&& (_Has_member_arrow<const _Iter&> || is_reference_v<iter_reference_t<_Iter>>
923928
|| constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>>)
924929
{
925-
#if _ITERATOR_DEBUG_LEVEL != 0
930+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
926931
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
927932
"common_iterator can only be dereferenced if it holds an iterator");
928-
#endif // _ITERATOR_DEBUG_LEVEL != 0
933+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
929934
if constexpr (_Has_member_arrow<const _Iter&> || is_pointer_v<_Iter>) {
930935
return _Val._Get_first();
931936
} else if constexpr (is_reference_v<iter_reference_t<_Iter>>) {
@@ -948,19 +953,19 @@ public:
948953
}
949954

950955
constexpr common_iterator& operator++() {
951-
#if _ITERATOR_DEBUG_LEVEL != 0
956+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
952957
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
953958
"common_iterator can only be incremented if it holds an iterator");
954-
#endif // _ITERATOR_DEBUG_LEVEL != 0
959+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
955960
++_Val._Get_first();
956961
return *this;
957962
}
958963

959964
constexpr decltype(auto) operator++(int) {
960-
#if _ITERATOR_DEBUG_LEVEL != 0
965+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
961966
_STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
962967
"common_iterator can only be incremented if it holds an iterator");
963-
#endif // _ITERATOR_DEBUG_LEVEL != 0
968+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
964969
if constexpr (forward_iterator<_Iter>) {
965970
common_iterator _Tmp = *this;
966971
++_Val._Get_first();
@@ -990,11 +995,11 @@ public:
990995
_NODISCARD friend constexpr bool operator==(
991996
const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
992997
auto& _Right_val = _Right._Get_val();
993-
#if _ITERATOR_DEBUG_LEVEL != 0
998+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
994999
_STL_VERIFY(
9951000
_Left._Val._Contains != _Variantish_state::_Nothing && _Right_val._Contains != _Variantish_state::_Nothing,
9961001
"common_iterators can only be compared if both hold a value");
997-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1002+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
9981003

9991004
if (_Left._Val._Contains == _Variantish_state::_Holds_first) {
10001005
if (_Right_val._Contains == _Variantish_state::_Holds_first) {
@@ -1020,11 +1025,11 @@ public:
10201025
_NODISCARD friend constexpr iter_difference_t<_OIter> operator-(
10211026
const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
10221027
auto& _Right_val = _Right._Get_val();
1023-
#if _ITERATOR_DEBUG_LEVEL != 0
1028+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10241029
_STL_VERIFY(
10251030
_Left._Val._Contains != _Variantish_state::_Nothing && _Right_val._Contains != _Variantish_state::_Nothing,
10261031
"Cannot take difference of valueless common_iterators");
1027-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1032+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10281033

10291034
if (_Left._Val._Contains == _Variantish_state::_Holds_first) {
10301035
if (_Right_val._Contains == _Variantish_state::_Holds_first) {
@@ -1045,22 +1050,22 @@ public:
10451050
noexcept(noexcept(_RANGES iter_move(_Right._Val._Get_first())))
10461051
requires input_iterator<_Iter>
10471052
{
1048-
#if _ITERATOR_DEBUG_LEVEL != 0
1053+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10491054
_STL_VERIFY(_Right._Val._Contains == _Variantish_state::_Holds_first,
10501055
"can only iter_move from common_iterator if it holds an iterator");
1051-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1056+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10521057
return _RANGES iter_move(_Right._Val._Get_first());
10531058
}
10541059

10551060
template <indirectly_swappable<_Iter> _OIter, class _OSe>
10561061
friend constexpr void iter_swap(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right)
10571062
noexcept(noexcept(_RANGES iter_swap(_Left._Val._Get_first(), _Right._Get_val()._Get_first()))) {
10581063
auto& _Right_val = _Right._Get_val();
1059-
#if _ITERATOR_DEBUG_LEVEL != 0
1064+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10601065
_STL_VERIFY(_Left._Val._Contains == _Variantish_state::_Holds_first
10611066
&& _Right_val._Contains == _Variantish_state::_Holds_first,
10621067
"can only iter_swap common_iterators if both hold iterators");
1063-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1068+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10641069
return _RANGES iter_swap(_Left._Val._Get_first(), _Right_val._Get_first());
10651070
}
10661071

@@ -1071,6 +1076,14 @@ public:
10711076
return _Val;
10721077
}
10731078

1079+
_NODISCARD constexpr const _Variantish<_Iter, _Se>& _Get_val_for_hardened_construction() const noexcept {
1080+
#if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1081+
_STL_VERIFY(_Val._Contains != _Variantish_state::_Nothing,
1082+
"common_iterator can only be constructed from if it holds a value");
1083+
#endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1084+
return _Val;
1085+
}
1086+
10741087
private:
10751088
_Variantish<_Iter, _Se> _Val;
10761089
};
@@ -1153,9 +1166,9 @@ public:
11531166
constexpr counted_iterator(_Iter _Right, const iter_difference_t<_Iter> _Diff)
11541167
noexcept(is_nothrow_move_constructible_v<_Iter>) // strengthened
11551168
: _Current(_STD move(_Right)), _Length(_Diff) {
1156-
#if _ITERATOR_DEBUG_LEVEL != 0
1169+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11571170
_STL_VERIFY(_Diff >= 0, "counted_iterator requires non-negative length n");
1158-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1171+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11591172
}
11601173

11611174
template <class _Other>
@@ -1188,18 +1201,18 @@ public:
11881201

11891202
// [counted.iter.elem]
11901203
_NODISCARD constexpr decltype(auto) operator*() noexcept(noexcept(*_Current)) /* strengthened */ {
1191-
#if _ITERATOR_DEBUG_LEVEL != 0
1204+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11921205
_STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
1193-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1206+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11941207
return *_Current;
11951208
}
11961209

11971210
_NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Current)) /* strengthened */
11981211
requires _Dereferenceable<const _Iter>
11991212
{
1200-
#if _ITERATOR_DEBUG_LEVEL != 0
1213+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12011214
_STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
1202-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1215+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12031216
return *_Current;
12041217
}
12051218

@@ -1212,26 +1225,26 @@ public:
12121225
_NODISCARD constexpr decltype(auto) operator[](const iter_difference_t<_Iter> _Diff) const
12131226
requires random_access_iterator<_Iter>
12141227
{
1215-
#if _ITERATOR_DEBUG_LEVEL != 0
1228+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12161229
_STL_VERIFY(_Diff < _Length, "counted_iterator index out of range");
1217-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1230+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12181231
return _Current[_Diff];
12191232
}
12201233

12211234
// [counted.iter.nav]
12221235
constexpr counted_iterator& operator++() {
1223-
#if _ITERATOR_DEBUG_LEVEL != 0
1236+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12241237
_STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
1225-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1238+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12261239
++_Current;
12271240
--_Length;
12281241
return *this;
12291242
}
12301243

12311244
constexpr decltype(auto) operator++(int) {
1232-
#if _ITERATOR_DEBUG_LEVEL != 0
1245+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12331246
_STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
1234-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1247+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12351248
--_Length;
12361249
_TRY_BEGIN
12371250
return _Current++;
@@ -1246,9 +1259,9 @@ public:
12461259
constexpr counted_iterator operator++(int)
12471260
requires forward_iterator<_Iter>
12481261
{
1249-
#if _ITERATOR_DEBUG_LEVEL != 0
1262+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12501263
_STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
1251-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1264+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12521265
counted_iterator _Tmp = *this;
12531266
++_Current;
12541267
--_Length;
@@ -1288,9 +1301,9 @@ public:
12881301
constexpr counted_iterator& operator+=(const iter_difference_t<_Iter> _Diff)
12891302
requires random_access_iterator<_Iter>
12901303
{
1291-
#if _ITERATOR_DEBUG_LEVEL != 0
1304+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12921305
_STL_VERIFY(_Diff <= _Length, "counted_iterator seek beyond end of range");
1293-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1306+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12941307
_Current += _Diff;
12951308
_Length -= _Diff;
12961309
return *this;
@@ -1324,9 +1337,9 @@ public:
13241337
constexpr counted_iterator& operator-=(const iter_difference_t<_Iter> _Diff)
13251338
requires random_access_iterator<_Iter>
13261339
{
1327-
#if _ITERATOR_DEBUG_LEVEL != 0
1340+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13281341
_STL_VERIFY(-_Diff <= _Length, "counted_iterator decrement beyond end of range");
1329-
#endif // _ITERATOR_DEBUG_LEVEL != 0
1342+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13301343
_Current -= _Diff;
13311344
_Length += _Diff;
13321345
return *this;
@@ -1360,12 +1373,18 @@ public:
13601373
noexcept(noexcept(_RANGES iter_move(_Right._Current)))
13611374
requires input_iterator<_Iter>
13621375
{
1376+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1377+
_STL_VERIFY(_Right._Length > 0, "iter_move on a counted_iterator beyond end of range");
1378+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13631379
return _RANGES iter_move(_Right._Current);
13641380
}
13651381

13661382
template <indirectly_swappable<_Iter> _Other>
13671383
friend constexpr void iter_swap(const counted_iterator& _Left, const counted_iterator<_Other>& _Right)
13681384
noexcept(noexcept(_RANGES iter_swap(_Left._Current, _Right.base()))) {
1385+
#if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1386+
_STL_VERIFY(_Left._Length > 0 && _Right.count() > 0, "iter_swap on a counted_iterator beyond end of range");
1387+
#endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13691388
_RANGES iter_swap(_Left._Current, _Right.base());
13701389
}
13711390

stl/inc/memory

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,14 @@ public:
17981798

17991799
template <class _Ty2 = _Ty, class _Elem = element_type, enable_if_t<is_array_v<_Ty2>, int> = 0>
18001800
_NODISCARD _Elem& operator[](ptrdiff_t _Idx) const noexcept /* strengthened */ {
1801+
#if _MSVC_STL_HARDENING_SHARED_PTR_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
1802+
if constexpr (extent_v<_Ty> != 0) {
1803+
_STL_VERIFY(
1804+
_Idx >= 0 && static_cast<size_t>(_Idx) < extent_v<_Ty>, "shared_ptr<T[N]> subscript out of range");
1805+
} else {
1806+
_STL_VERIFY(_Idx >= 0, "shared_ptr<T[]> subscript out of range");
1807+
}
1808+
#endif // _MSVC_STL_HARDENING_SHARED_PTR_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
18011809
return get()[_Idx];
18021810
}
18031811

stl/inc/stacktrace

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ public:
164164

165165
_NODISCARD __declspec(noinline) static basic_stacktrace current(
166166
const size_type _Skip, size_type _Max_depth, const allocator_type& _Al = allocator_type()) noexcept {
167+
#if _MSVC_STL_HARDENING_BASIC_STACKTRACE || _ITERATOR_DEBUG_LEVEL != 0
168+
_STL_VERIFY(_Skip <= _Skip + _Max_depth, "Mathematical result of (_Skip + _Max_depth) must be representable in "
169+
"size_t (N5008 [stacktrace.basic.cons]/5).");
170+
#endif // _MSVC_STL_HARDENING_BASIC_STACKTRACE || _ITERATOR_DEBUG_LEVEL != 0
167171
_TRY_BEGIN
168172
if (_Max_depth > _Max_frames) {
169173
_Max_depth = _Max_frames;
@@ -245,6 +249,10 @@ public:
245249
}
246250

247251
_NODISCARD const_reference operator[](const size_type _Sx) const noexcept /* strengthened */ {
252+
// Bound check is otherwise performed in vector::operator[].
253+
#if _MSVC_STL_HARDENING_BASIC_STACKTRACE && !_MSVC_STL_HARDENING_VECTOR && _ITERATOR_DEBUG_LEVEL == 0
254+
_STL_VERIFY(_Sx < _Frames.size(), "basic_stacktrace subscript out of range");
255+
#endif // _MSVC_STL_HARDENING_BASIC_STACKTRACE && !_MSVC_STL_HARDENING_VECTOR && _ITERATOR_DEBUG_LEVEL == 0
248256
return _Frames[_Sx];
249257
}
250258

stl/inc/yvals.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ _EMIT_STL_ERROR(STL1006, "_CONTAINER_DEBUG_LEVEL has been removed. It was supers
170170
#define _MSVC_STL_HARDENING_ARRAY _MSVC_STL_HARDENING
171171
#endif
172172

173+
#ifndef _MSVC_STL_HARDENING_BASIC_STACKTRACE
174+
#define _MSVC_STL_HARDENING_BASIC_STACKTRACE _MSVC_STL_HARDENING
175+
#endif
176+
173177
#ifndef _MSVC_STL_HARDENING_BASIC_STRING
174178
#define _MSVC_STL_HARDENING_BASIC_STRING _MSVC_STL_HARDENING
175179
#endif
@@ -178,6 +182,14 @@ _EMIT_STL_ERROR(STL1006, "_CONTAINER_DEBUG_LEVEL has been removed. It was supers
178182
#define _MSVC_STL_HARDENING_BASIC_STRING_VIEW _MSVC_STL_HARDENING
179183
#endif
180184

185+
#ifndef _MSVC_STL_HARDENING_COMMON_ITERATOR
186+
#define _MSVC_STL_HARDENING_COMMON_ITERATOR _MSVC_STL_HARDENING
187+
#endif
188+
189+
#ifndef _MSVC_STL_HARDENING_COUNTED_ITERATOR
190+
#define _MSVC_STL_HARDENING_COUNTED_ITERATOR _MSVC_STL_HARDENING
191+
#endif
192+
181193
#ifndef _MSVC_STL_HARDENING_BITSET
182194
#define _MSVC_STL_HARDENING_BITSET _MSVC_STL_HARDENING
183195
#endif
@@ -210,6 +222,10 @@ _EMIT_STL_ERROR(STL1006, "_CONTAINER_DEBUG_LEVEL has been removed. It was supers
210222
#define _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE _MSVC_STL_HARDENING
211223
#endif
212224

225+
#ifndef _MSVC_STL_HARDENING_SHARED_PTR_ARRAY
226+
#define _MSVC_STL_HARDENING_SHARED_PTR_ARRAY _MSVC_STL_HARDENING
227+
#endif
228+
213229
#ifndef _MSVC_STL_HARDENING_SPAN
214230
#define _MSVC_STL_HARDENING_SPAN _MSVC_STL_HARDENING
215231
#endif

0 commit comments

Comments
 (0)