1 /* Unit tests for GCC's garbage collector (and gengtype etc).
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
23 #include "tree-core.h"
25 #include "ggc-internal.h" /* (for ggc_force_collect). */
30 /* A helper function for writing ggc tests. */
33 selftest::forcibly_ggc_collect ()
35 ggc_force_collect
= true;
37 ggc_force_collect
= false;
40 /* The various GTY markers must be outside of a namespace to be seen by
41 gengtype, so we don't put this file within the selftest namespace. */
45 /* Verify that a simple struct works, and that it can
46 own references to non-roots, and have them be marked. */
48 struct GTY(()) test_struct
50 struct test_struct
*other
;
53 static GTY(()) test_struct
*root_test_struct
;
58 root_test_struct
= ggc_cleared_alloc
<test_struct
> ();
59 root_test_struct
->other
= ggc_cleared_alloc
<test_struct
> ();
61 selftest::forcibly_ggc_collect ();
63 ASSERT_TRUE (ggc_marked_p (root_test_struct
));
64 ASSERT_TRUE (ggc_marked_p (root_test_struct
->other
));
69 /* Selftest for GTY((length)). */
71 /* A test struct using GTY((length)). */
73 struct GTY(()) test_of_length
76 struct test_of_length
* GTY ((length ("%h.num_elem"))) elem
[1];
79 static GTY(()) test_of_length
*root_test_of_length
;
85 size_t sz
= sizeof (test_of_length
) + (count
- 1) * sizeof (test_of_length
*);
86 root_test_of_length
= (test_of_length
*)ggc_internal_cleared_alloc (sz
);
87 root_test_of_length
->num_elem
= count
;
88 for (int i
= 0; i
< count
; i
++)
89 root_test_of_length
->elem
[i
] = ggc_cleared_alloc
<test_of_length
> ();
91 selftest::forcibly_ggc_collect ();
93 ASSERT_TRUE (ggc_marked_p (root_test_of_length
));
94 for (int i
= 0; i
< count
; i
++)
95 ASSERT_TRUE (ggc_marked_p (root_test_of_length
->elem
[i
]));
100 /* Selftest for unions, GTY((tag)), and GTY((desc)). */
102 /* A struct with a reference that's an a different offset to test_struct,
103 to ensure that we're using the correct types. */
105 struct GTY(()) test_other
113 WHICH_FIELD_USE_TEST_STRUCT
,
114 WHICH_FIELD_USE_TEST_OTHER
117 /* An example function for use by a GTY((desc)) marker. */
119 static enum which_field
124 case 0: return WHICH_FIELD_USE_TEST_STRUCT
;
125 case 1: return WHICH_FIELD_USE_TEST_OTHER
;
131 /* A struct containing an example of a union, showing the "tag" and
134 struct GTY(()) test_of_union
138 test_struct
* GTY ((tag ("WHICH_FIELD_USE_TEST_STRUCT") )) u_test_struct
;
139 test_other
* GTY ((tag ("WHICH_FIELD_USE_TEST_OTHER") )) u_test_other
;
140 } GTY ((desc ("calc_desc (%0.m_kind)"))) m_u
;
145 static GTY(()) test_of_union
*root_test_of_union_1
;
146 static GTY(()) test_of_union
*root_test_of_union_2
;
148 /* Verify that the above work correctly. */
153 root_test_of_union_1
= ggc_cleared_alloc
<test_of_union
> ();
154 root_test_of_union_1
->m_kind
= 0;
155 test_struct
*ts
= ggc_cleared_alloc
<test_struct
> ();
156 root_test_of_union_1
->m_u
.u_test_struct
= ts
;
158 root_test_of_union_2
= ggc_cleared_alloc
<test_of_union
> ();
159 root_test_of_union_2
->m_kind
= 1;
160 test_other
*other
= ggc_cleared_alloc
<test_other
> ();
161 root_test_of_union_2
->m_u
.u_test_other
= other
;
162 test_struct
*referenced_by_other
= ggc_cleared_alloc
<test_struct
> ();
163 other
->m_ptr
= referenced_by_other
;
165 selftest::forcibly_ggc_collect ();
167 ASSERT_TRUE (ggc_marked_p (root_test_of_union_1
));
168 ASSERT_TRUE (ggc_marked_p (ts
));
170 ASSERT_TRUE (ggc_marked_p (root_test_of_union_2
));
171 ASSERT_TRUE (ggc_marked_p (other
));
172 ASSERT_TRUE (ggc_marked_p (referenced_by_other
));
177 /* Verify that destructors get run when instances are collected. */
179 class GTY(()) test_struct_with_dtor
182 /* This struct has a destructor; it *ought* to be called
183 by the ggc machinery when instances are collected. */
184 ~test_struct_with_dtor () { dtor_call_count
++; }
186 static int dtor_call_count
;
189 int test_struct_with_dtor::dtor_call_count
;
194 #if GCC_VERSION >= 4003
195 ASSERT_FALSE (need_finalization_p
<test_struct
> ());
196 ASSERT_TRUE (need_finalization_p
<test_struct_with_dtor
> ());
199 /* Create some garbage. */
200 const int count
= 10;
201 for (int i
= 0; i
< count
; i
++)
202 ggc_cleared_alloc
<test_struct_with_dtor
> ();
204 test_struct_with_dtor::dtor_call_count
= 0;
206 selftest::forcibly_ggc_collect ();
208 /* Verify that the destructor was run for each instance. */
209 ASSERT_EQ (count
, test_struct_with_dtor::dtor_call_count
);
214 /* Verify that a global can be marked as "deletable". */
216 static GTY((deletable
)) test_struct
*test_of_deletable
;
219 test_deletable_global ()
221 test_of_deletable
= ggc_cleared_alloc
<test_struct
> ();
222 ASSERT_TRUE (test_of_deletable
!= NULL
);
224 selftest::forcibly_ggc_collect ();
226 ASSERT_EQ (NULL
, test_of_deletable
);
231 /* Verify that gengtype etc can cope with inheritance. */
233 class GTY((desc("%h.m_kind"), tag("0"))) example_base
238 m_a (ggc_cleared_alloc
<test_struct
> ())
242 operator new (size_t sz
)
244 return ggc_internal_cleared_alloc (sz
);
248 example_base (int kind
)
250 m_a (ggc_cleared_alloc
<test_struct
> ())
258 class GTY((tag("1"))) some_subclass
: public example_base
263 m_b (ggc_cleared_alloc
<test_struct
> ())
269 class GTY((tag("2"))) some_other_subclass
: public example_base
272 some_other_subclass ()
274 m_c (ggc_cleared_alloc
<test_struct
> ())
280 /* Various test roots, both expressed as a ptr to the actual class, and
281 as a ptr to the base class. */
282 static GTY(()) example_base
*test_example_base
;
283 static GTY(()) some_subclass
*test_some_subclass
;
284 static GTY(()) some_other_subclass
*test_some_other_subclass
;
285 static GTY(()) example_base
*test_some_subclass_as_base_ptr
;
286 static GTY(()) example_base
*test_some_other_subclass_as_base_ptr
;
291 test_example_base
= new example_base ();
292 test_some_subclass
= new some_subclass ();
293 test_some_other_subclass
= new some_other_subclass ();
294 test_some_subclass_as_base_ptr
= new some_subclass ();
295 test_some_other_subclass_as_base_ptr
= new some_other_subclass ();
297 selftest::forcibly_ggc_collect ();
299 /* Verify that the roots and everything referenced by them got marked
300 (both for fields in the base class and those in subclasses). */
301 ASSERT_TRUE (ggc_marked_p (test_example_base
));
302 ASSERT_TRUE (ggc_marked_p (test_example_base
->m_a
));
304 ASSERT_TRUE (ggc_marked_p (test_some_subclass
));
305 ASSERT_TRUE (ggc_marked_p (test_some_subclass
->m_a
));
306 ASSERT_TRUE (ggc_marked_p (test_some_subclass
->m_b
));
308 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass
));
309 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass
->m_a
));
310 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass
->m_c
));
312 ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr
));
313 ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr
->m_a
));
314 ASSERT_TRUE (ggc_marked_p (((some_subclass
*)
315 test_some_subclass_as_base_ptr
)->m_b
));
317 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr
));
318 ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr
->m_a
));
319 ASSERT_TRUE (ggc_marked_p (((some_other_subclass
*)
320 test_some_other_subclass_as_base_ptr
)->m_c
));
325 /* Test of chain_next/chain_prev
327 Construct a very long linked list, so that without
328 the chain_next/chain_prev optimization we'd have
329 a stack overflow when gt_ggc_mx_test_node recurses. */
331 struct GTY(( chain_next ("%h.m_next"),
332 chain_prev ("%h.m_prev") )) test_node
339 static GTY(()) test_node
*root_test_node
;
344 /* Ideally we would construct a long list so that the number of
345 stack frames would be deep enough to crash if gengtype has created
346 something that recurses.
348 However, as the list is lengthened to increase the chance of
349 overflowing the stack, the test will require more time and memory
350 to run. On a Fedora 20 x86_64 box with 128GB of RAM, count=2000000
351 without the chain_next optimization reliably overflowed the stack,
352 but the test took 0.5s to run.
354 For now this test runs with a low value for "count", which defeats
355 the main purpose of the test - though it at least gives us coverage
356 for walking a GTY((chain_next)) list.
358 We could potentially increase this value once we have a better sense
359 of the time and space requirements of the test on different hosts,
360 or perhaps find a way to reduce the stack size when running this
362 const int count
= 10;
364 /* Build the linked list. */
365 root_test_node
= ggc_cleared_alloc
<test_node
> ();
366 test_node
*tail_node
= root_test_node
;
367 for (int i
= 0; i
< count
; i
++)
369 test_node
*new_node
= ggc_cleared_alloc
<test_node
> ();
370 tail_node
->m_next
= new_node
;
371 new_node
->m_prev
= tail_node
;
373 tail_node
= new_node
;
376 selftest::forcibly_ggc_collect ();
378 /* If we got here, we survived. */
380 /* Verify that all nodes in the list were marked. */
381 ASSERT_TRUE (ggc_marked_p (root_test_node
));
382 test_node
*iter_node
= root_test_node
->m_next
;
383 for (int i
= 0; i
< count
; i
++)
385 ASSERT_TRUE (ggc_marked_p (iter_node
));
386 ASSERT_EQ (i
, iter_node
->m_idx
);
387 iter_node
= iter_node
->m_next
;
393 /* Test for GTY((user)). */
395 struct GTY((user
)) user_struct
401 static GTY(()) user_struct
*root_user_struct_ptr
;
403 /* A global for verifying that the user-provided gt_ggc_mx gets
405 static int num_calls_to_user_gt_ggc_mx
;
407 /* User-provided implementation of gt_ggc_mx. */
410 gt_ggc_mx (user_struct
*p
)
412 num_calls_to_user_gt_ggc_mx
++;
413 gt_ggc_mx_test_struct (p
->m_ptr
);
416 /* User-provided implementation of gt_pch_nx. */
419 gt_pch_nx (user_struct
*p
)
421 gt_pch_nx_test_struct (p
->m_ptr
);
424 /* User-provided implementation of gt_pch_nx. */
427 gt_pch_nx (user_struct
*p
, gt_pointer_operator op
, void *cookie
)
429 op (&(p
->m_ptr
), cookie
);
432 /* Verify that GTY((user)) works. */
437 root_user_struct_ptr
= ggc_cleared_alloc
<user_struct
> ();
438 test_struct
*referenced
= ggc_cleared_alloc
<test_struct
> ();
439 root_user_struct_ptr
->m_ptr
= referenced
;
441 num_calls_to_user_gt_ggc_mx
= 0;
443 selftest::forcibly_ggc_collect ();
445 ASSERT_TRUE (ggc_marked_p (root_user_struct_ptr
));
446 ASSERT_TRUE (ggc_marked_p (referenced
));
447 ASSERT_TRUE (num_calls_to_user_gt_ggc_mx
> 0);
452 /* Smoketest to ensure that the tree type is marked. */
454 static GTY(()) tree dummy_unittesting_tree
;
459 dummy_unittesting_tree
= build_int_cst (integer_type_node
, 1066);
461 selftest::forcibly_ggc_collect ();
463 ASSERT_TRUE (ggc_marked_p (dummy_unittesting_tree
));
468 /* Ideas for other tests:
473 /* Run all of the selftests within this file. */
478 test_basic_struct ();
481 test_finalization ();
482 test_deletable_global ();
486 test_tree_marking ();
489 } // namespace selftest
491 #include "gt-ggc-tests.h"
493 #else /* #if CHECKING_P */
495 /* The #if CHECKING_P code above has various GTY-marked roots.
496 gengtype has no knowledge of the preprocessor, and so detects
497 these roots and writes them out to gt-ggc-tests.h.
498 In a !CHECKING_P build we can ignore gt-ggc-tests.h, but the
499 root tables are referenced in the various generated gtype-*.c
503 extern const struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[];
506 EXPORTED_CONST struct ggc_root_tab * const gt_ggc_rtab[] = {
508 gt_ggc_r_gt_ggc_tests_h,
512 Hence to avoid a link failure, we provide dummy implementations
513 of these root tables in an unchecked build.
515 Note that these conditional roots imply that PCH files are
516 incompatible between checked and unchecked builds. */
518 EXPORTED_CONST
struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h
[] = {
522 EXPORTED_CONST
struct ggc_root_tab gt_ggc_rd_gt_ggc_tests_h
[] = {
526 #endif /* #else clause of #if CHECKING_P */