1*280ddee8SMarshall Clow //===-------------------------- cxa_vector.cpp ---------------------------===//
2*280ddee8SMarshall Clow //
3*280ddee8SMarshall Clow //                     The LLVM Compiler Infrastructure
4*280ddee8SMarshall Clow //
5*280ddee8SMarshall Clow // This file is dual licensed under the MIT and the University of Illinois Open
6*280ddee8SMarshall Clow // Source Licenses. See LICENSE.TXT for details.
7*280ddee8SMarshall Clow //
8*280ddee8SMarshall Clow //
9*280ddee8SMarshall Clow //  This file implements the "Array Construction and Destruction APIs"
10*280ddee8SMarshall Clow //  http://www.codesourcery.com/public/cxx-abi/abi.html#array-ctor
11*280ddee8SMarshall Clow //
12*280ddee8SMarshall Clow //===----------------------------------------------------------------------===//
13*280ddee8SMarshall Clow 
14*280ddee8SMarshall Clow #include "cxxabi.h"
15*280ddee8SMarshall Clow 
16*280ddee8SMarshall Clow #include <exception>        // for std::terminate
17*280ddee8SMarshall Clow 
18*280ddee8SMarshall Clow namespace __cxxabiv1 {
19*280ddee8SMarshall Clow 
20*280ddee8SMarshall Clow #pragma mark --Helper routines and classes --
21*280ddee8SMarshall Clow 
22*280ddee8SMarshall Clow namespace {
23*280ddee8SMarshall Clow     inline static size_t __get_element_count ( void *p ) {
24*280ddee8SMarshall Clow         return static_cast <size_t *> (p)[-1];
25*280ddee8SMarshall Clow         }
26*280ddee8SMarshall Clow 
27*280ddee8SMarshall Clow     inline static void __set_element_count ( void *p, size_t element_count ) {
28*280ddee8SMarshall Clow         static_cast <size_t *> (p)[-1] = element_count;
29*280ddee8SMarshall Clow         }
30*280ddee8SMarshall Clow 
31*280ddee8SMarshall Clow 
32*280ddee8SMarshall Clow //  A pair of classes to simplify exception handling and control flow.
33*280ddee8SMarshall Clow //  They get passed a block of memory in the constructor, and unless the
34*280ddee8SMarshall Clow //  'release' method is called, they deallocate the memory in the destructor.
35*280ddee8SMarshall Clow //  Prefered usage is to allocate some memory, attach it to one of these objects,
36*280ddee8SMarshall Clow //  and then, when all the operations to set up the memory block have succeeded,
37*280ddee8SMarshall Clow //  call 'release'. If any of the setup operations fail, or an exception is
38*280ddee8SMarshall Clow //  thrown, then the block is automatically deallocated.
39*280ddee8SMarshall Clow //
40*280ddee8SMarshall Clow //  The only difference between these two classes is the signature for the
41*280ddee8SMarshall Clow //  deallocation function (to match new2/new3 and delete2/delete3.
42*280ddee8SMarshall Clow     class st_heap_block2 {
43*280ddee8SMarshall Clow     public:
44*280ddee8SMarshall Clow         typedef void (*dealloc_f)(void *);
45*280ddee8SMarshall Clow 
46*280ddee8SMarshall Clow         st_heap_block2 ( dealloc_f dealloc, void *ptr )
47*280ddee8SMarshall Clow             : dealloc_ ( dealloc ), ptr_ ( ptr ), enabled_ ( true ) {}
48*280ddee8SMarshall Clow         ~st_heap_block2 () { if ( enabled_ ) dealloc_ ( ptr_ ) ; }
49*280ddee8SMarshall Clow         void release () { enabled_ = false; }
50*280ddee8SMarshall Clow 
51*280ddee8SMarshall Clow     private:
52*280ddee8SMarshall Clow         dealloc_f dealloc_;
53*280ddee8SMarshall Clow         void *ptr_;
54*280ddee8SMarshall Clow         bool enabled_;
55*280ddee8SMarshall Clow     };
56*280ddee8SMarshall Clow 
57*280ddee8SMarshall Clow     class st_heap_block3 {
58*280ddee8SMarshall Clow     public:
59*280ddee8SMarshall Clow         typedef void (*dealloc_f)(void *, size_t);
60*280ddee8SMarshall Clow 
61*280ddee8SMarshall Clow         st_heap_block3 ( dealloc_f dealloc, void *ptr, size_t size )
62*280ddee8SMarshall Clow             : dealloc_ ( dealloc ), ptr_ ( ptr ), size_ ( size ), enabled_ ( true ) {}
63*280ddee8SMarshall Clow         ~st_heap_block3 () { if ( enabled_ ) dealloc_ ( ptr_, size_ ) ; }
64*280ddee8SMarshall Clow         void release () { enabled_ = false; }
65*280ddee8SMarshall Clow 
66*280ddee8SMarshall Clow     private:
67*280ddee8SMarshall Clow         dealloc_f dealloc_;
68*280ddee8SMarshall Clow         void *ptr_;
69*280ddee8SMarshall Clow         size_t size_;
70*280ddee8SMarshall Clow         bool enabled_;
71*280ddee8SMarshall Clow     };
72*280ddee8SMarshall Clow 
73*280ddee8SMarshall Clow     class st_cxa_cleanup {
74*280ddee8SMarshall Clow     public:
75*280ddee8SMarshall Clow         typedef void (*destruct_f)(void *);
76*280ddee8SMarshall Clow 
77*280ddee8SMarshall Clow         st_cxa_cleanup ( void *ptr, size_t &idx, size_t element_size, destruct_f destructor )
78*280ddee8SMarshall Clow             : ptr_ ( ptr ), idx_ ( idx ), element_size_ ( element_size ),
79*280ddee8SMarshall Clow                 destructor_ ( destructor ), enabled_ ( true ) {}
80*280ddee8SMarshall Clow         ~st_cxa_cleanup () {
81*280ddee8SMarshall Clow             if ( enabled_ )
82*280ddee8SMarshall Clow                 __cxa_vec_cleanup ( ptr_, idx_, element_size_, destructor_ );
83*280ddee8SMarshall Clow             }
84*280ddee8SMarshall Clow 
85*280ddee8SMarshall Clow         void release () { enabled_ = false; }
86*280ddee8SMarshall Clow 
87*280ddee8SMarshall Clow     private:
88*280ddee8SMarshall Clow         void *ptr_;
89*280ddee8SMarshall Clow         size_t &idx_;
90*280ddee8SMarshall Clow         size_t element_size_;
91*280ddee8SMarshall Clow         destruct_f destructor_;
92*280ddee8SMarshall Clow         bool enabled_;
93*280ddee8SMarshall Clow     };
94*280ddee8SMarshall Clow 
95*280ddee8SMarshall Clow     class st_terminate {
96*280ddee8SMarshall Clow     public:
97*280ddee8SMarshall Clow         st_terminate ( bool enabled = true ) : enabled_ ( enabled ) {}
98*280ddee8SMarshall Clow         ~st_terminate () { if ( enabled_ ) std::terminate (); }
99*280ddee8SMarshall Clow         void release () { enabled_ = false; }
100*280ddee8SMarshall Clow     private:
101*280ddee8SMarshall Clow         bool enabled_ ;
102*280ddee8SMarshall Clow     };
103*280ddee8SMarshall Clow }
104*280ddee8SMarshall Clow 
105*280ddee8SMarshall Clow #pragma mark --Externally visible routines--
106*280ddee8SMarshall Clow 
107*280ddee8SMarshall Clow extern "C" {
108*280ddee8SMarshall Clow 
109*280ddee8SMarshall Clow // Equivalent to
110*280ddee8SMarshall Clow //
111*280ddee8SMarshall Clow //   __cxa_vec_new2(element_count, element_size, padding_size, constructor,
112*280ddee8SMarshall Clow //                  destructor, &::operator new[], &::operator delete[])
113*280ddee8SMarshall Clow void* __cxa_vec_new(
114*280ddee8SMarshall Clow     size_t element_count, size_t element_size, size_t padding_size,
115*280ddee8SMarshall Clow         void (*constructor)(void*), void (*destructor)(void*) ) {
116*280ddee8SMarshall Clow 
117*280ddee8SMarshall Clow     return __cxa_vec_new2 ( element_count, element_size, padding_size,
118*280ddee8SMarshall Clow         constructor, destructor, &::operator new [], &::operator delete [] );
119*280ddee8SMarshall Clow }
120*280ddee8SMarshall Clow 
121*280ddee8SMarshall Clow 
122*280ddee8SMarshall Clow 
123*280ddee8SMarshall Clow // Given the number and size of elements for an array and the non-negative
124*280ddee8SMarshall Clow // size of prefix padding for a cookie, allocate space (using alloc) for
125*280ddee8SMarshall Clow // the array preceded by the specified padding, initialize the cookie if
126*280ddee8SMarshall Clow // the padding is non-zero, and call the given constructor on each element.
127*280ddee8SMarshall Clow // Return the address of the array proper, after the padding.
128*280ddee8SMarshall Clow //
129*280ddee8SMarshall Clow // If alloc throws an exception, rethrow the exception. If alloc returns
130*280ddee8SMarshall Clow // NULL, return NULL. If the constructor throws an exception, call
131*280ddee8SMarshall Clow // destructor for any already constructed elements, and rethrow the
132*280ddee8SMarshall Clow // exception. If the destructor throws an exception, call std::terminate.
133*280ddee8SMarshall Clow //
134*280ddee8SMarshall Clow // The constructor may be NULL, in which case it must not be called. If the
135*280ddee8SMarshall Clow // padding_size is zero, the destructor may be NULL; in that case it must
136*280ddee8SMarshall Clow // not be called.
137*280ddee8SMarshall Clow //
138*280ddee8SMarshall Clow // Neither alloc nor dealloc may be NULL.
139*280ddee8SMarshall Clow void* __cxa_vec_new2(
140*280ddee8SMarshall Clow     size_t element_count, size_t element_size, size_t padding_size,
141*280ddee8SMarshall Clow         void  (*constructor)(void*), void  (*destructor)(void*),
142*280ddee8SMarshall Clow         void* (*alloc)(size_t), void  (*dealloc)(void*) ) {
143*280ddee8SMarshall Clow 
144*280ddee8SMarshall Clow     const size_t heap_size = element_count * element_size + padding_size;
145*280ddee8SMarshall Clow     char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
146*280ddee8SMarshall Clow     char *vec_base = heap_block;
147*280ddee8SMarshall Clow 
148*280ddee8SMarshall Clow     if ( NULL != vec_base ) {
149*280ddee8SMarshall Clow         st_heap_block2 heap ( dealloc, heap_block );
150*280ddee8SMarshall Clow 
151*280ddee8SMarshall Clow     //  put the padding before the array elements
152*280ddee8SMarshall Clow         if ( 0 != padding_size ) {
153*280ddee8SMarshall Clow             vec_base += padding_size;
154*280ddee8SMarshall Clow             __set_element_count ( vec_base, element_count );
155*280ddee8SMarshall Clow         }
156*280ddee8SMarshall Clow 
157*280ddee8SMarshall Clow     //  Construct the elements
158*280ddee8SMarshall Clow         __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor );
159*280ddee8SMarshall Clow         heap.release ();    // We're good!
160*280ddee8SMarshall Clow     }
161*280ddee8SMarshall Clow 
162*280ddee8SMarshall Clow     return vec_base;
163*280ddee8SMarshall Clow }
164*280ddee8SMarshall Clow 
165*280ddee8SMarshall Clow 
166*280ddee8SMarshall Clow // Same as __cxa_vec_new2 except that the deallocation function takes both
167*280ddee8SMarshall Clow // the object address and its size.
168*280ddee8SMarshall Clow void* __cxa_vec_new3(
169*280ddee8SMarshall Clow     size_t element_count, size_t element_size, size_t padding_size,
170*280ddee8SMarshall Clow         void  (*constructor)(void*), void  (*destructor)(void*),
171*280ddee8SMarshall Clow         void* (*alloc)(size_t), void  (*dealloc)(void*, size_t) ) {
172*280ddee8SMarshall Clow 
173*280ddee8SMarshall Clow     const size_t heap_size = element_count * element_size + padding_size;
174*280ddee8SMarshall Clow     char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
175*280ddee8SMarshall Clow     char *vec_base = heap_block;
176*280ddee8SMarshall Clow 
177*280ddee8SMarshall Clow     if ( NULL != vec_base ) {
178*280ddee8SMarshall Clow         st_heap_block3 heap ( dealloc, heap_block, heap_size );
179*280ddee8SMarshall Clow 
180*280ddee8SMarshall Clow     //  put the padding before the array elements
181*280ddee8SMarshall Clow         if ( 0 != padding_size ) {
182*280ddee8SMarshall Clow             vec_base += padding_size;
183*280ddee8SMarshall Clow             __set_element_count ( vec_base, element_count );
184*280ddee8SMarshall Clow         }
185*280ddee8SMarshall Clow 
186*280ddee8SMarshall Clow     //  Construct the elements
187*280ddee8SMarshall Clow         __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor );
188*280ddee8SMarshall Clow         heap.release ();    // We're good!
189*280ddee8SMarshall Clow     }
190*280ddee8SMarshall Clow 
191*280ddee8SMarshall Clow     return vec_base;
192*280ddee8SMarshall Clow }
193*280ddee8SMarshall Clow 
194*280ddee8SMarshall Clow 
195*280ddee8SMarshall Clow // Given the (data) addresses of a destination and a source array, an
196*280ddee8SMarshall Clow // element count and an element size, call the given copy constructor to
197*280ddee8SMarshall Clow // copy each element from the source array to the destination array. The
198*280ddee8SMarshall Clow // copy constructor's arguments are the destination address and source
199*280ddee8SMarshall Clow // address, respectively. If an exception occurs, call the given destructor
200*280ddee8SMarshall Clow // (if non-NULL) on each copied element and rethrow. If the destructor
201*280ddee8SMarshall Clow // throws an exception, call terminate(). The constructor and or destructor
202*280ddee8SMarshall Clow // pointers may be NULL. If either is NULL, no action is taken when it
203*280ddee8SMarshall Clow // would have been called.
204*280ddee8SMarshall Clow 
205*280ddee8SMarshall Clow void __cxa_vec_cctor( void*  dest_array, void*  src_array,
206*280ddee8SMarshall Clow     size_t element_count, size_t element_size,
207*280ddee8SMarshall Clow         void  (*constructor) (void*, void*), void  (*destructor)(void*) ) {
208*280ddee8SMarshall Clow 
209*280ddee8SMarshall Clow     if ( NULL != constructor ) {
210*280ddee8SMarshall Clow         size_t idx = 0;
211*280ddee8SMarshall Clow         char *src_ptr  = static_cast<char *>(src_array);
212*280ddee8SMarshall Clow         char *dest_ptr = static_cast<char *>(dest_array);
213*280ddee8SMarshall Clow         st_cxa_cleanup cleanup ( dest_array, idx, element_size, destructor );
214*280ddee8SMarshall Clow 
215*280ddee8SMarshall Clow         for ( idx = 0; idx < element_count;
216*280ddee8SMarshall Clow                     ++idx, src_ptr += element_size, dest_ptr += element_size )
217*280ddee8SMarshall Clow             constructor ( dest_ptr, src_ptr );
218*280ddee8SMarshall Clow         cleanup.release ();     // We're good!
219*280ddee8SMarshall Clow     }
220*280ddee8SMarshall Clow }
221*280ddee8SMarshall Clow 
222*280ddee8SMarshall Clow 
223*280ddee8SMarshall Clow // Given the (data) address of an array, not including any cookie padding,
224*280ddee8SMarshall Clow // and the number and size of its elements, call the given constructor on
225*280ddee8SMarshall Clow // each element. If the constructor throws an exception, call the given
226*280ddee8SMarshall Clow // destructor for any already-constructed elements, and rethrow the
227*280ddee8SMarshall Clow // exception. If the destructor throws an exception, call terminate(). The
228*280ddee8SMarshall Clow // constructor and/or destructor pointers may be NULL. If either is NULL,
229*280ddee8SMarshall Clow // no action is taken when it would have been called.
230*280ddee8SMarshall Clow void __cxa_vec_ctor(
231*280ddee8SMarshall Clow     void*  array_address, size_t element_count, size_t element_size,
232*280ddee8SMarshall Clow        void (*constructor)(void*), void (*destructor)(void*) ) {
233*280ddee8SMarshall Clow 
234*280ddee8SMarshall Clow     if ( NULL != constructor ) {
235*280ddee8SMarshall Clow         size_t idx;
236*280ddee8SMarshall Clow         char *ptr = static_cast <char *> ( array_address );
237*280ddee8SMarshall Clow         st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor );
238*280ddee8SMarshall Clow 
239*280ddee8SMarshall Clow     //  Construct the elements
240*280ddee8SMarshall Clow         for ( idx = 0; idx < element_count; ++idx, ptr += element_size )
241*280ddee8SMarshall Clow             constructor ( ptr );
242*280ddee8SMarshall Clow         cleanup.release ();     // We're good!
243*280ddee8SMarshall Clow     }
244*280ddee8SMarshall Clow }
245*280ddee8SMarshall Clow 
246*280ddee8SMarshall Clow // Given the (data) address of an array, the number of elements, and the
247*280ddee8SMarshall Clow // size of its elements, call the given destructor on each element. If the
248*280ddee8SMarshall Clow // destructor throws an exception, rethrow after destroying the remaining
249*280ddee8SMarshall Clow // elements if possible. If the destructor throws a second exception, call
250*280ddee8SMarshall Clow // terminate(). The destructor pointer may be NULL, in which case this
251*280ddee8SMarshall Clow // routine does nothing.
252*280ddee8SMarshall Clow void __cxa_vec_dtor(
253*280ddee8SMarshall Clow     void*  array_address, size_t element_count, size_t element_size,
254*280ddee8SMarshall Clow        void (*destructor)(void*) ) {
255*280ddee8SMarshall Clow 
256*280ddee8SMarshall Clow     if ( NULL != destructor ) {
257*280ddee8SMarshall Clow         char *ptr = static_cast <char *> (array_address);
258*280ddee8SMarshall Clow         size_t idx = element_count;
259*280ddee8SMarshall Clow         st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor );
260*280ddee8SMarshall Clow         {
261*280ddee8SMarshall Clow             st_terminate exception_guard (std::uncaught_exception ());
262*280ddee8SMarshall Clow             ptr +=  element_count * element_size;   // one past the last element
263*280ddee8SMarshall Clow 
264*280ddee8SMarshall Clow             while ( idx-- > 0 ) {
265*280ddee8SMarshall Clow                 ptr -= element_size;
266*280ddee8SMarshall Clow                 destructor ( ptr );
267*280ddee8SMarshall Clow             }
268*280ddee8SMarshall Clow             exception_guard.release (); //  We're good !
269*280ddee8SMarshall Clow         }
270*280ddee8SMarshall Clow         cleanup.release ();     // We're still good!
271*280ddee8SMarshall Clow     }
272*280ddee8SMarshall Clow }
273*280ddee8SMarshall Clow 
274*280ddee8SMarshall Clow // Given the (data) address of an array, the number of elements, and the
275*280ddee8SMarshall Clow // size of its elements, call the given destructor on each element. If the
276*280ddee8SMarshall Clow // destructor throws an exception, call terminate(). The destructor pointer
277*280ddee8SMarshall Clow // may be NULL, in which case this routine does nothing.
278*280ddee8SMarshall Clow void __cxa_vec_cleanup( void* array_address, size_t element_count,
279*280ddee8SMarshall Clow         size_t element_size, void  (*destructor)(void*) ) {
280*280ddee8SMarshall Clow 
281*280ddee8SMarshall Clow     if ( NULL != destructor ) {
282*280ddee8SMarshall Clow         char *ptr = static_cast <char *> (array_address);
283*280ddee8SMarshall Clow         size_t idx = element_count;
284*280ddee8SMarshall Clow         st_terminate exception_guard;
285*280ddee8SMarshall Clow 
286*280ddee8SMarshall Clow         ptr += element_count * element_size;    // one past the last element
287*280ddee8SMarshall Clow         while ( idx-- > 0 ) {
288*280ddee8SMarshall Clow             ptr -= element_size;
289*280ddee8SMarshall Clow             destructor ( ptr );
290*280ddee8SMarshall Clow             }
291*280ddee8SMarshall Clow         exception_guard.release ();     // We're done!
292*280ddee8SMarshall Clow     }
293*280ddee8SMarshall Clow }
294*280ddee8SMarshall Clow 
295*280ddee8SMarshall Clow 
296*280ddee8SMarshall Clow // If the array_address is NULL, return immediately. Otherwise, given the
297*280ddee8SMarshall Clow // (data) address of an array, the non-negative size of prefix padding for
298*280ddee8SMarshall Clow // the cookie, and the size of its elements, call the given destructor on
299*280ddee8SMarshall Clow // each element, using the cookie to determine the number of elements, and
300*280ddee8SMarshall Clow // then delete the space by calling ::operator delete[](void *). If the
301*280ddee8SMarshall Clow // destructor throws an exception, rethrow after (a) destroying the
302*280ddee8SMarshall Clow // remaining elements, and (b) deallocating the storage. If the destructor
303*280ddee8SMarshall Clow // throws a second exception, call terminate(). If padding_size is 0, the
304*280ddee8SMarshall Clow // destructor pointer must be NULL. If the destructor pointer is NULL, no
305*280ddee8SMarshall Clow // destructor call is to be made.
306*280ddee8SMarshall Clow //
307*280ddee8SMarshall Clow // The intent of this function is to permit an implementation to call this
308*280ddee8SMarshall Clow // function when confronted with an expression of the form delete[] p in
309*280ddee8SMarshall Clow // the source code, provided that the default deallocation function can be
310*280ddee8SMarshall Clow // used. Therefore, the semantics of this function are consistent with
311*280ddee8SMarshall Clow // those required by the standard. The requirement that the deallocation
312*280ddee8SMarshall Clow // function be called even if the destructor throws an exception derives
313*280ddee8SMarshall Clow // from the resolution to DR 353 to the C++ standard, which was adopted in
314*280ddee8SMarshall Clow // April, 2003.
315*280ddee8SMarshall Clow void __cxa_vec_delete( void* array_address,
316*280ddee8SMarshall Clow         size_t element_size, size_t padding_size, void  (*destructor)(void*) ) {
317*280ddee8SMarshall Clow 
318*280ddee8SMarshall Clow     __cxa_vec_delete2 ( array_address, element_size, padding_size,
319*280ddee8SMarshall Clow                destructor, &::operator delete [] );
320*280ddee8SMarshall Clow }
321*280ddee8SMarshall Clow 
322*280ddee8SMarshall Clow 
323*280ddee8SMarshall Clow // Same as __cxa_vec_delete, except that the given function is used for
324*280ddee8SMarshall Clow // deallocation instead of the default delete function. If dealloc throws
325*280ddee8SMarshall Clow // an exception, the result is undefined. The dealloc pointer may not be
326*280ddee8SMarshall Clow // NULL.
327*280ddee8SMarshall Clow void __cxa_vec_delete2( void* array_address,
328*280ddee8SMarshall Clow         size_t element_size, size_t padding_size,
329*280ddee8SMarshall Clow         void  (*destructor)(void*), void  (*dealloc)(void*) ) {
330*280ddee8SMarshall Clow 
331*280ddee8SMarshall Clow     if ( NULL != array_address ) {
332*280ddee8SMarshall Clow         char *vec_base   = static_cast <char *> (array_address);
333*280ddee8SMarshall Clow         char *heap_block = vec_base - padding_size;
334*280ddee8SMarshall Clow         st_heap_block2 heap ( dealloc, heap_block );
335*280ddee8SMarshall Clow 
336*280ddee8SMarshall Clow         if ( 0 != padding_size && NULL != destructor ) // call the destructors
337*280ddee8SMarshall Clow             __cxa_vec_dtor ( array_address, __get_element_count ( vec_base ),
338*280ddee8SMarshall Clow                                     element_size, destructor );
339*280ddee8SMarshall Clow     }
340*280ddee8SMarshall Clow }
341*280ddee8SMarshall Clow 
342*280ddee8SMarshall Clow 
343*280ddee8SMarshall Clow // Same as __cxa_vec_delete, except that the given function is used for
344*280ddee8SMarshall Clow // deallocation instead of the default delete function. The deallocation
345*280ddee8SMarshall Clow // function takes both the object address and its size. If dealloc throws
346*280ddee8SMarshall Clow // an exception, the result is undefined. The dealloc pointer may not be
347*280ddee8SMarshall Clow // NULL.
348*280ddee8SMarshall Clow void __cxa_vec_delete3( void* array_address,
349*280ddee8SMarshall Clow         size_t element_size, size_t padding_size,
350*280ddee8SMarshall Clow         void  (*destructor)(void*), void  (*dealloc) (void*, size_t)) {
351*280ddee8SMarshall Clow 
352*280ddee8SMarshall Clow     if ( NULL != array_address ) {
353*280ddee8SMarshall Clow         char *vec_base   = static_cast <char *> (array_address);
354*280ddee8SMarshall Clow         char *heap_block = vec_base - padding_size;
355*280ddee8SMarshall Clow         const size_t element_count = padding_size ? __get_element_count ( vec_base ) : 0;
356*280ddee8SMarshall Clow         const size_t heap_block_size = element_size * element_count + padding_size;
357*280ddee8SMarshall Clow         st_heap_block3 heap ( dealloc, heap_block, heap_block_size );
358*280ddee8SMarshall Clow 
359*280ddee8SMarshall Clow         if ( 0 != padding_size && NULL != destructor ) // call the destructors
360*280ddee8SMarshall Clow             __cxa_vec_dtor ( array_address, element_count, element_size, destructor );
361*280ddee8SMarshall Clow     }
362*280ddee8SMarshall Clow }
363*280ddee8SMarshall Clow 
364*280ddee8SMarshall Clow 
365*280ddee8SMarshall Clow }  // extern "C"
366*280ddee8SMarshall Clow 
367*280ddee8SMarshall Clow }  // abi
368