From 3ff0c697d30707fa73a54b93d32afbad7f5de4ac Mon Sep 17 00:00:00 2001 From: Simon Giesecke Date: Fri, 24 Apr 2020 13:24:57 +0000 Subject: [PATCH] Bug 1628715 - Part 2: Disable copy assignment to FallibleTArray from infallible nsTArray. r=xpcom-reviewers,erahm Also prepare disabling copy construction and assignment in Bug 1628692. Differential Revision: https://phabricator.services.mozilla.com/D70383 --- xpcom/ds/nsTArray.h | 99 ++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/xpcom/ds/nsTArray.h b/xpcom/ds/nsTArray.h index 616ec2516ffec..69fe2b56e0f38 100644 --- a/xpcom/ds/nsTArray.h +++ b/xpcom/ds/nsTArray.h @@ -283,12 +283,20 @@ constexpr bool SpecializableIsCopyConstructibleValue = // nsTArray_Impl only is copy-constructible and copy-assignable if E is // copy-constructible. nsTArray_Impl never makes use of E's copy assignment // operator, so the decision is made solely based on E's copy-constructibility. -template > +template + // XXX Bug 1628692: We should disallow copy constructors/assignment + // operators for FallibleTArray, since copying may fail but there's no + // way to signal that to the caller. However, there are several uses, + // including in ipdlc generated code, that do this, which need to be + // fixed first. + // + // && std::is_same_v + > class nsTArray_CopyEnabler; -template -class nsTArray_CopyEnabler { +template +class nsTArray_CopyEnabler { public: nsTArray_CopyEnabler() = default; @@ -296,8 +304,8 @@ class nsTArray_CopyEnabler { nsTArray_CopyEnabler& operator=(const nsTArray_CopyEnabler&) = delete; }; -template -class nsTArray_CopyEnabler { +template +class nsTArray_CopyEnabler { public: nsTArray_CopyEnabler() = default; @@ -307,10 +315,17 @@ class nsTArray_CopyEnabler { nsTArray_CopyEnabler& operator=(const nsTArray_CopyEnabler& aOther) { if (this != &aOther) { - static_cast(this)->ReplaceElementsAt( + /// XXX Bug 1628692 will make FallibleTArray uncopyable. Checking of the + /// return value should be removed then again. + E* const res = static_cast(this)->ReplaceElementsAt( 0, static_cast(this)->Length(), static_cast(aOther).Elements(), static_cast(aOther).Length()); +#ifdef DEBUG + MOZ_ASSERT(res); +#else + (void)res; +#endif } return *this; } @@ -320,9 +335,9 @@ class nsTArray_CopyEnabler { // This class provides a SafeElementAt method to nsTArray which does // not take a second default value parameter. -template +template struct nsTArray_SafeElementAtHelper - : public ::detail::nsTArray_CopyEnabler { + : public ::detail::nsTArray_CopyEnabler { typedef E* elem_type; typedef size_t index_type; @@ -333,9 +348,9 @@ struct nsTArray_SafeElementAtHelper const elem_type& SafeElementAt(index_type aIndex) const; }; -template -struct nsTArray_SafeElementAtHelper - : public ::detail::nsTArray_CopyEnabler { +template +struct nsTArray_SafeElementAtHelper + : public ::detail::nsTArray_CopyEnabler { typedef E* elem_type; // typedef const E* const_elem_type; XXX: see below typedef size_t index_type; @@ -355,9 +370,9 @@ struct nsTArray_SafeElementAtHelper // E is a smart pointer type; the // smart pointer can act as its element_type*. -template +template struct nsTArray_SafeElementAtSmartPtrHelper - : public ::detail::nsTArray_CopyEnabler { + : public ::detail::nsTArray_CopyEnabler { typedef typename E::element_type* elem_type; typedef const typename E::element_type* const_elem_type; typedef size_t index_type; @@ -383,23 +398,24 @@ struct nsTArray_SafeElementAtSmartPtrHelper template class nsCOMPtr; -template -struct nsTArray_SafeElementAtHelper, Derived> - : public nsTArray_SafeElementAtSmartPtrHelper, Derived> {}; +template +struct nsTArray_SafeElementAtHelper, Derived, Alloc> + : public nsTArray_SafeElementAtSmartPtrHelper, Derived, Alloc> { +}; -template -struct nsTArray_SafeElementAtHelper, Derived> - : public nsTArray_SafeElementAtSmartPtrHelper, Derived> {}; +template +struct nsTArray_SafeElementAtHelper, Derived, Alloc> + : public nsTArray_SafeElementAtSmartPtrHelper, Derived, Alloc> {}; namespace mozilla { template class OwningNonNull; } // namespace mozilla -template -struct nsTArray_SafeElementAtHelper, Derived> +template +struct nsTArray_SafeElementAtHelper, Derived, Alloc> : public nsTArray_SafeElementAtSmartPtrHelper, - Derived> {}; + Derived, Alloc> {}; // Servo bindings. extern "C" void Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity, @@ -875,8 +891,9 @@ MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(mozilla::SourceBufferTask) // nsTArray_Impl class, to allow extra conversions to be added for specific // types. // -template -struct nsTArray_TypedBase : public nsTArray_SafeElementAtHelper {}; +template +struct nsTArray_TypedBase + : public nsTArray_SafeElementAtHelper {}; // // Specialization of nsTArray_TypedBase for arrays containing JS::Heap @@ -889,9 +906,9 @@ struct nsTArray_TypedBase : public nsTArray_SafeElementAtHelper {}; // The static_cast is necessary to obtain the correct address for the derived // class since we are a base class used in multiple inheritance. // -template -struct nsTArray_TypedBase, Derived> - : public nsTArray_SafeElementAtHelper, Derived> { +template +struct nsTArray_TypedBase, Derived, Alloc> + : public nsTArray_SafeElementAtHelper, Derived, Alloc> { operator const nsTArray&() { static_assert(sizeof(E) == sizeof(JS::Heap), "JS::Heap must be binary compatible with E."); @@ -1013,15 +1030,16 @@ template class nsTArray_Impl : public nsTArray_base::Type>, - public nsTArray_TypedBase< - E, - nsTArray_Impl> // This must come last to ensure the members - // from nsTArray_base are initialized before - // the delegated constructor calls from - // nsTArray_CopyEnabler are executed. + public nsTArray_TypedBase, + Alloc> // This must come last to ensure the + // members from nsTArray_base are + // initialized before the delegated + // constructor calls from + // nsTArray_CopyEnabler are executed. { private: - friend class ::detail::nsTArray_CopyEnabler>; + friend class ::detail::nsTArray_CopyEnabler, + Alloc>; typedef nsTArrayFallibleAllocator FallibleAlloc; typedef nsTArrayInfallibleAllocator InfallibleAlloc; @@ -1034,7 +1052,8 @@ class nsTArray_Impl typedef E elem_type; typedef nsTArray_Impl self_type; typedef nsTArrayElementTraits elem_traits; - typedef nsTArray_SafeElementAtHelper safeelementat_helper_type; + typedef nsTArray_SafeElementAtHelper + safeelementat_helper_type; typedef mozilla::ArrayIterator> iterator; typedef mozilla::ArrayIterator> const_iterator; typedef mozilla::ReverseIterator reverse_iterator; @@ -1149,7 +1168,13 @@ class nsTArray_Impl // elements as |aOther|. bool operator!=(const self_type& aOther) const { return !operator==(aOther); } - template + // If Alloc == FallibleAlloc, ReplaceElementsAt might fail, without a way to + // signal this to the caller, so we disallow copying via operator=. Callers + // should use ReplaceElementsAt with a fallible argument instead, and check + // the result. + template , + Allocator>> self_type& operator=(const nsTArray_Impl& aOther) { ReplaceElementsAt(0, Length(), aOther.Elements(), aOther.Length()); return *this;