Skip to content

Commit 72058ba

Browse files
committed
[libc++] Add unsafe-buffer-usage attributes to span, vector, string and string_view
This patch is a first step towards improving the integration of -Wunsafe-buffer-usage into the standard library. The patch basically flags common methods of span, vector & friends as unsafe when hardening is disabled. This allows producing a warning diagnostic when the user explicitly opts-into those with -Wunsafe-buffer-usage AND hardening is disabled. For example, indexing a span with hardening disabled and the warning enabled will now produce: <source>:644:11: warning: function introduces unsafe buffer manipulation [-Wunsafe-buffer-usage] 644 | (void)s[3]; | ^~~~ There are certainly more places in the library that could use this attribute and we can expand on it in the future, but this aims to cover the most important places and provide a direction for how to apply the same thing elsewhere. Note that an explicit anti-goal of this patch is to set a precedent for marking arbitrary library APIs with this attribute. There's a large number of APIs in the library that can potentially access pointers in unsafe way, and we should be careful to consider where it actually makes sense to apply the attribute to make sure that these diagnostics stay relevant (for users) and maintainable (for libc++). Fixes #107904
1 parent 3c464d2 commit 72058ba

File tree

10 files changed

+275
-44
lines changed

10 files changed

+275
-44
lines changed

libcxx/include/__assert

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,10 @@
115115
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
116116
// clang-format on
117117

118+
#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_NONE
119+
# define _LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION [[_Clang::__unsafe_buffer_usage__]]
120+
#else
121+
# define _LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION // those are checked
122+
#endif
123+
118124
#endif // _LIBCPP___ASSERT

libcxx/include/__iterator/wrap_iter.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef _LIBCPP___ITERATOR_WRAP_ITER_H
1111
#define _LIBCPP___ITERATOR_WRAP_ITER_H
1212

13+
#include <__assert>
1314
#include <__compare/ordering.h>
1415
#include <__compare/three_way_comparable.h>
1516
#include <__config>
@@ -57,7 +58,10 @@ class __wrap_iter {
5758
int> = 0>
5859
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_OtherIter>& __u) _NOEXCEPT
5960
: __i_(__u.__i_) {}
60-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { return *__i_; }
61+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference
62+
operator*() const _NOEXCEPT {
63+
return *__i_;
64+
}
6165
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT {
6266
return std::__to_address(__i_);
6367
}
@@ -96,7 +100,8 @@ class __wrap_iter {
96100
*this += -__n;
97101
return *this;
98102
}
99-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT {
103+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference
104+
operator[](difference_type __n) const _NOEXCEPT {
100105
return __i_[__n];
101106
}
102107

libcxx/include/__vector/vector.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,13 @@ class _LIBCPP_TEMPLATE_VIS vector {
391391
//
392392
// element access
393393
//
394-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
394+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference
395+
operator[](size_type __n) _NOEXCEPT {
395396
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
396397
return this->__begin_[__n];
397398
}
398-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const _NOEXCEPT {
399+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
400+
operator[](size_type __n) const _NOEXCEPT {
399401
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
400402
return this->__begin_[__n];
401403
}
@@ -410,19 +412,23 @@ class _LIBCPP_TEMPLATE_VIS vector {
410412
return this->__begin_[__n];
411413
}
412414

413-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
415+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference
416+
front() _NOEXCEPT {
414417
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
415418
return *this->__begin_;
416419
}
417-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
420+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
421+
front() const _NOEXCEPT {
418422
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
419423
return *this->__begin_;
420424
}
421-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
425+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference
426+
back() _NOEXCEPT {
422427
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
423428
return *(this->__end_ - 1);
424429
}
425-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
430+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
431+
back() const _NOEXCEPT {
426432
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
427433
return *(this->__end_ - 1);
428434
}
@@ -462,7 +468,7 @@ class _LIBCPP_TEMPLATE_VIS vector {
462468
}
463469
#endif
464470

465-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
471+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
466472
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
467473
this->__destruct_at_end(this->__end_ - 1);
468474
}
@@ -1115,7 +1121,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
11151121
}
11161122

11171123
template <class _Tp, class _Allocator>
1118-
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
1124+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
1125+
typename vector<_Tp, _Allocator>::iterator
11191126
vector<_Tp, _Allocator>::erase(const_iterator __position) {
11201127
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
11211128
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
@@ -1126,7 +1133,7 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
11261133
}
11271134

11281135
template <class _Tp, class _Allocator>
1129-
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
1136+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
11301137
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
11311138
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
11321139
pointer __p = this->__begin_ + (__first - begin());

libcxx/include/span

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,14 @@ public:
320320
return span<element_type, _Count>{data() + size() - _Count, _Count};
321321
}
322322

323-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept {
323+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
324+
first(size_type __count) const noexcept {
324325
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::first(count): count out of range");
325326
return {data(), __count};
326327
}
327328

328-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept {
329+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
330+
last(size_type __count) const noexcept {
329331
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::last(count): count out of range");
330332
return {data() + size() - __count, __count};
331333
}
@@ -341,7 +343,7 @@ public:
341343
return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
342344
}
343345

344-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
346+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
345347
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept {
346348
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range");
347349
if (__count == dynamic_extent)
@@ -355,7 +357,8 @@ public:
355357
_LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
356358
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return _Extent == 0; }
357359

358-
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept {
360+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference
361+
operator[](size_type __idx) const noexcept {
359362
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T, N>::operator[](index): index out of range");
360363
return __data_[__idx];
361364
}
@@ -368,12 +371,12 @@ public:
368371
}
369372
# endif
370373

371-
_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
374+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
372375
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span");
373376
return __data_[0];
374377
}
375378

376-
_LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
379+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
377380
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::back() on empty span");
378381
return __data_[size() - 1];
379382
}
@@ -477,36 +480,41 @@ public:
477480
: __data_{__other.data()}, __size_{__other.size()} {}
478481

479482
template <size_t _Count>
480-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept {
483+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count>
484+
first() const noexcept {
481485
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::first<Count>(): Count out of range");
482486
return span<element_type, _Count>{data(), _Count};
483487
}
484488

485489
template <size_t _Count>
486-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept {
490+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count>
491+
last() const noexcept {
487492
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::last<Count>(): Count out of range");
488493
return span<element_type, _Count>{data() + size() - _Count, _Count};
489494
}
490495

491-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept {
496+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
497+
first(size_type __count) const noexcept {
492498
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::first(count): count out of range");
493499
return {data(), __count};
494500
}
495501

496-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept {
502+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
503+
last(size_type __count) const noexcept {
497504
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::last(count): count out of range");
498505
return {data() + size() - __count, __count};
499506
}
500507

501508
template <size_t _Offset, size_t _Count = dynamic_extent>
502-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> subspan() const noexcept {
509+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count>
510+
subspan() const noexcept {
503511
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range");
504512
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count == dynamic_extent || _Count <= size() - _Offset,
505513
"span<T>::subspan<Offset, Count>(): Offset + Count out of range");
506514
return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
507515
}
508516

509-
constexpr span<element_type, dynamic_extent> _LIBCPP_HIDE_FROM_ABI
517+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
510518
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept {
511519
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T>::subspan(offset, count): offset out of range");
512520
if (__count == dynamic_extent)
@@ -520,7 +528,8 @@ public:
520528
_LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return __size_ * sizeof(element_type); }
521529
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return __size_ == 0; }
522530

523-
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept {
531+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference
532+
operator[](size_type __idx) const noexcept {
524533
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T>::operator[](index): index out of range");
525534
return __data_[__idx];
526535
}
@@ -533,12 +542,12 @@ public:
533542
}
534543
# endif
535544

536-
_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
545+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
537546
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span");
538547
return __data_[0];
539548
}
540549

541-
_LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
550+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
542551
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::back() on empty span");
543552
return __data_[size() - 1];
544553
}

libcxx/include/string

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,15 +1340,17 @@ public:
13401340
return size() == 0;
13411341
}
13421342

1343-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT {
1343+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference
1344+
operator[](size_type __pos) const _NOEXCEPT {
13441345
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
13451346
if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
13461347
return *(__get_long_pointer() + __pos);
13471348
}
13481349
return *(data() + __pos);
13491350
}
13501351

1351-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator[](size_type __pos) _NOEXCEPT {
1352+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference
1353+
operator[](size_type __pos) _NOEXCEPT {
13521354
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
13531355
if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
13541356
return *(__get_long_pointer() + __pos);
@@ -1446,24 +1448,31 @@ public:
14461448
# endif // _LIBCPP_CXX03_LANG
14471449

14481450
_LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c);
1449-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back();
1451+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() {
1452+
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
1453+
__erase_to_end(size() - 1);
1454+
}
14501455

1451-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT {
1456+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference
1457+
front() _NOEXCEPT {
14521458
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty");
14531459
return *__get_pointer();
14541460
}
14551461

1456-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT {
1462+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference
1463+
front() const _NOEXCEPT {
14571464
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty");
14581465
return *data();
14591466
}
14601467

1461-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT {
1468+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference
1469+
back() _NOEXCEPT {
14621470
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty");
14631471
return *(__get_pointer() + size() - 1);
14641472
}
14651473

1466-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT {
1474+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference
1475+
back() const _NOEXCEPT {
14671476
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty");
14681477
return *(data() + size() - 1);
14691478
}
@@ -3311,12 +3320,6 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_i
33113320
return __b + static_cast<difference_type>(__r);
33123321
}
33133322

3314-
template <class _CharT, class _Traits, class _Allocator>
3315-
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() {
3316-
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
3317-
__erase_to_end(size() - 1);
3318-
}
3319-
33203323
template <class _CharT, class _Traits, class _Allocator>
33213324
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT {
33223325
size_type __old_size = size();

libcxx/include/string_view

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -403,32 +403,37 @@ public:
403403
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT { return __size_ == 0; }
404404

405405
// [string.view.access], element access
406-
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __pos) const _NOEXCEPT {
406+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference
407+
operator[](size_type __pos) const _NOEXCEPT {
407408
return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos < size(), "string_view[] index out of bounds"), __data_[__pos];
408409
}
409410

410411
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference at(size_type __pos) const {
411412
return __pos >= size() ? (__throw_out_of_range("string_view::at"), __data_[0]) : __data_[__pos];
412413
}
413414

414-
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
415+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference
416+
front() const _NOEXCEPT {
415417
return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::front(): string is empty"), __data_[0];
416418
}
417419

418-
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
420+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference
421+
back() const _NOEXCEPT {
419422
return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::back(): string is empty"), __data_[__size_ - 1];
420423
}
421424

422425
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_pointer data() const _NOEXCEPT { return __data_; }
423426

424427
// [string.view.modifiers], modifiers:
425-
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void remove_prefix(size_type __n) _NOEXCEPT {
428+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void
429+
remove_prefix(size_type __n) _NOEXCEPT {
426430
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_prefix() can't remove more than size()");
427431
__data_ += __n;
428432
__size_ -= __n;
429433
}
430434

431-
_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void remove_suffix(size_type __n) _NOEXCEPT {
435+
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void
436+
remove_suffix(size_type __n) _NOEXCEPT {
432437
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_suffix() can't remove more than size()");
433438
__size_ -= __n;
434439
}

0 commit comments

Comments
 (0)