Skip to content

Commit 795a47f

Browse files
authored
Suppress a redundant hardening check in basic_string_view::substr (#91804)
Fixes #91634. This could alternatively be done with an _LIBCPP_ASSUME, after #91801 lands, but would also require #91619 be fixed first. Given the dependencies, it seemed simplest to just make a private ctor.
1 parent eb90ac5 commit 795a47f

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

libcxx/include/string_view

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,11 @@ public:
448448
}
449449

450450
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI basic_string_view substr(size_type __pos = 0, size_type __n = npos) const {
451+
// Use the `__assume_valid` form of the constructor to avoid an unnecessary check. Any substring of a view is a
452+
// valid view. In particular, `size()` is known to be smaller than `numeric_limits<difference_type>::max()`, so the
453+
// new size is also smaller. See also https://github.com/llvm/llvm-project/issues/91634.
451454
return __pos > size() ? (__throw_out_of_range("string_view::substr"), basic_string_view())
452-
: basic_string_view(data() + __pos, std::min(__n, size() - __pos));
455+
: basic_string_view(__assume_valid(), data() + __pos, std::min(__n, size() - __pos));
453456
}
454457

455458
_LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
@@ -674,6 +677,16 @@ public:
674677
#endif
675678

676679
private:
680+
struct __assume_valid {};
681+
682+
// This is the same as the pointer and length constructor, but without the additional hardening checks. It is intended
683+
// for use within the class, when the class invariants already guarantee the resulting object is valid. The compiler
684+
// usually cannot eliminate the redundant checks because it does not know class invariants.
685+
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
686+
basic_string_view(__assume_valid, const _CharT* __s, size_type __len) _NOEXCEPT
687+
: __data_(__s),
688+
__size_(__len) {}
689+
677690
const value_type* __data_;
678691
size_type __size_;
679692
};

0 commit comments

Comments
 (0)