* vec.h: Fix the example use.
[gcc.git] / gcc / vec.h
1 /* Vector API for GNU compiler.
2 Copyright (C) 2004 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22 #ifndef GCC_VEC_H
23 #define GCC_VEC_H
24
25 /* The macros here implement a set of templated vector types and
26 associated interfaces. These templates are implemented with
27 macros, as we're not in C++ land. The interface functions are
28 typesafe and use static inline functions, sometimes backed by
29 out-of-line generic functions. The vectors are designed to
30 interoperate with the GTY machinery.
31
32 Because of the different behaviour of objects and of pointers to
33 objects, there are two flavours. One to deal with a vector of
34 pointers to objects, and one to deal with a vector of objects
35 themselves. Both of these pass pointers to objects around -- in
36 the former case the pointers are stored into the vector and in the
37 latter case the pointers are dereferenced and the objects copied
38 into the vector. Therefore, when using a vector of pointers, the
39 objects pointed to must be long lived, but when dealing with a
40 vector of objects, the source objects need not be.
41
42 The vectors are implemented using the trailing array idiom, thus
43 they are not resizeable without changing the address of the vector
44 object itself. This means you cannot have variables or fields of
45 vector type -- always use a pointer to a vector. The one exception
46 is the final field of a structure, which could be a vector type.
47 You will have to use the embedded_size & embedded_init calls to
48 create such objects, and they will probably not be resizeable (so
49 don't use the 'safe' allocation variants). The trailing array
50 idiom is used (rather than a pointer to an array of data), because,
51 if we allow NULL to also represent an empty vector, empty vectors
52 occupy minimal space in the structure containing them.
53
54 Each operation that increases the number of active elements is
55 available in 'quick' and 'safe' variants. The former presumes that
56 there is sufficient allocated space for the operation to succeed
57 (it aborts if there is not). The latter will reallocate the
58 vector, if needed. Reallocation causes an exponential increase in
59 vector size. If you know you will be adding N elements, it would
60 be more efficient to use the reserve operation before adding the
61 elements with the 'quick' operation.
62
63 You should prefer the push and pop operations, as they append and
64 remove from the end of the vector. If you need to remove several
65 items in one go, use the truncate operation. The insert and remove
66 operations allow you to change elements in the middle of the
67 vector. There are two remove operations, one which preserves the
68 element ordering 'ordered_remove', and one which does not
69 'unordered_remove'. The latter function copies the end element
70 into the removed slot, rather than invoke a memmove operation.
71
72 Vector types are defined using a DEF_VEC_x(TYPEDEF) macro, and
73 variables of vector type are declared using a VEC(TYPEDEF)
74 macro. The 'x' letter indicates whether TYPEDEF is a pointer (P) or
75 object (O) type.
76
77 An example of their use would be,
78
79 DEF_VEC_P(tree); // define a vector of tree pointers. This must
80 // appear at file scope.
81
82 struct my_struct {
83 VEC(tree) *v; // A (pointer to) a vector of tree pointers.
84 };
85
86 struct my_struct *s;
87
88 if (VEC_length(tree,s->v)) { we have some contents }
89 VEC_safe_push(tree,s->v,decl); // append some decl onto the end
90 for (ix = 0; (t = VEC_iterate(tree,s->v,ix)); ix++)
91 { do something with t }
92
93 */
94
95 /* Macros to invoke API calls. A single macro works for both pointer
96 and object vectors, but the argument and return types might well be
97 different. In each macro, TDEF is the typedef of the vector
98 elements. Some of these macros pass the vector, V, by reference
99 (by taking its address), this is noted in the descriptions. */
100
101 /* Length of vector
102 size_t VEC_T_length(const VEC(T) *v);
103
104 Return the number of active elements in V. V can be NULL, in which
105 case zero is returned. */
106 #define VEC_length(TDEF,V) (VEC_OP(TDEF,length)(V))
107
108 /* Get the final element of the vector.
109 T VEC_T_last(VEC(T) *v); // Pointer
110 T *VEC_T_last(VEC(T) *v); // Object
111
112 Return the final element. If V is empty, abort. */
113 #define VEC_last(TDEF,V) (VEC_OP(TDEF,last)(V))
114
115 /* Index into vector
116 T VEC_T_index(VEC(T) *v, size_t ix); // Pointer
117 T *VEC_T_index(VEC(T) *v, size_t ix); // Object
118
119 Return the IX'th element. If IX is outside the domain of V,
120 abort. */
121 #define VEC_index(TDEF,V,I) (VEC_OP(TDEF,index)(V,I))
122
123 /* Iterate over vector
124 T VEC_T_index(VEC(T) *v, size_t ix); // Pointer
125 T *VEC_T_index(VEC(T) *v, size_t ix); // Object
126
127 Return the IX'th element or NULL. Use this to iterate over the
128 elements of a vector as follows,
129
130 for (ix = 0; (ptr = VEC_iterate(T,v,ix)); ix++)
131 continue; */
132 #define VEC_iterate(TDEF,V,I) (VEC_OP(TDEF,iterate)(V,I))
133
134 /* Allocate new vector.
135 VEC(T) *VEC_T_alloc(size_t reserve);
136
137 Allocate a new vector with space for RESERVE objects. */
138 #define VEC_alloc(TDEF,A) (VEC_OP(TDEF,alloc)(A MEM_STAT_INFO))
139
140 /* Use these to determine the required size and initialization of a
141 vector embedded within another structure (as the final member).
142
143 size_t VEC_T_embedded_size(size_t reserve);
144 void VEC_T_embedded_init(VEC(T) *v, size_t reserve);
145
146 These allow the caller to perform the memory allocation. */
147 #define VEC_embedded_size(TDEF,A) (VEC_OP(TDEF,embedded_size)(A))
148 #define VEC_embedded_init(TDEF,O,A) (VEC_OP(TDEF,embedded_init)(O,A))
149
150 /* Reserve space.
151 void VEC_T_reserve(VEC(T) *&v, size_t reserve);
152
153 Ensure that V has at least RESERVE slots available. Note this can
154 cause V to be reallocated. */
155 #define VEC_reserve(TDEF,V,R) (VEC_OP(TDEF,reserve)(&(V),R MEM_STAT_INFO))
156
157 /* Push object with no reallocation
158 T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
159 T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
160
161 Push a new element onto the end, returns a pointer to the slot
162 filled in. For object vectors, the new value can be NULL, in which
163 case NO initialization is performed. Aborts if there is
164 insufficient space in the vector. */
165 #define VEC_quick_push(TDEF,V,O) (VEC_OP(TDEF,quick_push)(V,O))
166
167 /* Push object with reallocation
168 T *VEC_T_safe_push (VEC(T) *&v, T obj); // Pointer
169 T *VEC_T_safe_push (VEC(T) *&v, T *obj); // Object
170
171 Push a new element onto the end, returns a pointer to the slot
172 filled in. For object vectors, the new value can be NULL, in which
173 case NO initialization is performed. Reallocates V, if needed. */
174 #define VEC_safe_push(TDEF,V,O) (VEC_OP(TDEF,safe_push)(&(V),O MEM_STAT_INFO))
175
176 /* Pop element off end
177 T VEC_T_pop (VEC(T) *v); // Pointer
178 void VEC_T_pop (VEC(T) *v); // Object
179
180 Pop the last element off the end. Returns the element popped, for
181 pointer vectors. */
182 #define VEC_pop(TDEF,V) (VEC_OP(TDEF,pop)(V))
183
184 /* Truncate to specific length
185 void VEC_T_truncate (VEC(T) *v, size_t len);
186
187 Set the length as specified. This is an O(1) operation. */
188 #define VEC_truncate(TDEF,V,I) (VEC_OP(TDEF,truncate)(V,I))
189
190 /* Replace element
191 T VEC_T_replace (VEC(T) *v, size_t ix, T val); // Pointer
192 T *VEC_T_replace (VEC(T) *v, size_t ix, T *val); // Object
193
194 Replace the IXth element of V with a new value, VAL. For pointer
195 vectors returns the original value. For object vectors returns a
196 pointer to the new value. For object vectors the new value can be
197 NULL, in which case no overwriting of the slot is actually
198 performed. */
199 #define VEC_replace(TDEF,V,I,O) (VEC_OP(TDEF,replace)(V,I,O))
200
201 /* Insert object with no reallocation
202 T *VEC_T_quick_insert (VEC(T) *v, size_t ix, T val); // Pointer
203 T *VEC_T_quick_insert (VEC(T) *v, size_t ix, T *val); // Object
204
205 Insert an element, VAL, at the IXth position of V. Return a pointer
206 to the slot created. For vectors of object, the new value can be
207 NULL, in which case no initialization of the inserted slot takes
208 place. Aborts if there is insufficient space. */
209 #define VEC_quick_insert(TDEF,V,I,O) (VEC_OP(TDEF,quick_insert)(V,I,O))
210
211 /* Insert object with reallocation
212 T *VEC_T_safe_insert (VEC(T) *&v, size_t ix, T val); // Pointer
213 T *VEC_T_safe_insert (VEC(T) *&v, size_t ix, T *val); // Object
214
215 Insert an element, VAL, at the IXth position of V. Return a pointer
216 to the slot created. For vectors of object, the new value can be
217 NULL, in which case no initialization of the inserted slot takes
218 place. Reallocate V, if necessary. */
219 #define VEC_safe_insert(TDEF,V,I,O) (VEC_OP(TDEF,safe_insert)(&(V),I,O MEM_STAT_INFO))
220
221 /* Remove element retaining order
222 T VEC_T_ordered_remove (VEC(T) *v, size_t ix); // Pointer
223 void VEC_T_ordered_remove (VEC(T) *v, size_t ix); // Object
224
225 Remove an element from the IXth position of V. Ordering of
226 remaining elements is preserverd. For pointer vectors returns the
227 removed object. This is an O(N) operation due to a memmove. */
228 #define VEC_ordered_remove(TDEF,V,I) (VEC_OP(TDEF,ordered_remove)(V,I))
229
230 /* Remove element destroying order
231 T VEC_T_unordered_remove (VEC(T) *v, size_t ix); // Pointer
232 void VEC_T_unordered_remove (VEC(T) *v, size_t ix); // Object
233
234 Remove an element from the IXth position of V. Ordering of
235 remaining elements is destroyed. For pointer vectors returns the
236 removed object. This is an O(1) operation. */
237 #define VEC_unordered_remove(TDEF,V,I) (VEC_OP(TDEF,unordered_remove)(V,I))
238
239 #if !IN_GENGTYPE
240 /* Reallocate an array of elements with prefix. */
241 extern void *vec_p_reserve (void *, size_t MEM_STAT_DECL);
242 extern void *vec_o_reserve (void *, size_t, size_t, size_t MEM_STAT_DECL);
243
244 #if ENABLE_CHECKING
245 extern void vec_assert_fail (const char *, const char *,
246 const char *, size_t, const char *)
247 ATTRIBUTE_NORETURN;
248 #define VEC_ASSERT_FAIL(OP,VEC) \
249 vec_assert_fail (OP,#VEC,__FILE__,__LINE__,__FUNCTION__)
250
251 #define VEC_ASSERT(EXPR,OP,TDEF) \
252 (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(TDEF)), 0))
253 #else
254 #define VEC_ASSERT(EXPR,OP,TYPE) (void)(EXPR)
255 #endif
256
257 #define VEC(TDEF) VEC_##TDEF
258 #define VEC_OP(TDEF,OP) VEC_OP_(VEC(TDEF),OP)
259 #define VEC_OP_(VEC,OP) VEC_OP__(VEC,OP)
260 #define VEC_OP__(VEC,OP) VEC ## _ ## OP
261 #else /* IN_GENGTYPE */
262 #define VEC(TDEF) VEC_ TDEF
263 #define VEC_STRINGIFY(X) VEC_STRINGIFY_(X)
264 #define VEC_STRINGIFY_(X) #X
265 #undef GTY
266 #endif /* IN_GENGTYPE */
267
268 #define VEC_TDEF(TDEF) \
269 typedef struct VEC (TDEF) GTY(()) \
270 { \
271 size_t num; \
272 size_t alloc; \
273 TDEF GTY ((length ("%h.num"))) vec[1]; \
274 } VEC (TDEF)
275
276 /* Vector of pointer to object. */
277 #if IN_GENGTYPE
278 {"DEF_VEC_P", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
279 #else
280
281 #define DEF_VEC_P(TDEF) \
282 VEC_TDEF (TDEF); \
283 \
284 static inline size_t VEC_OP (TDEF,length) \
285 (const VEC (TDEF) *vec_) \
286 { \
287 return vec_ ? vec_->num : 0; \
288 } \
289 \
290 static inline TDEF VEC_OP (TDEF,last) \
291 (const VEC (TDEF) *vec_) \
292 { \
293 VEC_ASSERT (vec_ && vec_->num, "last", TDEF); \
294 \
295 return vec_->vec[vec_->num - 1]; \
296 } \
297 \
298 static inline TDEF VEC_OP (TDEF,index) \
299 (const VEC (TDEF) *vec_, size_t ix_) \
300 { \
301 VEC_ASSERT (vec_ && ix_ < vec_->num, "index", TDEF); \
302 \
303 return vec_->vec[ix_]; \
304 } \
305 \
306 static inline TDEF VEC_OP (TDEF,iterate) \
307 (const VEC (TDEF) *vec_, size_t ix_) \
308 { \
309 return vec_ && ix_ < vec_->num ? vec_->vec[ix_] : NULL; \
310 } \
311 \
312 static inline VEC (TDEF) *VEC_OP (TDEF,alloc MEM_STAT_DECL) \
313 (size_t alloc_) \
314 { \
315 return vec_p_reserve (NULL, alloc_ - !alloc_ PASS_MEM_STAT); \
316 } \
317 \
318 static inline size_t VEC_OP (TDEF,embedded_size) \
319 (size_t alloc_) \
320 { \
321 return offsetof (VEC(TDEF),vec) + alloc_ * sizeof(TDEF); \
322 } \
323 \
324 static inline void VEC_OP (TDEF,embedded_init) \
325 (VEC (TDEF) *vec_, size_t alloc_) \
326 { \
327 vec_->num = 0; \
328 vec_->alloc = alloc_; \
329 } \
330 \
331 static inline void VEC_OP (TDEF,reserve) \
332 (VEC (TDEF) **vec_, size_t alloc_ MEM_STAT_DECL) \
333 { \
334 *vec_ = vec_p_reserve (*vec_, alloc_ PASS_MEM_STAT); \
335 } \
336 \
337 static inline TDEF *VEC_OP (TDEF,quick_push) \
338 (VEC (TDEF) *vec_, TDEF obj_) \
339 { \
340 TDEF *slot_; \
341 \
342 VEC_ASSERT (vec_->num < vec_->alloc, "push", TDEF); \
343 slot_ = &vec_->vec[vec_->num++]; \
344 *slot_ = obj_; \
345 \
346 return slot_; \
347 } \
348 \
349 static inline TDEF *VEC_OP (TDEF,safe_push) \
350 (VEC (TDEF) **vec_, TDEF obj_ MEM_STAT_DECL) \
351 { \
352 if (!*vec_ || (*vec_)->num == (*vec_)->alloc) \
353 VEC_OP (TDEF,reserve) (vec_, ~(size_t)0 PASS_MEM_STAT); \
354 \
355 return VEC_OP (TDEF,quick_push) (*vec_, obj_); \
356 } \
357 \
358 static inline TDEF VEC_OP (TDEF,pop) \
359 (VEC (TDEF) *vec_) \
360 { \
361 TDEF obj_; \
362 \
363 VEC_ASSERT (vec_->num, "pop", TDEF); \
364 obj_ = vec_->vec[--vec_->num]; \
365 \
366 return obj_; \
367 } \
368 \
369 static inline void VEC_OP (TDEF,truncate) \
370 (VEC (TDEF) *vec_, size_t size_) \
371 { \
372 VEC_ASSERT (vec_->num >= size_, "truncate", TDEF); \
373 vec_->num = size_; \
374 } \
375 \
376 static inline TDEF VEC_OP (TDEF,replace) \
377 (VEC (TDEF) *vec_, size_t ix_, TDEF obj_) \
378 { \
379 TDEF old_obj_; \
380 \
381 VEC_ASSERT (ix_ < vec_->num, "replace", TDEF); \
382 old_obj_ = vec_->vec[ix_]; \
383 vec_->vec[ix_] = obj_; \
384 \
385 return old_obj_; \
386 } \
387 \
388 static inline TDEF *VEC_OP (TDEF,quick_insert) \
389 (VEC (TDEF) *vec_, size_t ix_, TDEF obj_) \
390 { \
391 TDEF *slot_; \
392 \
393 VEC_ASSERT (vec_->num < vec_->alloc, "insert", TDEF); \
394 VEC_ASSERT (ix_ <= vec_->num, "insert", TDEF); \
395 slot_ = &vec_->vec[ix_]; \
396 memmove (slot_ + 1, slot_, vec_->num++ - ix_); \
397 *slot_ = obj_; \
398 \
399 return slot_; \
400 } \
401 \
402 static inline TDEF *VEC_OP (TDEF,safe_insert) \
403 (VEC (TDEF) **vec_, size_t ix_, TDEF obj_ MEM_STAT_DECL) \
404 { \
405 if (!*vec_ || (*vec_)->num == (*vec_)->alloc) \
406 VEC_OP (TDEF,reserve) (vec_, ~(size_t)0 PASS_MEM_STAT); \
407 \
408 return VEC_OP (TDEF,quick_insert) (*vec_, ix_, obj_); \
409 } \
410 \
411 static inline TDEF VEC_OP (TDEF,ordered_remove) \
412 (VEC (TDEF) *vec_, size_t ix_) \
413 { \
414 TDEF *slot_; \
415 TDEF obj_; \
416 \
417 VEC_ASSERT (ix_ < vec_->num, "remove", TDEF); \
418 slot_ = &vec_->vec[ix_]; \
419 obj_ = *slot_; \
420 memmove (slot_, slot_ + 1, --vec_->num - ix_); \
421 \
422 return obj_; \
423 } \
424 \
425 static inline TDEF VEC_OP (TDEF,unordered_remove) \
426 (VEC (TDEF) *vec_, size_t ix_) \
427 { \
428 TDEF *slot_; \
429 TDEF obj_; \
430 \
431 VEC_ASSERT (ix_ < vec_->num, "remove", TDEF); \
432 slot_ = &vec_->vec[ix_]; \
433 obj_ = *slot_; \
434 *slot_ = vec_->vec[--vec_->num]; \
435 \
436 return obj_; \
437 } \
438 \
439 struct vec_swallow_trailing_semi
440 #endif
441
442 /* Vector of object. */
443 #if IN_GENGTYPE
444 {"DEF_VEC_O", VEC_STRINGIFY (VEC_TDEF (#)) ";", NULL},
445 #else
446
447 #define DEF_VEC_O(TDEF) \
448 VEC_TDEF (TDEF); \
449 \
450 static inline size_t VEC_OP (TDEF,length) \
451 (const VEC (TDEF) *vec_) \
452 { \
453 return vec_ ? vec_->num : 0; \
454 } \
455 \
456 static inline TDEF *VEC_OP (TDEF,last) \
457 (VEC (TDEF) *vec_) \
458 { \
459 VEC_ASSERT (vec_ && vec_->num, "last", TDEF); \
460 \
461 return &vec_->vec[vec_->num - 1]; \
462 } \
463 \
464 static inline TDEF *VEC_OP (TDEF,index) \
465 (VEC (TDEF) *vec_, size_t ix_) \
466 { \
467 VEC_ASSERT (vec_ && ix_ < vec_->num, "index", TDEF); \
468 \
469 return &vec_->vec[ix_]; \
470 } \
471 \
472 static inline TDEF *VEC_OP (TDEF,iterate) \
473 (VEC (TDEF) *vec_, size_t ix_) \
474 { \
475 return vec_ && ix_ < vec_->num ? &vec_->vec[ix_] : NULL; \
476 } \
477 \
478 static inline VEC (TDEF) *VEC_OP (TDEF,alloc) \
479 (size_t alloc_ MEM_STAT_DECL) \
480 { \
481 return vec_o_reserve (NULL, alloc_ - !alloc_, \
482 offsetof (VEC(TDEF),vec), sizeof (TDEF) \
483 PASS_MEM_STAT); \
484 } \
485 \
486 static inline size_t VEC_OP (TDEF,embedded_size) \
487 (size_t alloc_) \
488 { \
489 return offsetof (VEC(TDEF),vec) + alloc_ * sizeof(TDEF); \
490 } \
491 \
492 static inline void VEC_OP (TDEF,embedded_init) \
493 (VEC (TDEF) *vec_, size_t alloc_) \
494 { \
495 vec_->num = 0; \
496 vec_->alloc = alloc_; \
497 } \
498 \
499 static inline void VEC_OP (TDEF,reserve) \
500 (VEC (TDEF) **vec_, size_t alloc_ MEM_STAT_DECL) \
501 { \
502 *vec_ = vec_o_reserve (*vec_, alloc_, \
503 offsetof (VEC(TDEF),vec), sizeof (TDEF) \
504 PASS_MEM_STAT); \
505 } \
506 \
507 static inline TDEF *VEC_OP (TDEF,quick_push) \
508 (VEC (TDEF) *vec_, const TDEF *obj_) \
509 { \
510 TDEF *slot_; \
511 \
512 VEC_ASSERT (vec_->num < vec_->alloc, "push", TDEF); \
513 slot_ = &vec_->vec[vec_->num++]; \
514 if (obj_) \
515 *slot_ = *obj_; \
516 \
517 return slot_; \
518 } \
519 \
520 static inline TDEF *VEC_OP (TDEF,safe_push) \
521 (VEC (TDEF) **vec_, const TDEF *obj_ MEM_STAT_DECL) \
522 { \
523 if (!*vec_ || (*vec_)->num == (*vec_)->alloc) \
524 VEC_OP (TDEF,reserve) (vec_, ~(size_t)0 PASS_MEM_STAT); \
525 \
526 return VEC_OP (TDEF,quick_push) (*vec_, obj_); \
527 } \
528 \
529 static inline void VEC_OP (TDEF,pop) \
530 (VEC (TDEF) *vec_) \
531 { \
532 VEC_ASSERT (vec_->num, "pop", TDEF); \
533 --vec_->num; \
534 } \
535 \
536 static inline void VEC_OP (TDEF,truncate) \
537 (VEC (TDEF) *vec_, size_t size_) \
538 { \
539 VEC_ASSERT (vec_->num >= size_, "truncate", TDEF); \
540 vec_->num = size_; \
541 } \
542 \
543 static inline TDEF *VEC_OP (TDEF,replace) \
544 (VEC (TDEF) *vec_, size_t ix_, const TDEF *obj_) \
545 { \
546 TDEF *slot_; \
547 \
548 VEC_ASSERT (ix_ < vec_->num, "replace", TDEF); \
549 slot_ = &vec_->vec[ix_]; \
550 if (obj_) \
551 *slot_ = *obj_; \
552 \
553 return slot_; \
554 } \
555 \
556 static inline TDEF *VEC_OP (TDEF,quick_insert) \
557 (VEC (TDEF) *vec_, size_t ix_, const TDEF *obj_) \
558 { \
559 TDEF *slot_; \
560 \
561 VEC_ASSERT (vec_->num < vec_->alloc, "insert", TDEF); \
562 VEC_ASSERT (ix_ <= vec_->num, "insert", TDEF); \
563 slot_ = &vec_->vec[ix_]; \
564 memmove (slot_ + 1, slot_, vec_->num++ - ix_); \
565 if (obj_) \
566 *slot_ = *obj_; \
567 \
568 return slot_; \
569 } \
570 \
571 static inline TDEF *VEC_OP (TDEF,safe_insert) \
572 (VEC (TDEF) **vec_, size_t ix_, const TDEF *obj_ MEM_STAT_DECL) \
573 { \
574 if (!*vec_ || (*vec_)->num == (*vec_)->alloc) \
575 VEC_OP (TDEF,reserve) (vec_, ~(size_t)0 PASS_MEM_STAT); \
576 \
577 return VEC_OP (TDEF,quick_insert) (*vec_, ix_, obj_); \
578 } \
579 \
580 static inline void VEC_OP (TDEF,ordered_remove) \
581 (VEC (TDEF) *vec_, size_t ix_) \
582 { \
583 TDEF *slot_; \
584 \
585 VEC_ASSERT (ix_ < vec_->num, "remove", TDEF); \
586 slot_ = &vec_->vec[ix_]; \
587 memmove (slot_, slot_ + 1, --vec_->num - ix_); \
588 } \
589 \
590 static inline void VEC_OP (TDEF,unordered_remove) \
591 (VEC (TDEF) *vec_, size_t ix_) \
592 { \
593 VEC_ASSERT (ix_ < vec_->num, "remove", TDEF); \
594 vec_->vec[ix_] = vec_->vec[--vec_->num]; \
595 } \
596 \
597 struct vec_swallow_trailing_semi
598 #endif
599
600 #endif /* GCC_VEC_H */