Bug 1953243 - introduce gsl::Pointer and gsl::Owner semantic to some mfbt / xpcom types r=nika,xpcom-reviewers

The combination of [[gsl::Owner]], [[gsl::Pointer]] and
[[clang::lifetimebound]] attributes makes it possible for clang to
detect some basic form of lifetime issues.

Those are expressed in terms of MOZ_GSL_OWNER, MOZ_GSL_POINTER and
MOZ_LIFETIME_BOUND.

Differential Revision: https://phabricator.services.mozilla.com/D241077
This commit is contained in:
serge-sans-paille
2025-05-19 09:42:20 +00:00
committed by sguelton@mozilla.com
parent 1ca99ab9ac
commit 41e238ca0a
14 changed files with 142 additions and 85 deletions

View File

@@ -23,7 +23,7 @@ namespace mozilla::dom::binding_detail {
// or point at the buffer of an nsAString whose lifetime is longer than that of
// the FakeString.
template <typename CharT>
struct FakeString {
struct MOZ_GSL_OWNER FakeString {
using char_type = CharT;
using string_type = nsTString<CharT>;
using size_type = typename string_type::size_type;

View File

@@ -22,7 +22,7 @@
namespace mozilla {
template <typename T, size_t _Length>
class Array {
class MOZ_GSL_OWNER Array {
T mArr[_Length];
public:
@@ -39,14 +39,14 @@ class Array {
"parameter Length");
}
constexpr T& operator[](size_t aIndex) {
constexpr T& operator[](size_t aIndex) MOZ_LIFETIME_BOUND {
if (MOZ_UNLIKELY(aIndex >= Length)) {
detail::InvalidArrayIndex_CRASH(aIndex, Length);
}
return mArr[aIndex];
}
constexpr const T& operator[](size_t aIndex) const {
constexpr const T& operator[](size_t aIndex) const MOZ_LIFETIME_BOUND {
if (MOZ_UNLIKELY(aIndex >= Length)) {
detail::InvalidArrayIndex_CRASH(aIndex, Length);
}

View File

@@ -451,6 +451,39 @@
# define MOZ_NO_STACK_PROTECTOR /* no support */
#endif
/**
* MOZ_GSL_OWNER indicates that objects of the type this annotation is attached
* to own some kind of resources, generally memory.
*
* See: https://clang.llvm.org/docs/AttributeReference.html#owner
*/
#if defined(__clang__) && defined(__has_cpp_attribute)
# if __has_cpp_attribute(gsl::Owner)
# define MOZ_GSL_OWNER [[gsl::Owner]]
# else
# define MOZ_GSL_OWNER /* nothing */
# endif
#else
# define MOZ_GSL_OWNER /* nothing */
#endif
/**
* MOZ_GSL_POINTER indicates that objects of the type this annotation is
* attached to provide a non-owning view on some kind of resources, generally
* memory.
*
* See: https://clang.llvm.org/docs/AttributeReference.html#pointer
*/
#if defined(__clang__) && defined(__has_cpp_attribute)
# if __has_cpp_attribute(gsl::Pointer)
# define MOZ_GSL_POINTER [[gsl::Pointer]]
# else
# define MOZ_GSL_POINTER /* nothing */
# endif
#else
# define MOZ_GSL_POINTER /* nothing */
#endif
/**
* MOZ_LIFETIME_BOUND indicates that objects that are referred to by that
* parameter may also be referred to by the return value of the annotated

View File

@@ -250,8 +250,8 @@ class JSONWriter {
static constexpr Span<const char> scTopObjectEndString = MakeStringSpan("}");
static constexpr Span<const char> scTrueString = MakeStringSpan("true");
JSONWriteFunc& mWriter;
const UniquePtr<JSONWriteFunc> mMaybeOwnedWriter;
JSONWriteFunc& mWriter;
Vector<bool, 8> mNeedComma; // do we need a comma at depth N?
Vector<bool, 8> mNeedNewlines; // do we need newlines at depth N?
size_t mDepth; // the current nesting depth
@@ -352,8 +352,8 @@ class JSONWriter {
explicit JSONWriter(UniquePtr<JSONWriteFunc> aWriter,
CollectionStyle aStyle = MultiLineStyle)
: mWriter(*aWriter),
mMaybeOwnedWriter(std::move(aWriter)),
: mMaybeOwnedWriter(std::move(aWriter)),
mWriter(*mMaybeOwnedWriter),
mNeedComma(),
mNeedNewlines(),
mDepth(0) {
@@ -365,7 +365,7 @@ class JSONWriter {
// Returns the JSONWriteFunc passed in at creation, for temporary use. The
// JSONWriter object still owns the JSONWriteFunc.
JSONWriteFunc& WriteFunc() const { return mWriter; }
JSONWriteFunc& WriteFunc() const MOZ_LIFETIME_BOUND { return mWriter; }
// For all the following functions, the "Prints:" comment indicates what the
// basic output looks like. However, it doesn't indicate the whitespace and

View File

@@ -360,7 +360,7 @@ constexpr Maybe<U> Some(T&& aValue);
* functions |Some()| and |Nothing()|.
*/
template <class T>
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_GSL_OWNER Maybe
: private detail::MaybeStorage<T>,
public detail::Maybe_CopyMove_Enabler<T> {
template <typename, bool, bool, bool>
@@ -575,23 +575,24 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe
constexpr const T* operator->() const;
/* Returns the contents of this Maybe<T> by ref. Unsafe unless |isSome()|. */
constexpr T& ref() &;
constexpr const T& ref() const&;
constexpr T&& ref() &&;
constexpr const T&& ref() const&&;
constexpr T& ref() & MOZ_LIFETIME_BOUND;
constexpr const T& ref() const& MOZ_LIFETIME_BOUND;
constexpr T&& ref() && MOZ_LIFETIME_BOUND;
constexpr const T&& ref() const&& MOZ_LIFETIME_BOUND;
/*
* Returns the contents of this Maybe<T> by ref. If |isNothing()|, returns
* the default value provided.
*/
constexpr T& refOr(T& aDefault) {
constexpr T& refOr(T& aDefault MOZ_LIFETIME_BOUND) MOZ_LIFETIME_BOUND {
if (isSome()) {
return ref();
}
return aDefault;
}
constexpr const T& refOr(const T& aDefault) const {
constexpr const T& refOr(const T& aDefault MOZ_LIFETIME_BOUND) const
MOZ_LIFETIME_BOUND {
if (isSome()) {
return ref();
}
@@ -618,10 +619,10 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe
return aFunc();
}
constexpr T& operator*() &;
constexpr const T& operator*() const&;
constexpr T&& operator*() &&;
constexpr const T&& operator*() const&&;
constexpr T& operator*() & MOZ_LIFETIME_BOUND;
constexpr const T& operator*() const& MOZ_LIFETIME_BOUND;
constexpr T&& operator*() && MOZ_LIFETIME_BOUND;
constexpr const T&& operator*() const&& MOZ_LIFETIME_BOUND;
/* If |isSome()|, runs the provided function or functor on the contents of
* this Maybe. */

View File

@@ -365,7 +365,7 @@ class extent_type<dynamic_extent> {
* Subspan etc.
*/
template <class ElementType, size_t Extent /* = dynamic_extent */>
class Span {
class MOZ_GSL_POINTER Span {
public:
// constants and types
using element_type = ElementType;
@@ -405,12 +405,14 @@ class Span {
/**
* Constructor for pointer and length.
*/
constexpr Span(pointer aPtr, index_type aLength) : storage_(aPtr, aLength) {}
constexpr Span(pointer aPtr MOZ_LIFETIME_BOUND, index_type aLength)
: storage_(aPtr, aLength) {}
/**
* Constructor for start pointer and pointer past end.
*/
constexpr Span(pointer aStartPtr, pointer aEndPtr)
constexpr Span(pointer aStartPtr MOZ_LIFETIME_BOUND,
pointer aEndPtr MOZ_LIFETIME_BOUND)
: storage_(aStartPtr, std::distance(aStartPtr, aEndPtr)) {}
/**
@@ -438,7 +440,7 @@ class Span {
* Constructor for C array.
*/
template <size_t N>
constexpr MOZ_IMPLICIT Span(element_type (&aArr)[N])
constexpr MOZ_IMPLICIT Span(element_type (&aArr MOZ_LIFETIME_BOUND)[N])
: storage_(&aArr[0], span_details::extent_type<N>()) {}
// Implicit constructors for char* and char16_t* pointers are deleted in order
@@ -463,7 +465,8 @@ class Span {
*/
template <size_t N,
class ArrayElementType = std::remove_const_t<element_type>>
constexpr MOZ_IMPLICIT Span(std::array<ArrayElementType, N>& aArr)
constexpr MOZ_IMPLICIT Span(
std::array<ArrayElementType, N>& aArr MOZ_LIFETIME_BOUND)
: storage_(&aArr[0], span_details::extent_type<N>()) {}
/**
@@ -471,7 +474,8 @@ class Span {
*/
template <size_t N>
constexpr MOZ_IMPLICIT Span(
const std::array<std::remove_const_t<element_type>, N>& aArr)
const std::array<std::remove_const_t<element_type>, N>& aArr
MOZ_LIFETIME_BOUND)
: storage_(&aArr[0], span_details::extent_type<N>()) {}
/**
@@ -479,7 +483,8 @@ class Span {
*/
template <size_t N,
class ArrayElementType = std::remove_const_t<element_type>>
constexpr MOZ_IMPLICIT Span(mozilla::Array<ArrayElementType, N>& aArr)
constexpr MOZ_IMPLICIT Span(
mozilla::Array<ArrayElementType, N>& aArr MOZ_LIFETIME_BOUND)
: storage_(&aArr[0], span_details::extent_type<N>()) {}
/**
@@ -487,7 +492,8 @@ class Span {
*/
template <size_t N>
constexpr MOZ_IMPLICIT Span(
const mozilla::Array<std::remove_const_t<element_type>, N>& aArr)
const mozilla::Array<std::remove_const_t<element_type>, N>& aArr
MOZ_LIFETIME_BOUND)
: storage_(&aArr[0], span_details::extent_type<N>()) {}
/**
@@ -496,15 +502,17 @@ class Span {
template <size_t N, class Enum,
class ArrayElementType = std::remove_const_t<element_type>>
constexpr MOZ_IMPLICIT Span(
mozilla::EnumeratedArray<Enum, ArrayElementType, N>& aArr)
mozilla::EnumeratedArray<Enum, ArrayElementType, N>& aArr
MOZ_LIFETIME_BOUND)
: storage_(&aArr[Enum(0)], span_details::extent_type<N>()) {}
/**
* Constructor for const mozilla::EnumeratedArray.
*/
template <size_t N, class Enum>
constexpr MOZ_IMPLICIT Span(const mozilla::EnumeratedArray<
Enum, std::remove_const_t<element_type>, N>& aArr)
constexpr MOZ_IMPLICIT Span(
const mozilla::EnumeratedArray<Enum, std::remove_const_t<element_type>,
N>& aArr MOZ_LIFETIME_BOUND)
: storage_(&aArr[Enum(0)], span_details::extent_type<N>()) {}
/**
@@ -512,7 +520,8 @@ class Span {
*/
template <class ArrayElementType = std::add_pointer<element_type>,
class DeleterType>
constexpr Span(const mozilla::UniquePtr<ArrayElementType, DeleterType>& aPtr,
constexpr Span(const mozilla::UniquePtr<ArrayElementType, DeleterType>& aPtr
MOZ_LIFETIME_BOUND,
index_type aLength)
: storage_(aPtr.get(), aLength) {}

View File

@@ -187,7 +187,7 @@ struct PointerType {
* |UniquePtr&&| argument.
*/
template <typename T, class D>
class UniquePtr {
class MOZ_GSL_OWNER UniquePtr {
public:
typedef T ElementType;
typedef D DeleterType;
@@ -214,12 +214,13 @@ class UniquePtr {
/**
* Construct a UniquePtr containing |aPtr|.
*/
explicit UniquePtr(Pointer aPtr) : mTuple(aPtr, DeleterType()) {
explicit UniquePtr(Pointer aPtr MOZ_LIFETIME_BOUND)
: mTuple(aPtr, DeleterType()) {
static_assert(!std::is_pointer_v<D>, "must provide a deleter instance");
static_assert(!std::is_reference_v<D>, "must provide a deleter instance");
}
UniquePtr(Pointer aPtr,
UniquePtr(Pointer aPtr MOZ_LIFETIME_BOUND,
std::conditional_t<std::is_reference_v<D>, D, const D&> aD1)
: mTuple(aPtr, aD1) {}
@@ -273,21 +274,21 @@ class UniquePtr {
return *this;
}
std::add_lvalue_reference_t<T> operator*() const {
std::add_lvalue_reference_t<T> operator*() const MOZ_LIFETIME_BOUND {
MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr with *");
return *get();
}
Pointer operator->() const {
Pointer operator->() const MOZ_LIFETIME_BOUND {
MOZ_ASSERT(get(), "dereferencing a UniquePtr containing nullptr with ->");
return get();
}
explicit operator bool() const { return get() != nullptr; }
Pointer get() const { return ptr(); }
Pointer get() const MOZ_LIFETIME_BOUND { return ptr(); }
DeleterType& get_deleter() { return del(); }
const DeleterType& get_deleter() const { return del(); }
DeleterType& get_deleter() MOZ_LIFETIME_BOUND { return del(); }
const DeleterType& get_deleter() const MOZ_LIFETIME_BOUND { return del(); }
[[nodiscard]] Pointer release() {
Pointer p = ptr();

View File

@@ -567,7 +567,8 @@ struct VariantIndex {
* instead.
*/
template <typename... Ts>
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS
MOZ_NON_PARAM MOZ_GSL_OWNER Variant {
friend struct IPC::ParamTraits<mozilla::Variant<Ts...>>;
friend struct mozilla::ipc::IPDLParamTraits<mozilla::Variant<Ts...>>;
@@ -739,7 +740,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
/** Mutable lvalue-reference. */
template <typename T>
T& as() & {
T& as() & MOZ_LIFETIME_BOUND {
static_assert(
detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not uniquely found in this Variant's type list");
@@ -748,7 +749,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
}
template <size_t N>
typename detail::Nth<N, Ts...>::Type& as() & {
typename detail::Nth<N, Ts...>::Type& as() & MOZ_LIFETIME_BOUND {
static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>());
@@ -757,7 +758,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
/** Immutable const lvalue-reference. */
template <typename T>
const T& as() const& {
const T& as() const& MOZ_LIFETIME_BOUND {
static_assert(detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not found in this Variant's type list");
MOZ_RELEASE_ASSERT(is<T>());
@@ -765,7 +766,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
}
template <size_t N>
const typename detail::Nth<N, Ts...>::Type& as() const& {
const typename detail::Nth<N, Ts...>::Type& as() const& MOZ_LIFETIME_BOUND {
static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>());
@@ -774,7 +775,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
/** Mutable rvalue-reference. */
template <typename T>
T&& as() && {
T&& as() && MOZ_LIFETIME_BOUND {
static_assert(
detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not uniquely found in this Variant's type list");
@@ -783,7 +784,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
}
template <size_t N>
typename detail::Nth<N, Ts...>::Type&& as() && {
typename detail::Nth<N, Ts...>::Type&& as() && MOZ_LIFETIME_BOUND {
static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>());
@@ -793,7 +794,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
/** Immutable const rvalue-reference. */
template <typename T>
const T&& as() const&& {
const T&& as() const&& MOZ_LIFETIME_BOUND {
static_assert(detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not found in this Variant's type list");
MOZ_RELEASE_ASSERT(is<T>());
@@ -801,7 +802,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
}
template <size_t N>
const typename detail::Nth<N, Ts...>::Type&& as() const&& {
const typename detail::Nth<N, Ts...>::Type&& as() const&& MOZ_LIFETIME_BOUND {
static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>());

View File

@@ -339,7 +339,7 @@ struct VectorTesting;
*/
template <typename T, size_t MinInlineCapacity = 0,
class AllocPolicy = MallocAllocPolicy>
class MOZ_NON_PARAM Vector final : private AllocPolicy {
class MOZ_NON_PARAM MOZ_GSL_OWNER Vector final : private AllocPolicy {
/* utilities */
static constexpr bool kElemIsPod =
std::is_trivial_v<T> && std::is_standard_layout_v<T>;

View File

@@ -2742,7 +2742,8 @@ inline void ImplCycleCollectionIndexedContainer(nsTArray_Impl<E, Alloc>& aField,
// file for more details.
//
template <class E>
class nsTArray : public nsTArray_Impl<E, nsTArrayInfallibleAllocator> {
class MOZ_GSL_OWNER nsTArray
: public nsTArray_Impl<E, nsTArrayInfallibleAllocator> {
public:
using InfallibleAlloc = nsTArrayInfallibleAllocator;
using base_type = nsTArray_Impl<E, InfallibleAlloc>;
@@ -2963,7 +2964,7 @@ class nsTArray : public nsTArray_Impl<E, nsTArrayInfallibleAllocator> {
};
template <class E>
class CopyableTArray : public nsTArray<E> {
class MOZ_GSL_OWNER CopyableTArray : public nsTArray<E> {
public:
using nsTArray<E>::nsTArray;
@@ -3007,7 +3008,8 @@ class CopyableTArray : public nsTArray<E> {
// FallibleTArray is a fallible vector class.
//
template <class E>
class FallibleTArray : public nsTArray_Impl<E, nsTArrayFallibleAllocator> {
class MOZ_GSL_OWNER FallibleTArray
: public nsTArray_Impl<E, nsTArrayFallibleAllocator> {
public:
typedef nsTArray_Impl<E, nsTArrayFallibleAllocator> base_type;
typedef FallibleTArray<E> self_type;
@@ -3040,7 +3042,7 @@ class FallibleTArray : public nsTArray_Impl<E, nsTArrayFallibleAllocator> {
// Storing more than N elements is fine, but it will cause a heap allocation.
//
template <class E, size_t N>
class MOZ_NON_MEMMOVABLE AutoTArray : public nsTArray<E> {
class MOZ_NON_MEMMOVABLE MOZ_GSL_OWNER AutoTArray : public nsTArray<E> {
static_assert(N != 0, "AutoTArray<E, 0> should be specialized");
public:

View File

@@ -38,7 +38,7 @@ static_assert(sizeof(nsTLiteralString<char16_t>) == sizeof(nsTString<char16_t>),
/**
* A helper class that converts a UTF-16 string to ASCII in a lossy manner
*/
class NS_LossyConvertUTF16toASCII : public nsAutoCString {
class MOZ_GSL_OWNER NS_LossyConvertUTF16toASCII : public nsAutoCString {
public:
explicit NS_LossyConvertUTF16toASCII(const char16ptr_t aString) {
LossyAppendUTF16toASCII(mozilla::MakeStringSpan(aString), *this);

View File

@@ -21,7 +21,7 @@
* duration of its use.
*/
template <typename T>
class nsTDependentString : public nsTString<T> {
class MOZ_GSL_POINTER nsTDependentString : public nsTString<T> {
public:
typedef nsTDependentString<T> self_type;
typedef nsTString<T> base_string_type;
@@ -57,9 +57,11 @@ class nsTDependentString : public nsTString<T> {
* constructors
*/
nsTDependentString(const char_type* aStart, const char_type* aEnd);
nsTDependentString(const char_type* aStart MOZ_LIFETIME_BOUND,
const char_type* aEnd MOZ_LIFETIME_BOUND);
nsTDependentString(const char_type* aData, size_type aLength)
nsTDependentString(const char_type* aData MOZ_LIFETIME_BOUND,
size_type aLength)
: string_type(const_cast<char_type*>(aData), aLength,
DataFlags::TERMINATED, ClassFlags(0)) {
this->AssertValidDependentString();
@@ -67,11 +69,11 @@ class nsTDependentString : public nsTString<T> {
#if defined(MOZ_USE_CHAR16_WRAPPER)
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
nsTDependentString(char16ptr_t aData, size_type aLength)
nsTDependentString(char16ptr_t aData MOZ_LIFETIME_BOUND, size_type aLength)
: nsTDependentString(static_cast<const char16_t*>(aData), aLength) {}
#endif
explicit nsTDependentString(const char_type* aData)
explicit nsTDependentString(const char_type* aData MOZ_LIFETIME_BOUND)
: string_type(const_cast<char_type*>(aData), char_traits::length(aData),
DataFlags::TERMINATED, ClassFlags(0)) {
string_type::AssertValidDependentString();
@@ -79,11 +81,12 @@ class nsTDependentString : public nsTString<T> {
#if defined(MOZ_USE_CHAR16_WRAPPER)
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
explicit nsTDependentString(char16ptr_t aData)
explicit nsTDependentString(char16ptr_t aData MOZ_LIFETIME_BOUND)
: nsTDependentString(static_cast<const char16_t*>(aData)) {}
#endif
nsTDependentString(const string_type& aStr, index_type aStartPos)
nsTDependentString(const string_type& aStr MOZ_LIFETIME_BOUND,
index_type aStartPos)
: string_type() {
Rebind(aStr, aStartPos);
}
@@ -107,11 +110,12 @@ class nsTDependentString : public nsTString<T> {
*/
using nsTString<T>::Rebind;
void Rebind(const char_type* aData) {
void Rebind(const char_type* aData MOZ_LIFETIME_BOUND) {
Rebind(aData, char_traits::length(aData));
}
void Rebind(const char_type* aStart, const char_type* aEnd);
void Rebind(const char_type* aStart MOZ_LIFETIME_BOUND,
const char_type* aEnd MOZ_LIFETIME_BOUND);
void Rebind(const string_type&, index_type aStartPos);
private:

View File

@@ -24,7 +24,7 @@
* nsDependentCSubstring for narrow characters
*/
template <typename T>
class nsTDependentSubstring : public nsTSubstring<T> {
class MOZ_GSL_POINTER nsTDependentSubstring : public nsTSubstring<T> {
public:
typedef nsTDependentSubstring<T> self_type;
typedef nsTSubstring<T> substring_type;
@@ -67,26 +67,30 @@ class nsTDependentSubstring : public nsTSubstring<T> {
Rebind(aStr, aStartPos, aLength);
}
nsTDependentSubstring(const char_type* aData, size_type aLength)
nsTDependentSubstring(const char_type* aData MOZ_LIFETIME_BOUND,
size_type aLength)
: substring_type(const_cast<char_type*>(aData), aLength, DataFlags(0),
ClassFlags(0)) {}
explicit nsTDependentSubstring(mozilla::Span<const char_type> aData)
explicit nsTDependentSubstring(
mozilla::Span<const char_type> aData MOZ_LIFETIME_BOUND)
: nsTDependentSubstring(aData.Elements(), aData.Length()) {}
nsTDependentSubstring(const char_type* aStart, const char_type* aEnd);
nsTDependentSubstring(const char_type* aStart MOZ_LIFETIME_BOUND,
const char_type* aEnd MOZ_LIFETIME_BOUND);
#if defined(MOZ_USE_CHAR16_WRAPPER)
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
nsTDependentSubstring(char16ptr_t aData, size_type aLength)
nsTDependentSubstring(char16ptr_t aData MOZ_LIFETIME_BOUND, size_type aLength)
: nsTDependentSubstring(static_cast<const char16_t*>(aData), aLength) {}
template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
nsTDependentSubstring(char16ptr_t aStart, char16ptr_t aEnd);
nsTDependentSubstring(char16ptr_t aStart MOZ_LIFETIME_BOUND,
char16ptr_t aEnd MOZ_LIFETIME_BOUND);
#endif
nsTDependentSubstring(const const_iterator& aStart,
const const_iterator& aEnd);
nsTDependentSubstring(const const_iterator& aStart MOZ_LIFETIME_BOUND,
const const_iterator& aEnd MOZ_LIFETIME_BOUND);
// Create a nsTDependentSubstring to be bound later
nsTDependentSubstring() : substring_type() {}
@@ -129,26 +133,28 @@ inline const nsTDependentSubstring<T> Substring(
}
template <typename T>
inline const nsTDependentSubstring<T> Substring(const T* aData,
size_t aLength) {
inline const nsTDependentSubstring<T> Substring(
const T* aData MOZ_LIFETIME_BOUND, size_t aLength) {
return nsTDependentSubstring<T>(aData, aLength);
}
template <typename T>
const nsTDependentSubstring<T> Substring(const T* aStart, const T* aEnd);
const nsTDependentSubstring<T> Substring(const T* aStart MOZ_LIFETIME_BOUND,
const T* aEnd MOZ_LIFETIME_BOUND);
extern template const nsTDependentSubstring<char> Substring(const char* aStart,
const char* aEnd);
extern template const nsTDependentSubstring<char> Substring(
const char* aStart MOZ_LIFETIME_BOUND, const char* aEnd MOZ_LIFETIME_BOUND);
extern template const nsTDependentSubstring<char16_t> Substring(
const char16_t* aStart, const char16_t* aEnd);
const char16_t* aStart MOZ_LIFETIME_BOUND,
const char16_t* aEnd MOZ_LIFETIME_BOUND);
#if defined(MOZ_USE_CHAR16_WRAPPER)
inline const nsTDependentSubstring<char16_t> Substring(char16ptr_t aData,
size_t aLength);
inline const nsTDependentSubstring<char16_t> Substring(
char16ptr_t aData MOZ_LIFETIME_BOUND, size_t aLength);
const nsTDependentSubstring<char16_t> Substring(char16ptr_t aStart,
char16ptr_t aEnd);
const nsTDependentSubstring<char16_t> Substring(
char16ptr_t aStart MOZ_LIFETIME_BOUND, char16ptr_t aEnd MOZ_LIFETIME_BOUND);
#endif
template <typename T>
@@ -158,8 +164,8 @@ inline const nsTDependentSubstring<T> StringHead(const nsTSubstring<T>& aStr,
}
template <typename T>
inline const nsTDependentSubstring<T> StringTail(const nsTSubstring<T>& aStr,
size_t aCount) {
inline const nsTDependentSubstring<T> StringTail(
const nsTSubstring<T>& aStr MOZ_LIFETIME_BOUND, size_t aCount) {
return nsTDependentSubstring<T>(aStr, aStr.Length() - aCount, aCount);
}

View File

@@ -23,7 +23,7 @@
* to denote a null-terminated string.
*/
template <typename T>
class nsTString : public nsTSubstring<T> {
class MOZ_GSL_OWNER nsTString : public nsTSubstring<T> {
public:
typedef nsTString<T> self_type;
@@ -255,7 +255,7 @@ struct fmt::formatter<nsTString<Char>, Char>
* nsAutoCStringN / nsTAutoCString for narrow characters
*/
template <typename T, size_t N>
class MOZ_NON_MEMMOVABLE nsTAutoStringN : public nsTString<T> {
class MOZ_NON_MEMMOVABLE MOZ_GSL_OWNER nsTAutoStringN : public nsTString<T> {
public:
typedef nsTAutoStringN<T, N> self_type;