Remove backward-compatibility-1500-revert-remove-base-stackvector.patch
BUG=b:295505917
TEST=emerge-hatch libchrome
Cq-Depend: chromium:4782568
Change-Id: Ida2b7cad36fbff5842c1bada1ded38757b91029f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/libchrome/+/4780691
Tested-by: Ryo Hashimoto <hashimoto@chromium.org>
Commit-Queue: Grace Cham <hscham@chromium.org>
Reviewed-by: Grace Cham <hscham@chromium.org>
diff --git a/libchrome_tools/patches/backward-compatibility-1500-revert-remove-base-stackvector.patch b/libchrome_tools/patches/backward-compatibility-1500-revert-remove-base-stackvector.patch
deleted file mode 100644
index 5f44647..0000000
--- a/libchrome_tools/patches/backward-compatibility-1500-revert-remove-base-stackvector.patch
+++ /dev/null
@@ -1,519 +0,0 @@
-From 67b1b0352f38a531781bb0311441b77f092a6845 Mon Sep 17 00:00:00 2001
-From: Brett Brotherton <bbrotherton@google.com>
-Date: Fri, 11 Aug 2023 07:21:32 -0600
-Subject: [PATCH] Revert "Remove base::StackVector"
-
-This reverts commit 70f8b27d8e7b42cd461e388af427a361ca509808.
----
- base/containers/stack_container.h | 277 ++++++++++++++++++++
- base/containers/stack_container_unittest.cc | 214 +++++++++++++++
- 2 files changed, 491 insertions(+)
- create mode 100644 base/containers/stack_container.h
- create mode 100644 base/containers/stack_container_unittest.cc
-
-diff --git a/base/containers/stack_container.h b/base/containers/stack_container.h
-new file mode 100644
-index 0000000000..ba3842a28d
---- /dev/null
-+++ b/base/containers/stack_container.h
-@@ -0,0 +1,277 @@
-+// Copyright 2012 The Chromium Authors
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#ifndef BASE_CONTAINERS_STACK_CONTAINER_H_
-+#define BASE_CONTAINERS_STACK_CONTAINER_H_
-+
-+// ================== DEPRECATION NOTICE ==================
-+// These classes are deprecated and will be removed soon. Use
-+// absl::InlinedVector instead. If absl::InlinedVector doesn't fit your use
-+// case, please email cxx@chromium.org with details.
-+
-+#include <stddef.h>
-+#include <memory>
-+#include <vector>
-+
-+#include "base/compiler_specific.h"
-+#include "base/memory/raw_ptr_exclusion.h"
-+#include "build/build_config.h"
-+
-+namespace base {
-+
-+// This allocator can be used with STL containers to provide a stack buffer
-+// from which to allocate memory and overflows onto the heap. This stack buffer
-+// would be allocated on the stack and allows us to avoid heap operations in
-+// some situations.
-+//
-+// STL likes to make copies of allocators, so the allocator itself can't hold
-+// the data. Instead, we make the creator responsible for creating a
-+// StackAllocator::Source which contains the data. Copying the allocator
-+// merely copies the pointer to this shared source, so all allocators created
-+// based on our allocator will share the same stack buffer.
-+//
-+// This stack buffer implementation is very simple. The first allocation that
-+// fits in the stack buffer will use the stack buffer. Any subsequent
-+// allocations will not use the stack buffer, even if there is unused room.
-+// This makes it appropriate for array-like containers, but the caller should
-+// be sure to reserve() in the container up to the stack buffer size. Otherwise
-+// the container will allocate a small array which will "use up" the stack
-+// buffer.
-+template <typename T, size_t stack_capacity, typename FallbackAllocator>
-+class StackAllocator : public FallbackAllocator {
-+ public:
-+ using pointer = typename std::allocator_traits<FallbackAllocator>::pointer;
-+ using size_type =
-+ typename std::allocator_traits<FallbackAllocator>::size_type;
-+
-+ // Backing store for the allocator. The container owner is responsible for
-+ // maintaining this for as long as any containers using this allocator are
-+ // live.
-+ struct Source {
-+ Source() : used_stack_buffer_(false) {
-+ }
-+
-+ // Casts the buffer in its right type.
-+ NO_SANITIZE("cfi-unrelated-cast")
-+ T* stack_buffer() { return reinterpret_cast<T*>(stack_buffer_); }
-+ NO_SANITIZE("cfi-unrelated-cast")
-+ const T* stack_buffer() const {
-+ return reinterpret_cast<const T*>(&stack_buffer_);
-+ }
-+
-+ // The buffer itself. It is not of type T because we don't want the
-+ // constructors and destructors to be automatically called. Define a POD
-+ // buffer of the right size instead.
-+ alignas(T) char stack_buffer_[sizeof(T[stack_capacity])];
-+#if defined(__GNUC__) && !defined(ARCH_CPU_X86_FAMILY)
-+ static_assert(alignof(T) <= 16, "http://crbug.com/115612");
-+#endif
-+
-+ // Set when the stack buffer is used for an allocation. We do not track
-+ // how much of the buffer is used, only that somebody is using it.
-+ bool used_stack_buffer_;
-+ };
-+
-+ // Used by containers when they want to refer to an allocator of type U.
-+ template<typename U>
-+ struct rebind {
-+ typedef StackAllocator<U, stack_capacity, FallbackAllocator> other;
-+ };
-+
-+ // For the straight up copy c-tor, we can share storage.
-+ StackAllocator(
-+ const StackAllocator<T, stack_capacity, FallbackAllocator>& rhs)
-+ : source_(rhs.source_) {}
-+
-+ // ISO C++ requires the following constructor to be defined,
-+ // and std::vector in VC++2008SP1 Release fails with an error
-+ // in the class _Container_base_aux_alloc_real (from <xutility>)
-+ // if the constructor does not exist.
-+ // For this constructor, we cannot share storage; there's
-+ // no guarantee that the Source buffer of Ts is large enough
-+ // for Us.
-+ // TODO: If we were fancy pants, perhaps we could share storage
-+ // iff sizeof(T) == sizeof(U).
-+ template <typename U, size_t other_capacity, typename FA>
-+ StackAllocator(const StackAllocator<U, other_capacity, FA>& other)
-+ : source_(nullptr) {}
-+
-+ // This constructor must exist. It creates a default allocator that doesn't
-+ // actually have a stack buffer. glibc's std::string() will compare the
-+ // current allocator against the default-constructed allocator, so this
-+ // should be fast.
-+ StackAllocator() : source_(nullptr) {}
-+
-+ explicit StackAllocator(Source* source) : source_(source) {
-+ }
-+
-+ // Actually do the allocation. Use the stack buffer if nobody has used it yet
-+ // and the size requested fits. Otherwise, fall through to the standard
-+ // allocator.
-+ pointer allocate(size_type n) {
-+ if (source_ && !source_->used_stack_buffer_ && n <= stack_capacity) {
-+ source_->used_stack_buffer_ = true;
-+ return source_->stack_buffer();
-+ } else {
-+ return std::allocator_traits<FallbackAllocator>::allocate(*this, n);
-+ }
-+ }
-+
-+ // Free: when trying to free the stack buffer, just mark it as free. For
-+ // non-stack-buffer pointers, just fall though to the standard allocator.
-+ void deallocate(pointer p, size_type n) {
-+ if (source_ && p == source_->stack_buffer())
-+ source_->used_stack_buffer_ = false;
-+ else
-+ std::allocator_traits<FallbackAllocator>::deallocate(*this, p, n);
-+ }
-+
-+ private:
-+ // `source_` is not a raw_ptr<T> for performance reasons: on-stack pointee.
-+ RAW_PTR_EXCLUSION Source* source_;
-+};
-+
-+// A wrapper around STL containers that maintains a stack-sized buffer that the
-+// initial capacity of the vector is based on. Growing the container beyond the
-+// stack capacity will transparently overflow onto the heap. The container must
-+// support reserve().
-+//
-+// This will not work with std::string since some implementations allocate
-+// more bytes than requested in calls to reserve(), forcing the allocation onto
-+// the heap. http://crbug.com/709273
-+//
-+// WATCH OUT: the ContainerType MUST use the proper StackAllocator for this
-+// type. This object is really intended to be used only internally. You'll want
-+// to use the wrappers below for different types.
-+template <typename TContainerType, int stack_capacity>
-+class StackContainer {
-+ public:
-+ using ContainerType = TContainerType;
-+ using ContainedType = typename ContainerType::value_type;
-+ using Allocator = typename ContainerType::allocator_type;
-+
-+ // Allocator must be constructed before the container!
-+ StackContainer() : allocator_(&stack_data_), container_(allocator_) {
-+ // Make the container use the stack allocation by reserving our buffer size
-+ // before doing anything else.
-+ container_.reserve(stack_capacity);
-+ }
-+ StackContainer(const StackContainer&) = delete;
-+ StackContainer& operator=(const StackContainer&) = delete;
-+
-+ // Getters for the actual container.
-+ //
-+ // Danger: any copies of this made using the copy constructor must have
-+ // shorter lifetimes than the source. The copy will share the same allocator
-+ // and therefore the same stack buffer as the original. Use std::copy to
-+ // copy into a "real" container for longer-lived objects.
-+ ContainerType& container() { return container_; }
-+ const ContainerType& container() const { return container_; }
-+
-+ // Support operator-> to get to the container. This allows nicer syntax like:
-+ // StackContainer<...> foo;
-+ // std::sort(foo->begin(), foo->end());
-+ ContainerType* operator->() { return &container_; }
-+ const ContainerType* operator->() const { return &container_; }
-+
-+#ifdef UNIT_TEST
-+ // Retrieves the stack source so that that unit tests can verify that the
-+ // buffer is being used properly.
-+ const typename Allocator::Source& stack_data() const {
-+ return stack_data_;
-+ }
-+#endif
-+
-+ protected:
-+ typename Allocator::Source stack_data_;
-+ NO_UNIQUE_ADDRESS Allocator allocator_;
-+ ContainerType container_;
-+};
-+
-+// Range-based iteration support for StackContainer.
-+template <typename TContainerType, int stack_capacity>
-+auto begin(
-+ const StackContainer<TContainerType, stack_capacity>& stack_container)
-+ -> decltype(begin(stack_container.container())) {
-+ return begin(stack_container.container());
-+}
-+
-+template <typename TContainerType, int stack_capacity>
-+auto begin(StackContainer<TContainerType, stack_capacity>& stack_container)
-+ -> decltype(begin(stack_container.container())) {
-+ return begin(stack_container.container());
-+}
-+
-+template <typename TContainerType, int stack_capacity>
-+auto end(StackContainer<TContainerType, stack_capacity>& stack_container)
-+ -> decltype(end(stack_container.container())) {
-+ return end(stack_container.container());
-+}
-+
-+template <typename TContainerType, int stack_capacity>
-+auto end(const StackContainer<TContainerType, stack_capacity>& stack_container)
-+ -> decltype(end(stack_container.container())) {
-+ return end(stack_container.container());
-+}
-+
-+// StackVector -----------------------------------------------------------------
-+
-+// THIS CLASS IS DEPRECATED. Use absl::InlinedVector instead.
-+
-+// Example:
-+// StackVector<int, 16> foo;
-+// foo->push_back(22); // we have overloaded operator->
-+// foo[0] = 10; // as well as operator[]
-+template <typename T,
-+ size_t stack_capacity,
-+ typename FallbackAllocator = std::allocator<T>>
-+class StackVector
-+ : public StackContainer<
-+ std::vector<T, StackAllocator<T, stack_capacity, FallbackAllocator>>,
-+ stack_capacity> {
-+ public:
-+ StackVector()
-+ : StackContainer<
-+ std::vector<T,
-+ StackAllocator<T, stack_capacity, FallbackAllocator>>,
-+ stack_capacity>() {}
-+
-+ // We need to put this in STL containers sometimes, which requires a copy
-+ // constructor. We can't call the regular copy constructor because that will
-+ // take the stack buffer from the original. Here, we create an empty object
-+ // and make a stack buffer of its own.
-+ StackVector(const StackVector<T, stack_capacity, FallbackAllocator>& other)
-+ : StackContainer<
-+ std::vector<T,
-+ StackAllocator<T, stack_capacity, FallbackAllocator>>,
-+ stack_capacity>() {
-+ this->container().assign(other->begin(), other->end());
-+ }
-+
-+ StackVector<T, stack_capacity, FallbackAllocator>& operator=(
-+ const StackVector<T, stack_capacity, FallbackAllocator>& other) {
-+ this->container().assign(other->begin(), other->end());
-+ return *this;
-+ }
-+
-+ // Vectors are commonly indexed, which isn't very convenient even with
-+ // operator-> (using "->at()" does exception stuff we don't want).
-+ T& operator[](size_t i) { return this->container().operator[](i); }
-+ const T& operator[](size_t i) const {
-+ return this->container().operator[](i);
-+ }
-+};
-+
-+} // namespace base
-+
-+// Opt out of libc++ container annotations for StackAllocator. It seems to slow
-+// down some tests enough to cause timeouts(?) crbug.com/1444659
-+#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS
-+template <typename T, size_t stack_capacity, typename FallbackAllocator>
-+struct ::std::__asan_annotate_container_with_allocator<
-+ base::StackAllocator<T, stack_capacity, FallbackAllocator>>
-+ : ::std::false_type {};
-+#endif // _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS
-+
-+#endif // BASE_CONTAINERS_STACK_CONTAINER_H_
-diff --git a/base/containers/stack_container_unittest.cc b/base/containers/stack_container_unittest.cc
-new file mode 100644
-index 0000000000..68c6321824
---- /dev/null
-+++ b/base/containers/stack_container_unittest.cc
-@@ -0,0 +1,214 @@
-+// Copyright 2012 The Chromium Authors
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "base/containers/stack_container.h"
-+
-+#include <stddef.h>
-+
-+#include "base/memory/aligned_memory.h"
-+#include "base/memory/raw_ptr.h"
-+#include "base/memory/ref_counted.h"
-+#include "base/ranges/algorithm.h"
-+#include "build/build_config.h"
-+#include "testing/gtest/include/gtest/gtest.h"
-+
-+namespace base {
-+
-+namespace {
-+
-+class Dummy : public RefCounted<Dummy> {
-+ public:
-+ explicit Dummy(int* alive) : alive_(alive) {
-+ ++*alive_;
-+ }
-+
-+ private:
-+ friend class RefCounted<Dummy>;
-+
-+ ~Dummy() {
-+ --*alive_;
-+ }
-+
-+ const raw_ptr<int> alive_;
-+};
-+
-+} // namespace
-+
-+TEST(StackContainer, Vector) {
-+ const int stack_size = 3;
-+ StackVector<int, stack_size> vect;
-+ const int* stack_buffer = &vect.stack_data().stack_buffer()[0];
-+
-+ // The initial |stack_size| elements should appear in the stack buffer.
-+ EXPECT_EQ(static_cast<size_t>(stack_size), vect.container().capacity());
-+ for (int i = 0; i < stack_size; i++) {
-+ vect.container().push_back(i);
-+ EXPECT_EQ(stack_buffer, &vect.container()[0]);
-+ EXPECT_TRUE(vect.stack_data().used_stack_buffer_);
-+ }
-+
-+ // Adding more elements should push the array onto the heap.
-+ for (int i = 0; i < stack_size; i++) {
-+ vect.container().push_back(i + stack_size);
-+ EXPECT_NE(stack_buffer, &vect.container()[0]);
-+ EXPECT_FALSE(vect.stack_data().used_stack_buffer_);
-+ }
-+
-+ // The array should still be in order.
-+ for (int i = 0; i < stack_size * 2; i++)
-+ EXPECT_EQ(i, vect.container()[i]);
-+
-+ // Resize to smaller. Our STL implementation won't reallocate in this case,
-+ // otherwise it might use our stack buffer. We reserve right after the resize
-+ // to guarantee it isn't using the stack buffer, even though it doesn't have
-+ // much data.
-+ vect.container().resize(stack_size);
-+ vect.container().reserve(stack_size * 2);
-+ EXPECT_FALSE(vect.stack_data().used_stack_buffer_);
-+
-+ // Copying the small vector to another should use the same allocator and use
-+ // the now-unused stack buffer. GENERALLY CALLERS SHOULD NOT DO THIS since
-+ // they have to get the template types just right and it can cause errors.
-+ std::vector<int, StackAllocator<int, stack_size, std::allocator<int>>> other(
-+ vect.container());
-+ EXPECT_EQ(stack_buffer, &other.front());
-+ EXPECT_TRUE(vect.stack_data().used_stack_buffer_);
-+ for (int i = 0; i < stack_size; i++)
-+ EXPECT_EQ(i, other[i]);
-+}
-+
-+TEST(StackContainer, VectorDoubleDelete) {
-+ // Regression testing for double-delete.
-+ typedef StackVector<scoped_refptr<Dummy>, 2> Vector;
-+ Vector vect;
-+
-+ int alive = 0;
-+ scoped_refptr<Dummy> dummy(new Dummy(&alive));
-+ EXPECT_EQ(alive, 1);
-+
-+ vect->push_back(dummy);
-+ EXPECT_EQ(alive, 1);
-+
-+ Dummy* dummy_unref = dummy.get();
-+ dummy = nullptr;
-+ EXPECT_EQ(alive, 1);
-+
-+ auto itr = ranges::find(vect, dummy_unref);
-+ EXPECT_EQ(itr->get(), dummy_unref);
-+ vect->erase(itr);
-+ EXPECT_EQ(alive, 0);
-+
-+ // Shouldn't crash at exit.
-+}
-+
-+namespace {
-+
-+template <size_t alignment>
-+class AlignedData {
-+ public:
-+ AlignedData() { memset(data_, 0, alignment); }
-+ ~AlignedData() = default;
-+ alignas(alignment) char data_[alignment];
-+};
-+
-+} // namespace
-+
-+TEST(StackContainer, BufferAlignment) {
-+ StackVector<wchar_t, 16> text;
-+ text->push_back(L'A');
-+ EXPECT_TRUE(IsAligned(&text[0], alignof(wchar_t)));
-+
-+ StackVector<double, 1> doubles;
-+ doubles->push_back(0.0);
-+ EXPECT_TRUE(IsAligned(&doubles[0], alignof(double)));
-+
-+ StackVector<AlignedData<16>, 1> aligned16;
-+ aligned16->push_back(AlignedData<16>());
-+ EXPECT_TRUE(IsAligned(&aligned16[0], 16));
-+
-+#if !defined(__GNUC__) || defined(ARCH_CPU_X86_FAMILY)
-+ // It seems that non-X86 gcc doesn't respect greater than 16 byte alignment.
-+ // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33721 for details.
-+ // TODO(sbc): Re-enable this if GCC starts respecting higher alignments.
-+ StackVector<AlignedData<256>, 1> aligned256;
-+ aligned256->push_back(AlignedData<256>());
-+ EXPECT_TRUE(IsAligned(&aligned256[0], 256));
-+#endif
-+}
-+
-+template class StackVector<int, 2>;
-+template class StackVector<scoped_refptr<Dummy>, 2>;
-+
-+template <typename T, size_t size>
-+void CheckStackVectorElements(const StackVector<T, size>& vec,
-+ std::initializer_list<T> expected) {
-+ auto expected_it = expected.begin();
-+ EXPECT_EQ(vec->size(), expected.size());
-+ for (T t : vec) {
-+ EXPECT_NE(expected.end(), expected_it);
-+ EXPECT_EQ(*expected_it, t);
-+ ++expected_it;
-+ }
-+ EXPECT_EQ(expected.end(), expected_it);
-+}
-+
-+TEST(StackContainer, Iteration) {
-+ StackVector<int, 3> vect;
-+ vect->push_back(7);
-+ vect->push_back(11);
-+
-+ CheckStackVectorElements(vect, {7, 11});
-+ for (int& i : vect) {
-+ ++i;
-+ }
-+ CheckStackVectorElements(vect, {8, 12});
-+ vect->push_back(13);
-+ CheckStackVectorElements(vect, {8, 12, 13});
-+ vect->resize(5);
-+ CheckStackVectorElements(vect, {8, 12, 13, 0, 0});
-+ vect->resize(1);
-+ CheckStackVectorElements(vect, {8});
-+}
-+
-+namespace {
-+struct Allocator : std::allocator<int> {
-+ using Base = std::allocator<int>;
-+
-+ int* allocate(size_t n) {
-+ ++allocated;
-+ return Base::allocate(n);
-+ }
-+ void deallocate(int* p, size_t n) {
-+ ++deallocated;
-+ Base::deallocate(p, n);
-+ }
-+
-+ static int allocated;
-+ static int deallocated;
-+};
-+
-+int Allocator::allocated = 0;
-+int Allocator::deallocated = 0;
-+} // namespace
-+
-+TEST(StackContainer, CustomAllocator) {
-+ StackVector<int, 2, Allocator> v;
-+
-+ EXPECT_EQ(0, Allocator::allocated);
-+ EXPECT_EQ(0, Allocator::deallocated);
-+
-+ v->push_back(1);
-+ v->push_back(1);
-+ EXPECT_EQ(0, Allocator::allocated);
-+ v->push_back(1);
-+ EXPECT_EQ(1, Allocator::allocated);
-+
-+ EXPECT_EQ(0, Allocator::deallocated);
-+ v->clear();
-+ // shrink_to_fit() makes sure to destroy empty backing store.
-+ v->shrink_to_fit();
-+ EXPECT_EQ(1, Allocator::deallocated);
-+}
-+
-+} // namespace base
---
-2.41.0.640.ga95def55d0-goog
-