Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libcxx/include/__assert
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,10 @@
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST
// clang-format on

#if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_NONE
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be really nice if these attributes could automatically be added via the _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS assertion macro instead, since we pretty much want to have this attribute on each function that has such preconditions.

# define _LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION [[_Clang::__unsafe_buffer_usage__]]
#else
# define _LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION // those are checked
#endif

#endif // _LIBCPP___ASSERT
9 changes: 7 additions & 2 deletions libcxx/include/__iterator/wrap_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#ifndef _LIBCPP___ITERATOR_WRAP_ITER_H
#define _LIBCPP___ITERATOR_WRAP_ITER_H

#include <__assert>
#include <__compare/ordering.h>
#include <__compare/three_way_comparable.h>
#include <__config>
Expand Down Expand Up @@ -57,7 +58,10 @@ class __wrap_iter {
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __wrap_iter(const __wrap_iter<_OtherIter>& __u) _NOEXCEPT
: __i_(__u.__i_) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { return *__i_; }
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This warns when hardening is disabled, but whether the checking is happening is dependent also on the checked iterator ABI flag. In this case, since the checked iterator ABI flag is off (we're using __wrap_iter) the hardening flag has no effect, so it the behaviour would always be what I would expect to be flagged as unsafe_buffer_usage, even if hardening is enabled? Or am I misunderstanding when __wrap_iter is used?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use case is when you've enabled hardening in libc++ (so you get bounds checking in span::operator[], array::operator[], etc.), but your vendor configuration -- e.g., Darwin user space -- does not enable hardening for iterators (so you can't safely use span.begin(), array.begin(), etc.), because enabling hardening for iterators would break ABI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this generate -Wunsafe-buffer-usage even if hardening is not enabled then too? The warning isn't tied to hardening. These iterators are never safe buffer usage.

operator*() const _NOEXCEPT {
return *__i_;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT {
return std::__to_address(__i_);
}
Expand Down Expand Up @@ -96,7 +100,8 @@ class __wrap_iter {
*this += -__n;
return *this;
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference
operator[](difference_type __n) const _NOEXCEPT {
return __i_[__n];
}

Expand Down
25 changes: 16 additions & 9 deletions libcxx/include/__vector/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,13 @@ class _LIBCPP_TEMPLATE_VIS vector {
//
// element access
//
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference
operator[](size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
return this->__begin_[__n];
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
operator[](size_type __n) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "vector[] index out of bounds");
return this->__begin_[__n];
}
Expand All @@ -410,19 +412,23 @@ class _LIBCPP_TEMPLATE_VIS vector {
return this->__begin_[__n];
}

_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference
front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
return *this->__begin_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty vector");
return *this->__begin_;
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference
back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
return *(this->__end_ - 1);
}
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference
back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty vector");
return *(this->__end_ - 1);
}
Expand Down Expand Up @@ -462,7 +468,7 @@ class _LIBCPP_TEMPLATE_VIS vector {
}
#endif

_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "vector::pop_back called on an empty vector");
this->__destruct_at_end(this->__end_ - 1);
}
Expand Down Expand Up @@ -1115,7 +1121,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
}

template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI
typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __position) {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
__position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator");
Expand All @@ -1126,7 +1133,7 @@ vector<_Tp, _Allocator>::erase(const_iterator __position) {
}

template <class _Tp, class _Allocator>
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator
vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
_LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range");
pointer __p = this->__begin_ + (__first - begin());
Expand Down
39 changes: 24 additions & 15 deletions libcxx/include/span
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,14 @@ public:
return span<element_type, _Count>{data() + size() - _Count, _Count};
}

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

_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
last(size_type __count) const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::last(count): count out of range");
return {data() + size() - __count, __count};
}
Expand All @@ -341,7 +343,7 @@ public:
return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
}

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

_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference
operator[](size_type __idx) const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T, N>::operator[](index): index out of range");
return __data_[__idx];
}
Expand All @@ -368,12 +371,12 @@ public:
}
# endif

_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span");
return __data_[0];
}

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

template <size_t _Count>
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count>
first() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::first<Count>(): Count out of range");
return span<element_type, _Count>{data(), _Count};
}

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

_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
first(size_type __count) const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::first(count): count out of range");
return {data(), __count};
}

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

template <size_t _Offset, size_t _Count = dynamic_extent>
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> subspan() const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count>
subspan() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range");
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count == dynamic_extent || _Count <= size() - _Offset,
"span<T>::subspan<Offset, Count>(): Offset + Count out of range");
return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
}

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

_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference
operator[](size_type __idx) const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T>::operator[](index): index out of range");
return __data_[__idx];
}
Expand All @@ -533,12 +542,12 @@ public:
}
# endif

_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span");
return __data_[0];
}

_LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::back() on empty span");
return __data_[size() - 1];
}
Expand Down
29 changes: 16 additions & 13 deletions libcxx/include/string
Original file line number Diff line number Diff line change
Expand Up @@ -1340,15 +1340,17 @@ public:
return size() == 0;
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference operator[](size_type __pos) const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference
operator[](size_type __pos) const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__pos <= size(), "string index out of bounds");
if (__builtin_constant_p(__pos) && !__fits_in_sso(__pos)) {
return *(__get_long_pointer() + __pos);
}
return *(data() + __pos);
}

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

_LIBCPP_CONSTEXPR_SINCE_CXX20 void push_back(value_type __c);
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back();
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
__erase_to_end(size() - 1);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference front() _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference
front() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty");
return *__get_pointer();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference front() const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference
front() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::front(): string is empty");
return *data();
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference back() _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference
back() _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty");
return *(__get_pointer() + size() - 1);
}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference back() const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 const_reference
back() const _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::back(): string is empty");
return *(data() + size() - 1);
}
Expand Down Expand Up @@ -3311,12 +3320,6 @@ basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_i
return __b + static_cast<difference_type>(__r);
}

template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pop_back() {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string::pop_back(): string is already empty");
__erase_to_end(size() - 1);
}

template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::clear() _NOEXCEPT {
size_type __old_size = size();
Expand Down
15 changes: 10 additions & 5 deletions libcxx/include/string_view
Original file line number Diff line number Diff line change
Expand Up @@ -403,32 +403,37 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT { return __size_ == 0; }

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

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

_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference front() const _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_reference
front() const _NOEXCEPT {
return _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "string_view::front(): string is empty"), __data_[0];
}

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

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

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

_LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void remove_suffix(size_type __n) _NOEXCEPT {
_LIBCPP_VALID_ELEMENT_ACCESS_PRECONDITION _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI void
remove_suffix(size_type __n) _NOEXCEPT {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n <= size(), "remove_suffix() can't remove more than size()");
__size_ -= __n;
}
Expand Down
Loading
Loading