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 // or point at the buffer of an nsAString whose lifetime is longer than that of
// the FakeString. // the FakeString.
template <typename CharT> template <typename CharT>
struct FakeString { struct MOZ_GSL_OWNER FakeString {
using char_type = CharT; using char_type = CharT;
using string_type = nsTString<CharT>; using string_type = nsTString<CharT>;
using size_type = typename string_type::size_type; using size_type = typename string_type::size_type;

View File

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

View File

@@ -451,6 +451,39 @@
# define MOZ_NO_STACK_PROTECTOR /* no support */ # define MOZ_NO_STACK_PROTECTOR /* no support */
#endif #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 * 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 * 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> scTopObjectEndString = MakeStringSpan("}");
static constexpr Span<const char> scTrueString = MakeStringSpan("true"); static constexpr Span<const char> scTrueString = MakeStringSpan("true");
JSONWriteFunc& mWriter;
const UniquePtr<JSONWriteFunc> mMaybeOwnedWriter; const UniquePtr<JSONWriteFunc> mMaybeOwnedWriter;
JSONWriteFunc& mWriter;
Vector<bool, 8> mNeedComma; // do we need a comma at depth N? Vector<bool, 8> mNeedComma; // do we need a comma at depth N?
Vector<bool, 8> mNeedNewlines; // do we need newlines at depth N? Vector<bool, 8> mNeedNewlines; // do we need newlines at depth N?
size_t mDepth; // the current nesting depth size_t mDepth; // the current nesting depth
@@ -352,8 +352,8 @@ class JSONWriter {
explicit JSONWriter(UniquePtr<JSONWriteFunc> aWriter, explicit JSONWriter(UniquePtr<JSONWriteFunc> aWriter,
CollectionStyle aStyle = MultiLineStyle) CollectionStyle aStyle = MultiLineStyle)
: mWriter(*aWriter), : mMaybeOwnedWriter(std::move(aWriter)),
mMaybeOwnedWriter(std::move(aWriter)), mWriter(*mMaybeOwnedWriter),
mNeedComma(), mNeedComma(),
mNeedNewlines(), mNeedNewlines(),
mDepth(0) { mDepth(0) {
@@ -365,7 +365,7 @@ class JSONWriter {
// Returns the JSONWriteFunc passed in at creation, for temporary use. The // Returns the JSONWriteFunc passed in at creation, for temporary use. The
// JSONWriter object still owns the JSONWriteFunc. // 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 // For all the following functions, the "Prints:" comment indicates what the
// basic output looks like. However, it doesn't indicate the whitespace and // 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()|. * functions |Some()| and |Nothing()|.
*/ */
template <class T> 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>, : private detail::MaybeStorage<T>,
public detail::Maybe_CopyMove_Enabler<T> { public detail::Maybe_CopyMove_Enabler<T> {
template <typename, bool, bool, bool> template <typename, bool, bool, bool>
@@ -575,23 +575,24 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe
constexpr const T* operator->() const; constexpr const T* operator->() const;
/* Returns the contents of this Maybe<T> by ref. Unsafe unless |isSome()|. */ /* Returns the contents of this Maybe<T> by ref. Unsafe unless |isSome()|. */
constexpr T& ref() &; constexpr T& ref() & MOZ_LIFETIME_BOUND;
constexpr const T& ref() const&; constexpr const T& ref() const& MOZ_LIFETIME_BOUND;
constexpr T&& ref() &&; constexpr T&& ref() && MOZ_LIFETIME_BOUND;
constexpr const T&& ref() const&&; constexpr const T&& ref() const&& MOZ_LIFETIME_BOUND;
/* /*
* Returns the contents of this Maybe<T> by ref. If |isNothing()|, returns * Returns the contents of this Maybe<T> by ref. If |isNothing()|, returns
* the default value provided. * the default value provided.
*/ */
constexpr T& refOr(T& aDefault) { constexpr T& refOr(T& aDefault MOZ_LIFETIME_BOUND) MOZ_LIFETIME_BOUND {
if (isSome()) { if (isSome()) {
return ref(); return ref();
} }
return aDefault; 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()) { if (isSome()) {
return ref(); return ref();
} }
@@ -618,10 +619,10 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Maybe
return aFunc(); return aFunc();
} }
constexpr T& operator*() &; constexpr T& operator*() & MOZ_LIFETIME_BOUND;
constexpr const T& operator*() const&; constexpr const T& operator*() const& MOZ_LIFETIME_BOUND;
constexpr T&& operator*() &&; constexpr T&& operator*() && MOZ_LIFETIME_BOUND;
constexpr const T&& operator*() const&&; constexpr const T&& operator*() const&& MOZ_LIFETIME_BOUND;
/* If |isSome()|, runs the provided function or functor on the contents of /* If |isSome()|, runs the provided function or functor on the contents of
* this Maybe. */ * this Maybe. */

View File

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

View File

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

View File

@@ -567,7 +567,8 @@ struct VariantIndex {
* instead. * instead.
*/ */
template <typename... Ts> 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 IPC::ParamTraits<mozilla::Variant<Ts...>>;
friend struct mozilla::ipc::IPDLParamTraits<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. */ /** Mutable lvalue-reference. */
template <typename T> template <typename T>
T& as() & { T& as() & MOZ_LIFETIME_BOUND {
static_assert( static_assert(
detail::SelectVariantType<T, Ts...>::count == 1, detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not uniquely found in this Variant's type list"); "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> 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), static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list"); "provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>()); 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. */ /** Immutable const lvalue-reference. */
template <typename T> template <typename T>
const T& as() const& { const T& as() const& MOZ_LIFETIME_BOUND {
static_assert(detail::SelectVariantType<T, Ts...>::count == 1, static_assert(detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not found in this Variant's type list"); "provided a type not found in this Variant's type list");
MOZ_RELEASE_ASSERT(is<T>()); 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> 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), static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list"); "provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>()); MOZ_RELEASE_ASSERT(is<N>());
@@ -774,7 +775,7 @@ class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS MOZ_NON_PARAM Variant {
/** Mutable rvalue-reference. */ /** Mutable rvalue-reference. */
template <typename T> template <typename T>
T&& as() && { T&& as() && MOZ_LIFETIME_BOUND {
static_assert( static_assert(
detail::SelectVariantType<T, Ts...>::count == 1, detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not uniquely found in this Variant's type list"); "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> 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), static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list"); "provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>()); 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. */ /** Immutable const rvalue-reference. */
template <typename T> template <typename T>
const T&& as() const&& { const T&& as() const&& MOZ_LIFETIME_BOUND {
static_assert(detail::SelectVariantType<T, Ts...>::count == 1, static_assert(detail::SelectVariantType<T, Ts...>::count == 1,
"provided a type not found in this Variant's type list"); "provided a type not found in this Variant's type list");
MOZ_RELEASE_ASSERT(is<T>()); 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> 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), static_assert(N < sizeof...(Ts),
"provided an index outside of this Variant's type list"); "provided an index outside of this Variant's type list");
MOZ_RELEASE_ASSERT(is<N>()); MOZ_RELEASE_ASSERT(is<N>());

View File

@@ -339,7 +339,7 @@ struct VectorTesting;
*/ */
template <typename T, size_t MinInlineCapacity = 0, template <typename T, size_t MinInlineCapacity = 0,
class AllocPolicy = MallocAllocPolicy> class AllocPolicy = MallocAllocPolicy>
class MOZ_NON_PARAM Vector final : private AllocPolicy { class MOZ_NON_PARAM MOZ_GSL_OWNER Vector final : private AllocPolicy {
/* utilities */ /* utilities */
static constexpr bool kElemIsPod = static constexpr bool kElemIsPod =
std::is_trivial_v<T> && std::is_standard_layout_v<T>; 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. // file for more details.
// //
template <class E> template <class E>
class nsTArray : public nsTArray_Impl<E, nsTArrayInfallibleAllocator> { class MOZ_GSL_OWNER nsTArray
: public nsTArray_Impl<E, nsTArrayInfallibleAllocator> {
public: public:
using InfallibleAlloc = nsTArrayInfallibleAllocator; using InfallibleAlloc = nsTArrayInfallibleAllocator;
using base_type = nsTArray_Impl<E, InfallibleAlloc>; using base_type = nsTArray_Impl<E, InfallibleAlloc>;
@@ -2963,7 +2964,7 @@ class nsTArray : public nsTArray_Impl<E, nsTArrayInfallibleAllocator> {
}; };
template <class E> template <class E>
class CopyableTArray : public nsTArray<E> { class MOZ_GSL_OWNER CopyableTArray : public nsTArray<E> {
public: public:
using nsTArray<E>::nsTArray; using nsTArray<E>::nsTArray;
@@ -3007,7 +3008,8 @@ class CopyableTArray : public nsTArray<E> {
// FallibleTArray is a fallible vector class. // FallibleTArray is a fallible vector class.
// //
template <class E> template <class E>
class FallibleTArray : public nsTArray_Impl<E, nsTArrayFallibleAllocator> { class MOZ_GSL_OWNER FallibleTArray
: public nsTArray_Impl<E, nsTArrayFallibleAllocator> {
public: public:
typedef nsTArray_Impl<E, nsTArrayFallibleAllocator> base_type; typedef nsTArray_Impl<E, nsTArrayFallibleAllocator> base_type;
typedef FallibleTArray<E> self_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. // Storing more than N elements is fine, but it will cause a heap allocation.
// //
template <class E, size_t N> 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"); static_assert(N != 0, "AutoTArray<E, 0> should be specialized");
public: 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 * 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: public:
explicit NS_LossyConvertUTF16toASCII(const char16ptr_t aString) { explicit NS_LossyConvertUTF16toASCII(const char16ptr_t aString) {
LossyAppendUTF16toASCII(mozilla::MakeStringSpan(aString), *this); LossyAppendUTF16toASCII(mozilla::MakeStringSpan(aString), *this);

View File

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

View File

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

View File

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