xref: /aosp_15_r20/external/abseil-cpp/absl/container/fixed_array.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker //      https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker //
15*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
16*9356374aSAndroid Build Coastguard Worker // File: fixed_array.h
17*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
18*9356374aSAndroid Build Coastguard Worker //
19*9356374aSAndroid Build Coastguard Worker // A `FixedArray<T>` represents a non-resizable array of `T` where the length of
20*9356374aSAndroid Build Coastguard Worker // the array can be determined at run-time. It is a good replacement for
21*9356374aSAndroid Build Coastguard Worker // non-standard and deprecated uses of `alloca()` and variable length arrays
22*9356374aSAndroid Build Coastguard Worker // within the GCC extension. (See
23*9356374aSAndroid Build Coastguard Worker // https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html).
24*9356374aSAndroid Build Coastguard Worker //
25*9356374aSAndroid Build Coastguard Worker // `FixedArray` allocates small arrays inline, keeping performance fast by
26*9356374aSAndroid Build Coastguard Worker // avoiding heap operations. It also helps reduce the chances of
27*9356374aSAndroid Build Coastguard Worker // accidentally overflowing your stack if large input is passed to
28*9356374aSAndroid Build Coastguard Worker // your function.
29*9356374aSAndroid Build Coastguard Worker 
30*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_CONTAINER_FIXED_ARRAY_H_
31*9356374aSAndroid Build Coastguard Worker #define ABSL_CONTAINER_FIXED_ARRAY_H_
32*9356374aSAndroid Build Coastguard Worker 
33*9356374aSAndroid Build Coastguard Worker #include <algorithm>
34*9356374aSAndroid Build Coastguard Worker #include <cassert>
35*9356374aSAndroid Build Coastguard Worker #include <cstddef>
36*9356374aSAndroid Build Coastguard Worker #include <initializer_list>
37*9356374aSAndroid Build Coastguard Worker #include <iterator>
38*9356374aSAndroid Build Coastguard Worker #include <limits>
39*9356374aSAndroid Build Coastguard Worker #include <memory>
40*9356374aSAndroid Build Coastguard Worker #include <new>
41*9356374aSAndroid Build Coastguard Worker #include <type_traits>
42*9356374aSAndroid Build Coastguard Worker 
43*9356374aSAndroid Build Coastguard Worker #include "absl/algorithm/algorithm.h"
44*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
45*9356374aSAndroid Build Coastguard Worker #include "absl/base/dynamic_annotations.h"
46*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/throw_delegate.h"
47*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h"
48*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
49*9356374aSAndroid Build Coastguard Worker #include "absl/base/port.h"
50*9356374aSAndroid Build Coastguard Worker #include "absl/container/internal/compressed_tuple.h"
51*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
52*9356374aSAndroid Build Coastguard Worker 
53*9356374aSAndroid Build Coastguard Worker namespace absl {
54*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
55*9356374aSAndroid Build Coastguard Worker 
56*9356374aSAndroid Build Coastguard Worker constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
57*9356374aSAndroid Build Coastguard Worker 
58*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
59*9356374aSAndroid Build Coastguard Worker // FixedArray
60*9356374aSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
61*9356374aSAndroid Build Coastguard Worker //
62*9356374aSAndroid Build Coastguard Worker // A `FixedArray` provides a run-time fixed-size array, allocating a small array
63*9356374aSAndroid Build Coastguard Worker // inline for efficiency.
64*9356374aSAndroid Build Coastguard Worker //
65*9356374aSAndroid Build Coastguard Worker // Most users should not specify the `N` template parameter and let `FixedArray`
66*9356374aSAndroid Build Coastguard Worker // automatically determine the number of elements to store inline based on
67*9356374aSAndroid Build Coastguard Worker // `sizeof(T)`. If `N` is specified, the `FixedArray` implementation will use
68*9356374aSAndroid Build Coastguard Worker // inline storage for arrays with a length <= `N`.
69*9356374aSAndroid Build Coastguard Worker //
70*9356374aSAndroid Build Coastguard Worker // Note that a `FixedArray` constructed with a `size_type` argument will
71*9356374aSAndroid Build Coastguard Worker // default-initialize its values by leaving trivially constructible types
72*9356374aSAndroid Build Coastguard Worker // uninitialized (e.g. int, int[4], double), and others default-constructed.
73*9356374aSAndroid Build Coastguard Worker // This matches the behavior of c-style arrays and `std::array`, but not
74*9356374aSAndroid Build Coastguard Worker // `std::vector`.
75*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N = kFixedArrayUseDefault,
76*9356374aSAndroid Build Coastguard Worker           typename A = std::allocator<T>>
77*9356374aSAndroid Build Coastguard Worker class FixedArray {
78*9356374aSAndroid Build Coastguard Worker   static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
79*9356374aSAndroid Build Coastguard Worker                 "Arrays with unknown bounds cannot be used with FixedArray.");
80*9356374aSAndroid Build Coastguard Worker 
81*9356374aSAndroid Build Coastguard Worker   static constexpr size_t kInlineBytesDefault = 256;
82*9356374aSAndroid Build Coastguard Worker 
83*9356374aSAndroid Build Coastguard Worker   using AllocatorTraits = std::allocator_traits<A>;
84*9356374aSAndroid Build Coastguard Worker   // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
85*9356374aSAndroid Build Coastguard Worker   // but this seems to be mostly pedantic.
86*9356374aSAndroid Build Coastguard Worker   template <typename Iterator>
87*9356374aSAndroid Build Coastguard Worker   using EnableIfForwardIterator = absl::enable_if_t<std::is_convertible<
88*9356374aSAndroid Build Coastguard Worker       typename std::iterator_traits<Iterator>::iterator_category,
89*9356374aSAndroid Build Coastguard Worker       std::forward_iterator_tag>::value>;
NoexceptCopyable()90*9356374aSAndroid Build Coastguard Worker   static constexpr bool NoexceptCopyable() {
91*9356374aSAndroid Build Coastguard Worker     return std::is_nothrow_copy_constructible<StorageElement>::value &&
92*9356374aSAndroid Build Coastguard Worker            absl::allocator_is_nothrow<allocator_type>::value;
93*9356374aSAndroid Build Coastguard Worker   }
NoexceptMovable()94*9356374aSAndroid Build Coastguard Worker   static constexpr bool NoexceptMovable() {
95*9356374aSAndroid Build Coastguard Worker     return std::is_nothrow_move_constructible<StorageElement>::value &&
96*9356374aSAndroid Build Coastguard Worker            absl::allocator_is_nothrow<allocator_type>::value;
97*9356374aSAndroid Build Coastguard Worker   }
DefaultConstructorIsNonTrivial()98*9356374aSAndroid Build Coastguard Worker   static constexpr bool DefaultConstructorIsNonTrivial() {
99*9356374aSAndroid Build Coastguard Worker     return !absl::is_trivially_default_constructible<StorageElement>::value;
100*9356374aSAndroid Build Coastguard Worker   }
101*9356374aSAndroid Build Coastguard Worker 
102*9356374aSAndroid Build Coastguard Worker  public:
103*9356374aSAndroid Build Coastguard Worker   using allocator_type = typename AllocatorTraits::allocator_type;
104*9356374aSAndroid Build Coastguard Worker   using value_type = typename AllocatorTraits::value_type;
105*9356374aSAndroid Build Coastguard Worker   using pointer = typename AllocatorTraits::pointer;
106*9356374aSAndroid Build Coastguard Worker   using const_pointer = typename AllocatorTraits::const_pointer;
107*9356374aSAndroid Build Coastguard Worker   using reference = value_type&;
108*9356374aSAndroid Build Coastguard Worker   using const_reference = const value_type&;
109*9356374aSAndroid Build Coastguard Worker   using size_type = typename AllocatorTraits::size_type;
110*9356374aSAndroid Build Coastguard Worker   using difference_type = typename AllocatorTraits::difference_type;
111*9356374aSAndroid Build Coastguard Worker   using iterator = pointer;
112*9356374aSAndroid Build Coastguard Worker   using const_iterator = const_pointer;
113*9356374aSAndroid Build Coastguard Worker   using reverse_iterator = std::reverse_iterator<iterator>;
114*9356374aSAndroid Build Coastguard Worker   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
115*9356374aSAndroid Build Coastguard Worker 
116*9356374aSAndroid Build Coastguard Worker   static constexpr size_type inline_elements =
117*9356374aSAndroid Build Coastguard Worker       (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
118*9356374aSAndroid Build Coastguard Worker                                   : static_cast<size_type>(N));
119*9356374aSAndroid Build Coastguard Worker 
noexcept(NoexceptCopyable ())120*9356374aSAndroid Build Coastguard Worker   FixedArray(const FixedArray& other) noexcept(NoexceptCopyable())
121*9356374aSAndroid Build Coastguard Worker       : FixedArray(other,
122*9356374aSAndroid Build Coastguard Worker                    AllocatorTraits::select_on_container_copy_construction(
123*9356374aSAndroid Build Coastguard Worker                        other.storage_.alloc())) {}
124*9356374aSAndroid Build Coastguard Worker 
FixedArray(const FixedArray & other,const allocator_type & a)125*9356374aSAndroid Build Coastguard Worker   FixedArray(const FixedArray& other,
126*9356374aSAndroid Build Coastguard Worker              const allocator_type& a) noexcept(NoexceptCopyable())
127*9356374aSAndroid Build Coastguard Worker       : FixedArray(other.begin(), other.end(), a) {}
128*9356374aSAndroid Build Coastguard Worker 
noexcept(NoexceptMovable ())129*9356374aSAndroid Build Coastguard Worker   FixedArray(FixedArray&& other) noexcept(NoexceptMovable())
130*9356374aSAndroid Build Coastguard Worker       : FixedArray(std::move(other), other.storage_.alloc()) {}
131*9356374aSAndroid Build Coastguard Worker 
FixedArray(FixedArray && other,const allocator_type & a)132*9356374aSAndroid Build Coastguard Worker   FixedArray(FixedArray&& other,
133*9356374aSAndroid Build Coastguard Worker              const allocator_type& a) noexcept(NoexceptMovable())
134*9356374aSAndroid Build Coastguard Worker       : FixedArray(std::make_move_iterator(other.begin()),
135*9356374aSAndroid Build Coastguard Worker                    std::make_move_iterator(other.end()), a) {}
136*9356374aSAndroid Build Coastguard Worker 
137*9356374aSAndroid Build Coastguard Worker   // Creates an array object that can store `n` elements.
138*9356374aSAndroid Build Coastguard Worker   // Note that trivially constructible elements will be uninitialized.
139*9356374aSAndroid Build Coastguard Worker   explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
storage_(n,a)140*9356374aSAndroid Build Coastguard Worker       : storage_(n, a) {
141*9356374aSAndroid Build Coastguard Worker     if (DefaultConstructorIsNonTrivial()) {
142*9356374aSAndroid Build Coastguard Worker       memory_internal::ConstructRange(storage_.alloc(), storage_.begin(),
143*9356374aSAndroid Build Coastguard Worker                                       storage_.end());
144*9356374aSAndroid Build Coastguard Worker     }
145*9356374aSAndroid Build Coastguard Worker   }
146*9356374aSAndroid Build Coastguard Worker 
147*9356374aSAndroid Build Coastguard Worker   // Creates an array initialized with `n` copies of `val`.
148*9356374aSAndroid Build Coastguard Worker   FixedArray(size_type n, const value_type& val,
149*9356374aSAndroid Build Coastguard Worker              const allocator_type& a = allocator_type())
storage_(n,a)150*9356374aSAndroid Build Coastguard Worker       : storage_(n, a) {
151*9356374aSAndroid Build Coastguard Worker     memory_internal::ConstructRange(storage_.alloc(), storage_.begin(),
152*9356374aSAndroid Build Coastguard Worker                                     storage_.end(), val);
153*9356374aSAndroid Build Coastguard Worker   }
154*9356374aSAndroid Build Coastguard Worker 
155*9356374aSAndroid Build Coastguard Worker   // Creates an array initialized with the size and contents of `init_list`.
156*9356374aSAndroid Build Coastguard Worker   FixedArray(std::initializer_list<value_type> init_list,
157*9356374aSAndroid Build Coastguard Worker              const allocator_type& a = allocator_type())
158*9356374aSAndroid Build Coastguard Worker       : FixedArray(init_list.begin(), init_list.end(), a) {}
159*9356374aSAndroid Build Coastguard Worker 
160*9356374aSAndroid Build Coastguard Worker   // Creates an array initialized with the elements from the input
161*9356374aSAndroid Build Coastguard Worker   // range. The array's size will always be `std::distance(first, last)`.
162*9356374aSAndroid Build Coastguard Worker   // REQUIRES: Iterator must be a forward_iterator or better.
163*9356374aSAndroid Build Coastguard Worker   template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
164*9356374aSAndroid Build Coastguard Worker   FixedArray(Iterator first, Iterator last,
165*9356374aSAndroid Build Coastguard Worker              const allocator_type& a = allocator_type())
storage_(std::distance (first,last),a)166*9356374aSAndroid Build Coastguard Worker       : storage_(std::distance(first, last), a) {
167*9356374aSAndroid Build Coastguard Worker     memory_internal::CopyRange(storage_.alloc(), storage_.begin(), first, last);
168*9356374aSAndroid Build Coastguard Worker   }
169*9356374aSAndroid Build Coastguard Worker 
~FixedArray()170*9356374aSAndroid Build Coastguard Worker   ~FixedArray() noexcept {
171*9356374aSAndroid Build Coastguard Worker     for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
172*9356374aSAndroid Build Coastguard Worker       AllocatorTraits::destroy(storage_.alloc(), cur);
173*9356374aSAndroid Build Coastguard Worker     }
174*9356374aSAndroid Build Coastguard Worker   }
175*9356374aSAndroid Build Coastguard Worker 
176*9356374aSAndroid Build Coastguard Worker   // Assignments are deleted because they break the invariant that the size of a
177*9356374aSAndroid Build Coastguard Worker   // `FixedArray` never changes.
178*9356374aSAndroid Build Coastguard Worker   void operator=(FixedArray&&) = delete;
179*9356374aSAndroid Build Coastguard Worker   void operator=(const FixedArray&) = delete;
180*9356374aSAndroid Build Coastguard Worker 
181*9356374aSAndroid Build Coastguard Worker   // FixedArray::size()
182*9356374aSAndroid Build Coastguard Worker   //
183*9356374aSAndroid Build Coastguard Worker   // Returns the length of the fixed array.
size()184*9356374aSAndroid Build Coastguard Worker   size_type size() const { return storage_.size(); }
185*9356374aSAndroid Build Coastguard Worker 
186*9356374aSAndroid Build Coastguard Worker   // FixedArray::max_size()
187*9356374aSAndroid Build Coastguard Worker   //
188*9356374aSAndroid Build Coastguard Worker   // Returns the largest possible value of `std::distance(begin(), end())` for a
189*9356374aSAndroid Build Coastguard Worker   // `FixedArray<T>`. This is equivalent to the most possible addressable bytes
190*9356374aSAndroid Build Coastguard Worker   // over the number of bytes taken by T.
max_size()191*9356374aSAndroid Build Coastguard Worker   constexpr size_type max_size() const {
192*9356374aSAndroid Build Coastguard Worker     return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
193*9356374aSAndroid Build Coastguard Worker   }
194*9356374aSAndroid Build Coastguard Worker 
195*9356374aSAndroid Build Coastguard Worker   // FixedArray::empty()
196*9356374aSAndroid Build Coastguard Worker   //
197*9356374aSAndroid Build Coastguard Worker   // Returns whether or not the fixed array is empty.
empty()198*9356374aSAndroid Build Coastguard Worker   bool empty() const { return size() == 0; }
199*9356374aSAndroid Build Coastguard Worker 
200*9356374aSAndroid Build Coastguard Worker   // FixedArray::memsize()
201*9356374aSAndroid Build Coastguard Worker   //
202*9356374aSAndroid Build Coastguard Worker   // Returns the memory size of the fixed array in bytes.
memsize()203*9356374aSAndroid Build Coastguard Worker   size_t memsize() const { return size() * sizeof(value_type); }
204*9356374aSAndroid Build Coastguard Worker 
205*9356374aSAndroid Build Coastguard Worker   // FixedArray::data()
206*9356374aSAndroid Build Coastguard Worker   //
207*9356374aSAndroid Build Coastguard Worker   // Returns a const T* pointer to elements of the `FixedArray`. This pointer
208*9356374aSAndroid Build Coastguard Worker   // can be used to access (but not modify) the contained elements.
data()209*9356374aSAndroid Build Coastguard Worker   const_pointer data() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
210*9356374aSAndroid Build Coastguard Worker     return AsValueType(storage_.begin());
211*9356374aSAndroid Build Coastguard Worker   }
212*9356374aSAndroid Build Coastguard Worker 
213*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::data() to return a T* pointer to elements of the
214*9356374aSAndroid Build Coastguard Worker   // fixed array. This pointer can be used to access and modify the contained
215*9356374aSAndroid Build Coastguard Worker   // elements.
data()216*9356374aSAndroid Build Coastguard Worker   pointer data() ABSL_ATTRIBUTE_LIFETIME_BOUND {
217*9356374aSAndroid Build Coastguard Worker     return AsValueType(storage_.begin());
218*9356374aSAndroid Build Coastguard Worker   }
219*9356374aSAndroid Build Coastguard Worker 
220*9356374aSAndroid Build Coastguard Worker   // FixedArray::operator[]
221*9356374aSAndroid Build Coastguard Worker   //
222*9356374aSAndroid Build Coastguard Worker   // Returns a reference the ith element of the fixed array.
223*9356374aSAndroid Build Coastguard Worker   // REQUIRES: 0 <= i < size()
224*9356374aSAndroid Build Coastguard Worker   reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
225*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(i < size());
226*9356374aSAndroid Build Coastguard Worker     return data()[i];
227*9356374aSAndroid Build Coastguard Worker   }
228*9356374aSAndroid Build Coastguard Worker 
229*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::operator()[] to return a const reference to the
230*9356374aSAndroid Build Coastguard Worker   // ith element of the fixed array.
231*9356374aSAndroid Build Coastguard Worker   // REQUIRES: 0 <= i < size()
232*9356374aSAndroid Build Coastguard Worker   const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
233*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(i < size());
234*9356374aSAndroid Build Coastguard Worker     return data()[i];
235*9356374aSAndroid Build Coastguard Worker   }
236*9356374aSAndroid Build Coastguard Worker 
237*9356374aSAndroid Build Coastguard Worker   // FixedArray::at
238*9356374aSAndroid Build Coastguard Worker   //
239*9356374aSAndroid Build Coastguard Worker   // Bounds-checked access.  Returns a reference to the ith element of the fixed
240*9356374aSAndroid Build Coastguard Worker   // array, or throws std::out_of_range
at(size_type i)241*9356374aSAndroid Build Coastguard Worker   reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
242*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(i >= size())) {
243*9356374aSAndroid Build Coastguard Worker       base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
244*9356374aSAndroid Build Coastguard Worker     }
245*9356374aSAndroid Build Coastguard Worker     return data()[i];
246*9356374aSAndroid Build Coastguard Worker   }
247*9356374aSAndroid Build Coastguard Worker 
248*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::at() to return a const reference to the ith element
249*9356374aSAndroid Build Coastguard Worker   // of the fixed array.
at(size_type i)250*9356374aSAndroid Build Coastguard Worker   const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
251*9356374aSAndroid Build Coastguard Worker     if (ABSL_PREDICT_FALSE(i >= size())) {
252*9356374aSAndroid Build Coastguard Worker       base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
253*9356374aSAndroid Build Coastguard Worker     }
254*9356374aSAndroid Build Coastguard Worker     return data()[i];
255*9356374aSAndroid Build Coastguard Worker   }
256*9356374aSAndroid Build Coastguard Worker 
257*9356374aSAndroid Build Coastguard Worker   // FixedArray::front()
258*9356374aSAndroid Build Coastguard Worker   //
259*9356374aSAndroid Build Coastguard Worker   // Returns a reference to the first element of the fixed array.
front()260*9356374aSAndroid Build Coastguard Worker   reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {
261*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
262*9356374aSAndroid Build Coastguard Worker     return data()[0];
263*9356374aSAndroid Build Coastguard Worker   }
264*9356374aSAndroid Build Coastguard Worker 
265*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::front() to return a reference to the first element
266*9356374aSAndroid Build Coastguard Worker   // of a fixed array of const values.
front()267*9356374aSAndroid Build Coastguard Worker   const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
268*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
269*9356374aSAndroid Build Coastguard Worker     return data()[0];
270*9356374aSAndroid Build Coastguard Worker   }
271*9356374aSAndroid Build Coastguard Worker 
272*9356374aSAndroid Build Coastguard Worker   // FixedArray::back()
273*9356374aSAndroid Build Coastguard Worker   //
274*9356374aSAndroid Build Coastguard Worker   // Returns a reference to the last element of the fixed array.
back()275*9356374aSAndroid Build Coastguard Worker   reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {
276*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
277*9356374aSAndroid Build Coastguard Worker     return data()[size() - 1];
278*9356374aSAndroid Build Coastguard Worker   }
279*9356374aSAndroid Build Coastguard Worker 
280*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::back() to return a reference to the last element
281*9356374aSAndroid Build Coastguard Worker   // of a fixed array of const values.
back()282*9356374aSAndroid Build Coastguard Worker   const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
283*9356374aSAndroid Build Coastguard Worker     ABSL_HARDENING_ASSERT(!empty());
284*9356374aSAndroid Build Coastguard Worker     return data()[size() - 1];
285*9356374aSAndroid Build Coastguard Worker   }
286*9356374aSAndroid Build Coastguard Worker 
287*9356374aSAndroid Build Coastguard Worker   // FixedArray::begin()
288*9356374aSAndroid Build Coastguard Worker   //
289*9356374aSAndroid Build Coastguard Worker   // Returns an iterator to the beginning of the fixed array.
begin()290*9356374aSAndroid Build Coastguard Worker   iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
291*9356374aSAndroid Build Coastguard Worker 
292*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::begin() to return a const iterator to the
293*9356374aSAndroid Build Coastguard Worker   // beginning of the fixed array.
begin()294*9356374aSAndroid Build Coastguard Worker   const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
295*9356374aSAndroid Build Coastguard Worker 
296*9356374aSAndroid Build Coastguard Worker   // FixedArray::cbegin()
297*9356374aSAndroid Build Coastguard Worker   //
298*9356374aSAndroid Build Coastguard Worker   // Returns a const iterator to the beginning of the fixed array.
cbegin()299*9356374aSAndroid Build Coastguard Worker   const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
300*9356374aSAndroid Build Coastguard Worker     return begin();
301*9356374aSAndroid Build Coastguard Worker   }
302*9356374aSAndroid Build Coastguard Worker 
303*9356374aSAndroid Build Coastguard Worker   // FixedArray::end()
304*9356374aSAndroid Build Coastguard Worker   //
305*9356374aSAndroid Build Coastguard Worker   // Returns an iterator to the end of the fixed array.
end()306*9356374aSAndroid Build Coastguard Worker   iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return data() + size(); }
307*9356374aSAndroid Build Coastguard Worker 
308*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::end() to return a const iterator to the end of the
309*9356374aSAndroid Build Coastguard Worker   // fixed array.
end()310*9356374aSAndroid Build Coastguard Worker   const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
311*9356374aSAndroid Build Coastguard Worker     return data() + size();
312*9356374aSAndroid Build Coastguard Worker   }
313*9356374aSAndroid Build Coastguard Worker 
314*9356374aSAndroid Build Coastguard Worker   // FixedArray::cend()
315*9356374aSAndroid Build Coastguard Worker   //
316*9356374aSAndroid Build Coastguard Worker   // Returns a const iterator to the end of the fixed array.
cend()317*9356374aSAndroid Build Coastguard Worker   const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
318*9356374aSAndroid Build Coastguard Worker 
319*9356374aSAndroid Build Coastguard Worker   // FixedArray::rbegin()
320*9356374aSAndroid Build Coastguard Worker   //
321*9356374aSAndroid Build Coastguard Worker   // Returns a reverse iterator from the end of the fixed array.
rbegin()322*9356374aSAndroid Build Coastguard Worker   reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
323*9356374aSAndroid Build Coastguard Worker     return reverse_iterator(end());
324*9356374aSAndroid Build Coastguard Worker   }
325*9356374aSAndroid Build Coastguard Worker 
326*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::rbegin() to return a const reverse iterator from
327*9356374aSAndroid Build Coastguard Worker   // the end of the fixed array.
rbegin()328*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
329*9356374aSAndroid Build Coastguard Worker     return const_reverse_iterator(end());
330*9356374aSAndroid Build Coastguard Worker   }
331*9356374aSAndroid Build Coastguard Worker 
332*9356374aSAndroid Build Coastguard Worker   // FixedArray::crbegin()
333*9356374aSAndroid Build Coastguard Worker   //
334*9356374aSAndroid Build Coastguard Worker   // Returns a const reverse iterator from the end of the fixed array.
crbegin()335*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
336*9356374aSAndroid Build Coastguard Worker     return rbegin();
337*9356374aSAndroid Build Coastguard Worker   }
338*9356374aSAndroid Build Coastguard Worker 
339*9356374aSAndroid Build Coastguard Worker   // FixedArray::rend()
340*9356374aSAndroid Build Coastguard Worker   //
341*9356374aSAndroid Build Coastguard Worker   // Returns a reverse iterator from the beginning of the fixed array.
rend()342*9356374aSAndroid Build Coastguard Worker   reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND {
343*9356374aSAndroid Build Coastguard Worker     return reverse_iterator(begin());
344*9356374aSAndroid Build Coastguard Worker   }
345*9356374aSAndroid Build Coastguard Worker 
346*9356374aSAndroid Build Coastguard Worker   // Overload of FixedArray::rend() for returning a const reverse iterator
347*9356374aSAndroid Build Coastguard Worker   // from the beginning of the fixed array.
rend()348*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
349*9356374aSAndroid Build Coastguard Worker     return const_reverse_iterator(begin());
350*9356374aSAndroid Build Coastguard Worker   }
351*9356374aSAndroid Build Coastguard Worker 
352*9356374aSAndroid Build Coastguard Worker   // FixedArray::crend()
353*9356374aSAndroid Build Coastguard Worker   //
354*9356374aSAndroid Build Coastguard Worker   // Returns a reverse iterator from the beginning of the fixed array.
crend()355*9356374aSAndroid Build Coastguard Worker   const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
356*9356374aSAndroid Build Coastguard Worker     return rend();
357*9356374aSAndroid Build Coastguard Worker   }
358*9356374aSAndroid Build Coastguard Worker 
359*9356374aSAndroid Build Coastguard Worker   // FixedArray::fill()
360*9356374aSAndroid Build Coastguard Worker   //
361*9356374aSAndroid Build Coastguard Worker   // Assigns the given `value` to all elements in the fixed array.
fill(const value_type & val)362*9356374aSAndroid Build Coastguard Worker   void fill(const value_type& val) { std::fill(begin(), end(), val); }
363*9356374aSAndroid Build Coastguard Worker 
364*9356374aSAndroid Build Coastguard Worker   // Relational operators. Equality operators are elementwise using
365*9356374aSAndroid Build Coastguard Worker   // `operator==`, while order operators order FixedArrays lexicographically.
366*9356374aSAndroid Build Coastguard Worker   friend bool operator==(const FixedArray& lhs, const FixedArray& rhs) {
367*9356374aSAndroid Build Coastguard Worker     return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
368*9356374aSAndroid Build Coastguard Worker   }
369*9356374aSAndroid Build Coastguard Worker 
370*9356374aSAndroid Build Coastguard Worker   friend bool operator!=(const FixedArray& lhs, const FixedArray& rhs) {
371*9356374aSAndroid Build Coastguard Worker     return !(lhs == rhs);
372*9356374aSAndroid Build Coastguard Worker   }
373*9356374aSAndroid Build Coastguard Worker 
374*9356374aSAndroid Build Coastguard Worker   friend bool operator<(const FixedArray& lhs, const FixedArray& rhs) {
375*9356374aSAndroid Build Coastguard Worker     return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
376*9356374aSAndroid Build Coastguard Worker                                         rhs.end());
377*9356374aSAndroid Build Coastguard Worker   }
378*9356374aSAndroid Build Coastguard Worker 
379*9356374aSAndroid Build Coastguard Worker   friend bool operator>(const FixedArray& lhs, const FixedArray& rhs) {
380*9356374aSAndroid Build Coastguard Worker     return rhs < lhs;
381*9356374aSAndroid Build Coastguard Worker   }
382*9356374aSAndroid Build Coastguard Worker 
383*9356374aSAndroid Build Coastguard Worker   friend bool operator<=(const FixedArray& lhs, const FixedArray& rhs) {
384*9356374aSAndroid Build Coastguard Worker     return !(rhs < lhs);
385*9356374aSAndroid Build Coastguard Worker   }
386*9356374aSAndroid Build Coastguard Worker 
387*9356374aSAndroid Build Coastguard Worker   friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
388*9356374aSAndroid Build Coastguard Worker     return !(lhs < rhs);
389*9356374aSAndroid Build Coastguard Worker   }
390*9356374aSAndroid Build Coastguard Worker 
391*9356374aSAndroid Build Coastguard Worker   template <typename H>
AbslHashValue(H h,const FixedArray & v)392*9356374aSAndroid Build Coastguard Worker   friend H AbslHashValue(H h, const FixedArray& v) {
393*9356374aSAndroid Build Coastguard Worker     return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
394*9356374aSAndroid Build Coastguard Worker                       v.size());
395*9356374aSAndroid Build Coastguard Worker   }
396*9356374aSAndroid Build Coastguard Worker 
397*9356374aSAndroid Build Coastguard Worker  private:
398*9356374aSAndroid Build Coastguard Worker   // StorageElement
399*9356374aSAndroid Build Coastguard Worker   //
400*9356374aSAndroid Build Coastguard Worker   // For FixedArrays with a C-style-array value_type, StorageElement is a POD
401*9356374aSAndroid Build Coastguard Worker   // wrapper struct called StorageElementWrapper that holds the value_type
402*9356374aSAndroid Build Coastguard Worker   // instance inside. This is needed for construction and destruction of the
403*9356374aSAndroid Build Coastguard Worker   // entire array regardless of how many dimensions it has. For all other cases,
404*9356374aSAndroid Build Coastguard Worker   // StorageElement is just an alias of value_type.
405*9356374aSAndroid Build Coastguard Worker   //
406*9356374aSAndroid Build Coastguard Worker   // Maintainer's Note: The simpler solution would be to simply wrap value_type
407*9356374aSAndroid Build Coastguard Worker   // in a struct whether it's an array or not. That causes some paranoid
408*9356374aSAndroid Build Coastguard Worker   // diagnostics to misfire, believing that 'data()' returns a pointer to a
409*9356374aSAndroid Build Coastguard Worker   // single element, rather than the packed array that it really is.
410*9356374aSAndroid Build Coastguard Worker   // e.g.:
411*9356374aSAndroid Build Coastguard Worker   //
412*9356374aSAndroid Build Coastguard Worker   //     FixedArray<char> buf(1);
413*9356374aSAndroid Build Coastguard Worker   //     sprintf(buf.data(), "foo");
414*9356374aSAndroid Build Coastguard Worker   //
415*9356374aSAndroid Build Coastguard Worker   //     error: call to int __builtin___sprintf_chk(etc...)
416*9356374aSAndroid Build Coastguard Worker   //     will always overflow destination buffer [-Werror]
417*9356374aSAndroid Build Coastguard Worker   //
418*9356374aSAndroid Build Coastguard Worker   template <typename OuterT, typename InnerT = absl::remove_extent_t<OuterT>,
419*9356374aSAndroid Build Coastguard Worker             size_t InnerN = std::extent<OuterT>::value>
420*9356374aSAndroid Build Coastguard Worker   struct StorageElementWrapper {
421*9356374aSAndroid Build Coastguard Worker     InnerT array[InnerN];
422*9356374aSAndroid Build Coastguard Worker   };
423*9356374aSAndroid Build Coastguard Worker 
424*9356374aSAndroid Build Coastguard Worker   using StorageElement =
425*9356374aSAndroid Build Coastguard Worker       absl::conditional_t<std::is_array<value_type>::value,
426*9356374aSAndroid Build Coastguard Worker                           StorageElementWrapper<value_type>, value_type>;
427*9356374aSAndroid Build Coastguard Worker 
AsValueType(pointer ptr)428*9356374aSAndroid Build Coastguard Worker   static pointer AsValueType(pointer ptr) { return ptr; }
AsValueType(StorageElementWrapper<value_type> * ptr)429*9356374aSAndroid Build Coastguard Worker   static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
430*9356374aSAndroid Build Coastguard Worker     return std::addressof(ptr->array);
431*9356374aSAndroid Build Coastguard Worker   }
432*9356374aSAndroid Build Coastguard Worker 
433*9356374aSAndroid Build Coastguard Worker   static_assert(sizeof(StorageElement) == sizeof(value_type), "");
434*9356374aSAndroid Build Coastguard Worker   static_assert(alignof(StorageElement) == alignof(value_type), "");
435*9356374aSAndroid Build Coastguard Worker 
436*9356374aSAndroid Build Coastguard Worker   class NonEmptyInlinedStorage {
437*9356374aSAndroid Build Coastguard Worker    public:
data()438*9356374aSAndroid Build Coastguard Worker     StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
439*9356374aSAndroid Build Coastguard Worker     void AnnotateConstruct(size_type n);
440*9356374aSAndroid Build Coastguard Worker     void AnnotateDestruct(size_type n);
441*9356374aSAndroid Build Coastguard Worker 
442*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_ADDRESS_SANITIZER
RedzoneBegin()443*9356374aSAndroid Build Coastguard Worker     void* RedzoneBegin() { return &redzone_begin_; }
RedzoneEnd()444*9356374aSAndroid Build Coastguard Worker     void* RedzoneEnd() { return &redzone_end_ + 1; }
445*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_HAVE_ADDRESS_SANITIZER
446*9356374aSAndroid Build Coastguard Worker 
447*9356374aSAndroid Build Coastguard Worker    private:
448*9356374aSAndroid Build Coastguard Worker     ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
449*9356374aSAndroid Build Coastguard Worker     alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
450*9356374aSAndroid Build Coastguard Worker     ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
451*9356374aSAndroid Build Coastguard Worker   };
452*9356374aSAndroid Build Coastguard Worker 
453*9356374aSAndroid Build Coastguard Worker   class EmptyInlinedStorage {
454*9356374aSAndroid Build Coastguard Worker    public:
data()455*9356374aSAndroid Build Coastguard Worker     StorageElement* data() { return nullptr; }
AnnotateConstruct(size_type)456*9356374aSAndroid Build Coastguard Worker     void AnnotateConstruct(size_type) {}
AnnotateDestruct(size_type)457*9356374aSAndroid Build Coastguard Worker     void AnnotateDestruct(size_type) {}
458*9356374aSAndroid Build Coastguard Worker   };
459*9356374aSAndroid Build Coastguard Worker 
460*9356374aSAndroid Build Coastguard Worker   using InlinedStorage =
461*9356374aSAndroid Build Coastguard Worker       absl::conditional_t<inline_elements == 0, EmptyInlinedStorage,
462*9356374aSAndroid Build Coastguard Worker                           NonEmptyInlinedStorage>;
463*9356374aSAndroid Build Coastguard Worker 
464*9356374aSAndroid Build Coastguard Worker   // Storage
465*9356374aSAndroid Build Coastguard Worker   //
466*9356374aSAndroid Build Coastguard Worker   // An instance of Storage manages the inline and out-of-line memory for
467*9356374aSAndroid Build Coastguard Worker   // instances of FixedArray. This guarantees that even when construction of
468*9356374aSAndroid Build Coastguard Worker   // individual elements fails in the FixedArray constructor body, the
469*9356374aSAndroid Build Coastguard Worker   // destructor for Storage will still be called and out-of-line memory will be
470*9356374aSAndroid Build Coastguard Worker   // properly deallocated.
471*9356374aSAndroid Build Coastguard Worker   //
472*9356374aSAndroid Build Coastguard Worker   class Storage : public InlinedStorage {
473*9356374aSAndroid Build Coastguard Worker    public:
Storage(size_type n,const allocator_type & a)474*9356374aSAndroid Build Coastguard Worker     Storage(size_type n, const allocator_type& a)
475*9356374aSAndroid Build Coastguard Worker         : size_alloc_(n, a), data_(InitializeData()) {}
476*9356374aSAndroid Build Coastguard Worker 
~Storage()477*9356374aSAndroid Build Coastguard Worker     ~Storage() noexcept {
478*9356374aSAndroid Build Coastguard Worker       if (UsingInlinedStorage(size())) {
479*9356374aSAndroid Build Coastguard Worker         InlinedStorage::AnnotateDestruct(size());
480*9356374aSAndroid Build Coastguard Worker       } else {
481*9356374aSAndroid Build Coastguard Worker         AllocatorTraits::deallocate(alloc(), AsValueType(begin()), size());
482*9356374aSAndroid Build Coastguard Worker       }
483*9356374aSAndroid Build Coastguard Worker     }
484*9356374aSAndroid Build Coastguard Worker 
size()485*9356374aSAndroid Build Coastguard Worker     size_type size() const { return size_alloc_.template get<0>(); }
begin()486*9356374aSAndroid Build Coastguard Worker     StorageElement* begin() const { return data_; }
end()487*9356374aSAndroid Build Coastguard Worker     StorageElement* end() const { return begin() + size(); }
alloc()488*9356374aSAndroid Build Coastguard Worker     allocator_type& alloc() { return size_alloc_.template get<1>(); }
alloc()489*9356374aSAndroid Build Coastguard Worker     const allocator_type& alloc() const {
490*9356374aSAndroid Build Coastguard Worker       return size_alloc_.template get<1>();
491*9356374aSAndroid Build Coastguard Worker     }
492*9356374aSAndroid Build Coastguard Worker 
493*9356374aSAndroid Build Coastguard Worker    private:
UsingInlinedStorage(size_type n)494*9356374aSAndroid Build Coastguard Worker     static bool UsingInlinedStorage(size_type n) {
495*9356374aSAndroid Build Coastguard Worker       return n <= inline_elements;
496*9356374aSAndroid Build Coastguard Worker     }
497*9356374aSAndroid Build Coastguard Worker 
498*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_ADDRESS_SANITIZER
499*9356374aSAndroid Build Coastguard Worker     ABSL_ATTRIBUTE_NOINLINE
500*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_HAVE_ADDRESS_SANITIZER
InitializeData()501*9356374aSAndroid Build Coastguard Worker     StorageElement* InitializeData() {
502*9356374aSAndroid Build Coastguard Worker       if (UsingInlinedStorage(size())) {
503*9356374aSAndroid Build Coastguard Worker         InlinedStorage::AnnotateConstruct(size());
504*9356374aSAndroid Build Coastguard Worker         return InlinedStorage::data();
505*9356374aSAndroid Build Coastguard Worker       } else {
506*9356374aSAndroid Build Coastguard Worker         return reinterpret_cast<StorageElement*>(
507*9356374aSAndroid Build Coastguard Worker             AllocatorTraits::allocate(alloc(), size()));
508*9356374aSAndroid Build Coastguard Worker       }
509*9356374aSAndroid Build Coastguard Worker     }
510*9356374aSAndroid Build Coastguard Worker 
511*9356374aSAndroid Build Coastguard Worker     // `CompressedTuple` takes advantage of EBCO for stateless `allocator_type`s
512*9356374aSAndroid Build Coastguard Worker     container_internal::CompressedTuple<size_type, allocator_type> size_alloc_;
513*9356374aSAndroid Build Coastguard Worker     StorageElement* data_;
514*9356374aSAndroid Build Coastguard Worker   };
515*9356374aSAndroid Build Coastguard Worker 
516*9356374aSAndroid Build Coastguard Worker   Storage storage_;
517*9356374aSAndroid Build Coastguard Worker };
518*9356374aSAndroid Build Coastguard Worker 
519*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
520*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
521*9356374aSAndroid Build Coastguard Worker constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
522*9356374aSAndroid Build Coastguard Worker 
523*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
524*9356374aSAndroid Build Coastguard Worker constexpr typename FixedArray<T, N, A>::size_type
525*9356374aSAndroid Build Coastguard Worker     FixedArray<T, N, A>::inline_elements;
526*9356374aSAndroid Build Coastguard Worker #endif
527*9356374aSAndroid Build Coastguard Worker 
528*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
AnnotateConstruct(typename FixedArray<T,N,A>::size_type n)529*9356374aSAndroid Build Coastguard Worker void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
530*9356374aSAndroid Build Coastguard Worker     typename FixedArray<T, N, A>::size_type n) {
531*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_ADDRESS_SANITIZER
532*9356374aSAndroid Build Coastguard Worker   if (!n) return;
533*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(),
534*9356374aSAndroid Build Coastguard Worker                                      data() + n);
535*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(),
536*9356374aSAndroid Build Coastguard Worker                                      RedzoneBegin());
537*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_HAVE_ADDRESS_SANITIZER
538*9356374aSAndroid Build Coastguard Worker   static_cast<void>(n);  // Mark used when not in asan mode
539*9356374aSAndroid Build Coastguard Worker }
540*9356374aSAndroid Build Coastguard Worker 
541*9356374aSAndroid Build Coastguard Worker template <typename T, size_t N, typename A>
AnnotateDestruct(typename FixedArray<T,N,A>::size_type n)542*9356374aSAndroid Build Coastguard Worker void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
543*9356374aSAndroid Build Coastguard Worker     typename FixedArray<T, N, A>::size_type n) {
544*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_HAVE_ADDRESS_SANITIZER
545*9356374aSAndroid Build Coastguard Worker   if (!n) return;
546*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n,
547*9356374aSAndroid Build Coastguard Worker                                      RedzoneEnd());
548*9356374aSAndroid Build Coastguard Worker   ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(),
549*9356374aSAndroid Build Coastguard Worker                                      data());
550*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_HAVE_ADDRESS_SANITIZER
551*9356374aSAndroid Build Coastguard Worker   static_cast<void>(n);  // Mark used when not in asan mode
552*9356374aSAndroid Build Coastguard Worker }
553*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
554*9356374aSAndroid Build Coastguard Worker }  // namespace absl
555*9356374aSAndroid Build Coastguard Worker 
556*9356374aSAndroid Build Coastguard Worker #endif  // ABSL_CONTAINER_FIXED_ARRAY_H_
557