Skip to content

Commit f71a3d9

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

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
@@ -449,8 +449,11 @@ public:
449449
}
450450

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

456459
_LIBCPP_CONSTEXPR_SINCE_CXX14 int compare(basic_string_view __sv) const _NOEXCEPT {
@@ -675,6 +678,16 @@ public:
675678
#endif
676679

677680
private:
681+
struct __assume_valid {};
682+
683+
// This is the same as the pointer and length constructor, but it does not include additionally hardening checks. It
684+
// is intended for use within the class, when the class invariants already imply the resulting object is valid. The
685+
// compiler usually cannot apply this optimization itself, because it does not know class invariants.
686+
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
687+
basic_string_view(const _CharT* __s, size_type __len, __assume_valid) _NOEXCEPT
688+
: __data_(__s),
689+
__size_(__len) {}
690+
678691
const value_type* __data_;
679692
size_type __size_;
680693
};

0 commit comments

Comments
 (0)