Line data Source code
1 : /* Vector API for GNU compiler.
2 : Copyright (C) 2004-2026 Free Software Foundation, Inc.
3 : Contributed by Nathan Sidwell <nathan@codesourcery.com>
4 : Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it under
9 : the terms of the GNU General Public License as published by the Free
10 : Software Foundation; either version 3, or (at your option) any later
11 : version.
12 :
13 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING3. If not see
20 : <http://www.gnu.org/licenses/>. */
21 :
22 : /* This file is compiled twice: once for the generator programs
23 : once for the compiler. */
24 : #ifdef GENERATOR_FILE
25 : #include "bconfig.h"
26 : #else
27 : #include "config.h"
28 : #endif
29 :
30 : #include "system.h"
31 : #include "coretypes.h"
32 : #include "hash-table.h"
33 : #include "selftest.h"
34 : #ifdef GENERATOR_FILE
35 : #include "errors.h"
36 : #else
37 : #include "input.h"
38 : #include "diagnostic-core.h"
39 : #endif
40 :
41 : /* Vector memory usage. */
42 : class vec_usage: public mem_usage
43 : {
44 : public:
45 : /* Default constructor. */
46 0 : vec_usage (): m_items (0), m_items_peak (0), m_element_size (0) {}
47 :
48 : /* Constructor. */
49 0 : vec_usage (size_t allocated, size_t times, size_t peak,
50 : size_t items, size_t items_peak, size_t element_size)
51 : : mem_usage (allocated, times, peak),
52 0 : m_items (items), m_items_peak (items_peak),
53 0 : m_element_size (element_size) {}
54 :
55 : /* Sum the usage with SECOND usage. */
56 : vec_usage
57 0 : operator+ (const vec_usage &second)
58 : {
59 0 : return vec_usage (m_allocated + second.m_allocated,
60 0 : m_times + second.m_times,
61 0 : m_peak + second.m_peak,
62 0 : m_items + second.m_items,
63 0 : m_items_peak + second.m_items_peak, 0);
64 : }
65 :
66 : /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
67 : inline void
68 0 : dump (mem_location *loc, mem_usage &total) const
69 : {
70 0 : char s[4096];
71 0 : sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
72 : loc->m_line, loc->m_function);
73 :
74 0 : s[48] = '\0';
75 :
76 0 : fprintf (stderr,
77 : "%-48s %10" PRIu64 PRsa (10) ":%4.1f%%" PRsa (9) "%10" PRIu64
78 : ":%4.1f%%" PRsa (10) PRsa (10) "\n",
79 : s,
80 0 : (uint64_t)m_element_size,
81 0 : SIZE_AMOUNT (m_allocated),
82 0 : m_allocated * 100.0 / total.m_allocated,
83 0 : SIZE_AMOUNT (m_peak), (uint64_t)m_times,
84 0 : m_times * 100.0 / total.m_times,
85 0 : SIZE_AMOUNT (m_items), SIZE_AMOUNT (m_items_peak));
86 0 : }
87 :
88 : /* Dump footer. */
89 : inline void
90 0 : dump_footer ()
91 : {
92 0 : fprintf (stderr, "%s" PRsa (64) PRsa (25) PRsa (16) "\n",
93 0 : "Total", SIZE_AMOUNT (m_allocated),
94 0 : SIZE_AMOUNT (m_times), SIZE_AMOUNT (m_items));
95 0 : }
96 :
97 : /* Dump header with NAME. */
98 : static inline void
99 0 : dump_header (const char *name)
100 : {
101 0 : fprintf (stderr, "%-48s %10s%11s%16s%10s%17s%11s\n", name, "sizeof(T)",
102 : "Leak", "Peak", "Times", "Leak items", "Peak items");
103 0 : }
104 :
105 : /* Current number of items allocated. */
106 : size_t m_items;
107 : /* Peak value of number of allocated items. */
108 : size_t m_items_peak;
109 : /* Size of element of the vector. */
110 : size_t m_element_size;
111 : };
112 :
113 : /* Vector memory description. */
114 : inline auto &
115 0 : vec_mem_desc ()
116 : {
117 0 : return mem_alloc_description<vec_usage>::instance<VEC_ORIGIN> ();
118 : }
119 :
120 : /* Account the overhead. */
121 :
122 : void
123 0 : vec_prefix::register_overhead (void *ptr, size_t elements,
124 : size_t element_size MEM_STAT_DECL)
125 : {
126 0 : vec_mem_desc ().register_descriptor (ptr, VEC_ORIGIN, false
127 : FINAL_PASS_MEM_STAT);
128 0 : vec_usage *usage
129 0 : = vec_mem_desc ().register_instance_overhead (elements * element_size, ptr);
130 0 : usage->m_element_size = element_size;
131 0 : usage->m_items += elements;
132 0 : if (usage->m_items_peak < usage->m_items)
133 0 : usage->m_items_peak = usage->m_items;
134 0 : }
135 :
136 : /* Notice that the memory allocated for the vector has been freed. */
137 :
138 : void
139 0 : vec_prefix::release_overhead (void *ptr, size_t size, size_t elements,
140 : bool in_dtor MEM_STAT_DECL)
141 : {
142 0 : if (!vec_mem_desc ().contains_descriptor_for_instance (ptr))
143 0 : vec_mem_desc ().register_descriptor (ptr, VEC_ORIGIN,
144 : false FINAL_PASS_MEM_STAT);
145 0 : vec_usage *usage = vec_mem_desc ().release_instance_overhead (ptr, size,
146 : in_dtor);
147 0 : usage->m_items -= elements;
148 0 : }
149 :
150 : /* Calculate the number of slots to reserve a vector, making sure that
151 : it is of at least DESIRED size by growing ALLOC exponentially. */
152 :
153 : unsigned
154 1042562611 : vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired)
155 : {
156 : /* We must have run out of room. */
157 1042562611 : gcc_assert (alloc < desired);
158 :
159 : /* Exponential growth. */
160 1042562611 : if (!alloc)
161 : alloc = 4;
162 1042562611 : else if (alloc < 16)
163 : /* Double when small. */
164 883986575 : alloc = alloc * 2;
165 : else
166 : /* Grow slower when large. */
167 158576036 : alloc = (alloc * 3 / 2);
168 :
169 : /* If this is still too small, set it to the right size. */
170 1042562611 : if (alloc < desired)
171 : alloc = desired;
172 1042562611 : return alloc;
173 : }
174 :
175 : /* Dump per-site memory statistics. */
176 :
177 : void
178 0 : dump_vec_loc_statistics (void)
179 : {
180 0 : vec_mem_desc ().dump (VEC_ORIGIN);
181 0 : }
182 :
183 : /* Gets the next token from STR delimited by DELIMS (deliminator not included
184 : in returned string).
185 :
186 : Updates STR to be the remaining string after the given token.
187 :
188 : STR and DELIMS must both be valid string_slices.
189 :
190 : If there aren't any of the chars in DELIM in STR (ie no more tokens in STR)
191 : then returns the string, and updates STR to be invalid. */
192 : string_slice
193 648 : string_slice::tokenize (string_slice *str, string_slice delims)
194 : {
195 648 : const char *ptr = str->begin ();
196 :
197 648 : gcc_assert (str->is_valid () && delims.is_valid ());
198 :
199 5176 : for (; ptr < str->end (); ptr++)
200 9400 : for (char c : delims)
201 4872 : if (*ptr == c)
202 : {
203 : /* Update the input string to be the remaining string. */
204 76 : const char *str_begin = str->begin ();
205 76 : *str = string_slice (ptr + 1, str->end ());
206 76 : return string_slice (str_begin, ptr);
207 : }
208 :
209 : /* If no deliminators between the start and end, return the whole string. */
210 572 : string_slice res = *str;
211 572 : *str = string_slice::invalid ();
212 572 : return res;
213 : }
214 :
215 : /* Compares the string_slices STR1 and STR2 giving a lexograpical ordering.
216 : Returns -1 if STR1 comes before STR2, 1 if STR1 comes after, and 0 if the
217 : string_slices have the same contents. */
218 :
219 : int
220 32 : string_slice::strcmp (string_slice str1, string_slice str2)
221 : {
222 56 : for (unsigned int i = 0; i < str1.size () && i < str2.size (); i++)
223 : {
224 32 : if (str1[i] < str2[i])
225 : return -1;
226 28 : if (str1[i] > str2[i])
227 : return 1;
228 : }
229 :
230 24 : if (str1.size () < str2.size ())
231 : return -1;
232 20 : if (str1.size () > str2.size ())
233 8 : return 1;
234 : return 0;
235 : }
236 :
237 : string_slice
238 604 : string_slice::strip ()
239 : {
240 604 : const char *start = this->begin ();
241 604 : const char *end = this->end ();
242 :
243 1272 : while (start < end && ISSPACE (*start))
244 64 : start++;
245 640 : while (end > start && ISSPACE (*(end-1)))
246 36 : end--;
247 :
248 604 : return string_slice (start, end);
249 : }
250 :
251 : #if CHECKING_P
252 : /* Report qsort comparator CMP consistency check failure with P1, P2, P3 as
253 : witness elements. */
254 : ATTRIBUTE_NORETURN ATTRIBUTE_COLD
255 : static void
256 0 : qsort_chk_error (const void *p1, const void *p2, const void *p3,
257 : sort_r_cmp_fn *cmp, void *data)
258 : {
259 0 : if (!p3)
260 : {
261 0 : int r1 = cmp (p1, p2, data), r2 = cmp (p2, p1, data);
262 0 : error ("qsort comparator not anti-symmetric: %d, %d", r1, r2);
263 : }
264 0 : else if (p1 == p2)
265 : {
266 0 : int r = cmp (p1, p3, data);
267 0 : error ("qsort comparator non-negative on sorted output: %d", r);
268 : }
269 : else
270 : {
271 0 : int r1 = cmp (p1, p2, data);
272 0 : int r2 = cmp (p2, p3, data);
273 0 : int r3 = cmp (p1, p3, data);
274 0 : error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3);
275 : }
276 0 : internal_error ("qsort checking failed");
277 : }
278 :
279 : /* Verify anti-symmetry and transitivity for comparator CMP on sorted array
280 : of N SIZE-sized elements pointed to by BASE. */
281 : void
282 182255001 : qsort_chk (void *base, size_t n, size_t size, sort_r_cmp_fn *cmp, void *data)
283 : {
284 : #if 0
285 : #define LIM(n) (n)
286 : #else
287 : /* Limit overall time complexity to O(n log n). */
288 : #define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n))
289 : #endif
290 : #define ELT(i) ((const char *) base + (i) * size)
291 : #define CMP(i, j) cmp (ELT (i), ELT (j), data)
292 : #define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp, data)
293 : #define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp, data)
294 182255001 : size_t i1, i2, i, j;
295 : /* This outer loop iterates over maximum spans [i1, i2) such that
296 : elements within each span compare equal to each other. */
297 1393034620 : for (i1 = 0; i1 < n; i1 = i2)
298 : {
299 : /* Position i2 one past last element that compares equal to i1'th. */
300 1309669551 : for (i2 = i1 + 1; i2 < n; i2++)
301 1127414550 : if (CMP (i1, i2))
302 : break;
303 98889932 : else if (CMP (i2, i1))
304 0 : ERR2 (i1, i2);
305 1210779619 : size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2);
306 : /* Verify that other pairs within current span compare equal. */
307 1299159242 : for (i = i1 + 1; i + 1 < i2; i++)
308 190632668 : for (j = i + 1; j < i1 + lim1; j++)
309 102253045 : if (CMP (i, j))
310 0 : ERR3 (i, i1, j);
311 102253045 : else if (CMP (j, i))
312 0 : ERR2 (i, j);
313 : /* Verify that elements within this span compare less than
314 : elements beyond the span. */
315 2520449170 : for (i = i1; i < i2; i++)
316 13585435010 : for (j = i2; j < i2 + lim2; j++)
317 12275765459 : if (CMP (i, j) >= 0)
318 0 : ERR3 (i, i1, j);
319 12275765459 : else if (CMP (j, i) <= 0)
320 0 : ERR2 (i, j);
321 : }
322 : #undef ERR3
323 : #undef ERR2
324 : #undef CMP
325 : #undef ELT
326 : #undef LIM
327 182255001 : }
328 : #endif /* #if CHECKING_P */
329 :
330 : #ifndef GENERATOR_FILE
331 : #if CHECKING_P
332 :
333 : namespace selftest {
334 :
335 : /* Selftests. */
336 :
337 : /* Call V.safe_push for all ints from START up to, but not including LIMIT.
338 : Helper function for selftests. */
339 :
340 : static void
341 52 : safe_push_range (vec <int>&v, int start, int limit)
342 : {
343 540 : for (int i = start; i < limit; i++)
344 488 : v.safe_push (i);
345 52 : }
346 :
347 : /* Verify forms of initialization. */
348 :
349 : static void
350 4 : test_init ()
351 : {
352 4 : {
353 4 : vec<int> v1{ };
354 4 : ASSERT_EQ (0, v1.length ());
355 :
356 4 : vec<int> v2 (v1);
357 4 : ASSERT_EQ (0, v2.length ());
358 : }
359 :
360 4 : {
361 4 : vec<int> v1 = vec<int>();
362 4 : ASSERT_EQ (0, v1.length ());
363 :
364 4 : vec<int> v2 = v1;
365 4 : ASSERT_EQ (0, v2.length ());
366 : }
367 :
368 4 : {
369 4 : vec<int> v1 (vNULL);
370 4 : ASSERT_EQ (0, v1.length ());
371 4 : v1.safe_push (1);
372 :
373 4 : vec<int> v2 (v1);
374 4 : ASSERT_EQ (1, v1.length ());
375 4 : v2.safe_push (1);
376 :
377 4 : ASSERT_EQ (2, v1.length ());
378 4 : ASSERT_EQ (2, v2.length ());
379 4 : v1.release ();
380 : }
381 4 : }
382 :
383 : /* Verify that vec::quick_push works correctly. */
384 :
385 : static void
386 4 : test_quick_push ()
387 : {
388 4 : auto_vec <int> v;
389 4 : ASSERT_EQ (0, v.length ());
390 4 : v.reserve (3);
391 4 : ASSERT_EQ (0, v.length ());
392 4 : ASSERT_TRUE (v.space (3));
393 4 : v.quick_push (5);
394 4 : v.quick_push (6);
395 4 : v.quick_push (7);
396 4 : ASSERT_EQ (3, v.length ());
397 4 : ASSERT_EQ (5, v[0]);
398 4 : ASSERT_EQ (6, v[1]);
399 4 : ASSERT_EQ (7, v[2]);
400 4 : }
401 :
402 : /* Verify that vec::safe_push works correctly. */
403 :
404 : static void
405 4 : test_safe_push ()
406 : {
407 4 : auto_vec <int> v;
408 4 : ASSERT_EQ (0, v.length ());
409 4 : v.safe_push (5);
410 4 : v.safe_push (6);
411 4 : v.safe_push (7);
412 4 : ASSERT_EQ (3, v.length ());
413 4 : ASSERT_EQ (5, v[0]);
414 4 : ASSERT_EQ (6, v[1]);
415 4 : ASSERT_EQ (7, v[2]);
416 4 : }
417 :
418 : /* Verify that vec::truncate works correctly. */
419 :
420 : static void
421 4 : test_truncate ()
422 : {
423 4 : auto_vec <int> v;
424 4 : ASSERT_EQ (0, v.length ());
425 4 : safe_push_range (v, 0, 10);
426 4 : ASSERT_EQ (10, v.length ());
427 :
428 4 : v.truncate (5);
429 4 : ASSERT_EQ (5, v.length ());
430 4 : }
431 :
432 : /* Verify that vec::safe_grow_cleared works correctly. */
433 :
434 : static void
435 4 : test_safe_grow_cleared ()
436 : {
437 4 : auto_vec <int> v;
438 4 : ASSERT_EQ (0, v.length ());
439 4 : v.safe_grow_cleared (50, true);
440 4 : ASSERT_EQ (50, v.length ());
441 4 : ASSERT_EQ (0, v[0]);
442 4 : ASSERT_EQ (0, v[49]);
443 4 : }
444 :
445 : /* Verify that vec::pop works correctly. */
446 :
447 : static void
448 4 : test_pop ()
449 : {
450 4 : auto_vec <int> v;
451 4 : safe_push_range (v, 5, 20);
452 4 : ASSERT_EQ (15, v.length ());
453 :
454 4 : int last = v.pop ();
455 4 : ASSERT_EQ (19, last);
456 4 : ASSERT_EQ (14, v.length ());
457 4 : }
458 :
459 : /* Verify that vec::safe_insert works correctly. */
460 :
461 : static void
462 4 : test_safe_insert ()
463 : {
464 4 : auto_vec <int> v;
465 4 : safe_push_range (v, 0, 10);
466 4 : v.safe_insert (5, 42);
467 4 : ASSERT_EQ (4, v[4]);
468 4 : ASSERT_EQ (42, v[5]);
469 4 : ASSERT_EQ (5, v[6]);
470 4 : ASSERT_EQ (11, v.length ());
471 4 : }
472 :
473 : /* Verify that vec::ordered_remove works correctly. */
474 :
475 : static void
476 4 : test_ordered_remove ()
477 : {
478 4 : auto_vec <int> v;
479 4 : safe_push_range (v, 0, 10);
480 4 : v.ordered_remove (5);
481 4 : ASSERT_EQ (4, v[4]);
482 4 : ASSERT_EQ (6, v[5]);
483 4 : ASSERT_EQ (9, v.length ());
484 4 : }
485 :
486 : /* Verify that vec::ordered_remove_if works correctly. */
487 :
488 : static void
489 4 : test_ordered_remove_if (void)
490 : {
491 4 : auto_vec <int> v;
492 4 : safe_push_range (v, 0, 10);
493 4 : unsigned ix, ix2;
494 4 : int *elem_ptr;
495 44 : VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr,
496 4 : *elem_ptr == 5 || *elem_ptr == 7);
497 4 : ASSERT_EQ (4, v[4]);
498 4 : ASSERT_EQ (6, v[5]);
499 4 : ASSERT_EQ (8, v[6]);
500 4 : ASSERT_EQ (8, v.length ());
501 :
502 4 : v.truncate (0);
503 4 : safe_push_range (v, 0, 10);
504 28 : VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 6,
505 4 : *elem_ptr == 5 || *elem_ptr == 7);
506 4 : ASSERT_EQ (4, v[4]);
507 4 : ASSERT_EQ (6, v[5]);
508 4 : ASSERT_EQ (7, v[6]);
509 4 : ASSERT_EQ (9, v.length ());
510 :
511 4 : v.truncate (0);
512 4 : safe_push_range (v, 0, 10);
513 24 : VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 5,
514 4 : *elem_ptr == 5 || *elem_ptr == 7);
515 12 : VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 8, 10,
516 4 : *elem_ptr == 5 || *elem_ptr == 7);
517 4 : ASSERT_EQ (4, v[4]);
518 4 : ASSERT_EQ (5, v[5]);
519 4 : ASSERT_EQ (6, v[6]);
520 4 : ASSERT_EQ (10, v.length ());
521 :
522 4 : v.truncate (0);
523 4 : safe_push_range (v, 0, 10);
524 44 : VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr, *elem_ptr == 5);
525 4 : ASSERT_EQ (4, v[4]);
526 4 : ASSERT_EQ (6, v[5]);
527 4 : ASSERT_EQ (7, v[6]);
528 4 : ASSERT_EQ (9, v.length ());
529 4 : }
530 :
531 : /* Verify that vec::unordered_remove works correctly. */
532 :
533 : static void
534 4 : test_unordered_remove ()
535 : {
536 4 : auto_vec <int> v;
537 4 : safe_push_range (v, 0, 10);
538 4 : v.unordered_remove (5);
539 4 : ASSERT_EQ (9, v.length ());
540 4 : }
541 :
542 : /* Verify that vec::block_remove works correctly. */
543 :
544 : static void
545 4 : test_block_remove ()
546 : {
547 4 : auto_vec <int> v;
548 4 : safe_push_range (v, 0, 10);
549 4 : v.block_remove (5, 3);
550 4 : ASSERT_EQ (3, v[3]);
551 4 : ASSERT_EQ (4, v[4]);
552 4 : ASSERT_EQ (8, v[5]);
553 4 : ASSERT_EQ (9, v[6]);
554 4 : ASSERT_EQ (7, v.length ());
555 4 : }
556 :
557 : /* Comparator for use by test_qsort. */
558 :
559 : static int
560 492 : reverse_cmp (const void *p_i, const void *p_j)
561 : {
562 492 : return *(const int *)p_j - *(const int *)p_i;
563 : }
564 :
565 : /* Verify that vec::qsort works correctly. */
566 :
567 : static void
568 4 : test_qsort ()
569 : {
570 4 : auto_vec <int> v;
571 4 : safe_push_range (v, 0, 10);
572 4 : v.qsort (reverse_cmp);
573 4 : ASSERT_EQ (9, v[0]);
574 4 : ASSERT_EQ (8, v[1]);
575 4 : ASSERT_EQ (1, v[8]);
576 4 : ASSERT_EQ (0, v[9]);
577 4 : ASSERT_EQ (10, v.length ());
578 4 : }
579 :
580 : /* Verify that vec::reverse works correctly. */
581 :
582 : static void
583 4 : test_reverse ()
584 : {
585 : /* Reversing an empty vec ought to be a no-op. */
586 4 : {
587 4 : auto_vec <int> v;
588 4 : ASSERT_EQ (0, v.length ());
589 4 : v.reverse ();
590 4 : ASSERT_EQ (0, v.length ());
591 4 : }
592 :
593 : /* Verify reversing a vec with even length. */
594 4 : {
595 4 : auto_vec <int> v;
596 4 : safe_push_range (v, 0, 4);
597 4 : v.reverse ();
598 4 : ASSERT_EQ (3, v[0]);
599 4 : ASSERT_EQ (2, v[1]);
600 4 : ASSERT_EQ (1, v[2]);
601 4 : ASSERT_EQ (0, v[3]);
602 4 : ASSERT_EQ (4, v.length ());
603 4 : }
604 :
605 : /* Verify reversing a vec with odd length. */
606 4 : {
607 4 : auto_vec <int> v;
608 4 : safe_push_range (v, 0, 3);
609 4 : v.reverse ();
610 4 : ASSERT_EQ (2, v[0]);
611 4 : ASSERT_EQ (1, v[1]);
612 4 : ASSERT_EQ (0, v[2]);
613 4 : ASSERT_EQ (3, v.length ());
614 4 : }
615 4 : }
616 :
617 : /* A test class that increments a counter every time its dtor is called. */
618 :
619 : class count_dtor
620 : {
621 : public:
622 8 : count_dtor (int *counter) : m_counter (counter) {}
623 8 : ~count_dtor () { (*m_counter)++; }
624 :
625 : private:
626 : int *m_counter;
627 : };
628 :
629 : /* Verify that auto_delete_vec deletes the elements within it. */
630 :
631 : static void
632 4 : test_auto_delete_vec ()
633 : {
634 4 : int dtor_count = 0;
635 4 : {
636 4 : auto_delete_vec <count_dtor> v;
637 4 : v.safe_push (new count_dtor (&dtor_count));
638 4 : v.safe_push (new count_dtor (&dtor_count));
639 4 : }
640 4 : ASSERT_EQ (dtor_count, 2);
641 4 : }
642 :
643 : /* Verify accesses to vector elements are done indirectly. */
644 :
645 : static void
646 4 : test_auto_alias ()
647 : {
648 4 : volatile int i = 1;
649 4 : auto_vec<int, 8> v;
650 4 : v.quick_grow (2);
651 4 : v[0] = 1;
652 4 : v[1] = 2;
653 4 : int val;
654 8 : for (int ix = i; v.iterate (ix, &val); ix++)
655 4 : ASSERT_EQ (val, 2);
656 4 : ASSERT_EQ (val, 0);
657 4 : }
658 :
659 : static void
660 4 : test_string_slice_initializers ()
661 : {
662 4 : string_slice str1 = string_slice ();
663 4 : ASSERT_TRUE (str1.is_valid ());
664 4 : ASSERT_EQ (str1.size (), 0);
665 :
666 4 : string_slice str2 = string_slice ("Test string");
667 4 : ASSERT_TRUE (str2.is_valid ());
668 4 : ASSERT_EQ (str2.size (), 11);
669 :
670 4 : string_slice str3 = "Test string the second";
671 4 : ASSERT_TRUE (str3.is_valid ());
672 4 : ASSERT_EQ (str3.size (), 22);
673 :
674 4 : string_slice str4 = string_slice ("Test string", 4);
675 4 : ASSERT_TRUE (str4.is_valid ());
676 4 : ASSERT_EQ (str4.size (), 4);
677 4 : }
678 :
679 : static void
680 4 : test_string_slice_tokenize ()
681 : {
682 4 : string_slice test_string_slice = "";
683 4 : string_slice test_delims = ",";
684 :
685 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
686 8 : ASSERT_FALSE (test_string_slice.is_valid ());
687 :
688 4 : test_string_slice = ",";
689 4 : test_delims = ",";
690 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
691 : string_slice (""));
692 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
693 : string_slice (""));
694 8 : ASSERT_FALSE (test_string_slice.is_valid ());
695 :
696 4 : test_string_slice = ",test.,.test, , test ";
697 4 : test_delims = ",.";
698 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
699 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "test");
700 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
701 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "");
702 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), "test");
703 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims), " ");
704 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
705 : " test ");
706 8 : ASSERT_FALSE (test_string_slice.is_valid ());
707 :
708 4 : const char *test_string
709 : = "This is the test string, it \0 is for testing, 123 ,,";
710 4 : test_string_slice = string_slice (test_string, 52);
711 4 : test_delims = string_slice (",\0", 2);
712 :
713 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
714 : "This is the test string");
715 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
716 : " it ");
717 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
718 : " is for testing");
719 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
720 : " 123 ");
721 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
722 : "");
723 4 : ASSERT_EQ (string_slice::tokenize (&test_string_slice, test_delims),
724 : "");
725 8 : ASSERT_FALSE (test_string_slice.is_valid ());
726 4 : }
727 :
728 : static void
729 4 : test_string_slice_strcmp ()
730 : {
731 4 : ASSERT_EQ (string_slice::strcmp (string_slice (),
732 : string_slice ()), 0);
733 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("test"),
734 : string_slice ()), 1);
735 4 : ASSERT_EQ (string_slice::strcmp (string_slice (),
736 : string_slice ("test")), -1);
737 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("test"),
738 : string_slice ("test")), 0);
739 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("a"),
740 : string_slice ("b")), -1);
741 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("b"),
742 : string_slice ("a")), 1);
743 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("ab", 1),
744 : string_slice ("a")), 0);
745 4 : ASSERT_EQ (string_slice::strcmp (string_slice ("ab", 2),
746 : string_slice ("a")), 1);
747 4 : }
748 :
749 : static void
750 4 : test_string_slice_equality ()
751 : {
752 4 : ASSERT_TRUE (string_slice () == string_slice ());
753 4 : ASSERT_FALSE (string_slice ("test") == string_slice ());
754 4 : ASSERT_FALSE ("test" == string_slice ());
755 4 : ASSERT_FALSE (string_slice () == string_slice ("test"));
756 4 : ASSERT_FALSE (string_slice () == "test");
757 4 : ASSERT_TRUE (string_slice ("test") == string_slice ("test"));
758 4 : ASSERT_TRUE ("test" == string_slice ("test"));
759 4 : ASSERT_TRUE (string_slice ("test") == "test");
760 4 : ASSERT_FALSE (string_slice ("a") == string_slice ("b"));
761 4 : ASSERT_FALSE ("a" == string_slice ("b"));
762 4 : ASSERT_FALSE (string_slice ("a") == "b");
763 4 : ASSERT_FALSE (string_slice ("b") == string_slice ("a"));
764 4 : ASSERT_TRUE (string_slice ("ab", 1) == string_slice ("a"));
765 4 : ASSERT_TRUE (string_slice ("ab", 1) == "a");
766 4 : ASSERT_FALSE (string_slice ("ab", 2) == string_slice ("a"));
767 4 : ASSERT_FALSE (string_slice ("ab", 2) == "a");
768 4 : }
769 :
770 : static void
771 4 : test_string_slice_inequality ()
772 : {
773 4 : ASSERT_FALSE (string_slice () != string_slice ());
774 4 : ASSERT_TRUE (string_slice ("test") != string_slice ());
775 4 : ASSERT_TRUE ("test" != string_slice ());
776 4 : ASSERT_TRUE (string_slice () != string_slice ("test"));
777 4 : ASSERT_TRUE (string_slice () != "test");
778 4 : ASSERT_FALSE (string_slice ("test") != string_slice ("test"));
779 4 : ASSERT_FALSE ("test" != string_slice ("test"));
780 4 : ASSERT_FALSE (string_slice ("test") != "test");
781 4 : ASSERT_TRUE (string_slice ("a") != string_slice ("b"));
782 4 : ASSERT_TRUE ("a" != string_slice ("b"));
783 4 : ASSERT_TRUE (string_slice ("a") != "b");
784 4 : ASSERT_TRUE (string_slice ("b") != string_slice ("a"));
785 4 : ASSERT_FALSE (string_slice ("ab", 1) != string_slice ("a"));
786 4 : ASSERT_FALSE (string_slice ("ab", 1) != "a");
787 4 : ASSERT_TRUE (string_slice ("ab", 2) != string_slice ("a"));
788 4 : ASSERT_TRUE (string_slice ("ab", 2) != "a");
789 4 : }
790 :
791 : static void
792 4 : test_string_slice_invalid ()
793 : {
794 4 : ASSERT_FALSE (string_slice::invalid ().is_valid ());
795 4 : ASSERT_FALSE (string_slice (NULL, 1).is_valid ());
796 4 : ASSERT_TRUE (string_slice (NULL, (size_t) 0).is_valid ());
797 4 : ASSERT_TRUE (string_slice ("Test", (size_t) 0).is_valid ());
798 4 : ASSERT_TRUE (string_slice ().is_valid ());
799 4 : }
800 :
801 : static void
802 4 : test_string_slice_strip ()
803 : {
804 4 : ASSERT_EQ (string_slice (" test ").strip (), string_slice ("test"));
805 4 : ASSERT_EQ (string_slice ("\t test string\t \n ").strip (),
806 : string_slice ("test string"));
807 4 : ASSERT_EQ (string_slice ("test").strip (), string_slice ("test"));
808 4 : ASSERT_EQ (string_slice ().strip (), string_slice ());
809 4 : ASSERT_EQ (string_slice ("\t \n \t ").strip (), string_slice ());
810 4 : }
811 :
812 : /* Run all of the selftests within this file. */
813 :
814 : void
815 4 : vec_cc_tests ()
816 : {
817 4 : test_init ();
818 4 : test_quick_push ();
819 4 : test_safe_push ();
820 4 : test_truncate ();
821 4 : test_safe_grow_cleared ();
822 4 : test_pop ();
823 4 : test_safe_insert ();
824 4 : test_ordered_remove ();
825 4 : test_ordered_remove_if ();
826 4 : test_unordered_remove ();
827 4 : test_block_remove ();
828 4 : test_qsort ();
829 4 : test_reverse ();
830 4 : test_auto_delete_vec ();
831 4 : test_auto_alias ();
832 4 : test_string_slice_initializers ();
833 4 : test_string_slice_tokenize ();
834 4 : test_string_slice_strcmp ();
835 4 : test_string_slice_equality ();
836 4 : test_string_slice_inequality ();
837 4 : test_string_slice_invalid ();
838 4 : test_string_slice_strip ();
839 4 : }
840 :
841 : } // namespace selftest
842 :
843 : #endif /* #if CHECKING_P */
844 : #endif /* #ifndef GENERATOR_FILE */
|