xref: /dragonfly/contrib/gcc-8.0/gcc/ggc-tests.c (revision 38fd1498)
1*38fd1498Szrj /* Unit tests for GCC's garbage collector (and gengtype etc).
2*38fd1498Szrj    Copyright (C) 2015-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "config.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "tree-core.h"
24*38fd1498Szrj #include "tree.h"
25*38fd1498Szrj #include "ggc-internal.h" /* (for ggc_force_collect).  */
26*38fd1498Szrj #include "selftest.h"
27*38fd1498Szrj 
28*38fd1498Szrj #if CHECKING_P
29*38fd1498Szrj 
30*38fd1498Szrj /* A helper function for writing ggc tests.  */
31*38fd1498Szrj 
32*38fd1498Szrj void
forcibly_ggc_collect()33*38fd1498Szrj selftest::forcibly_ggc_collect ()
34*38fd1498Szrj {
35*38fd1498Szrj   ggc_force_collect = true;
36*38fd1498Szrj   ggc_collect ();
37*38fd1498Szrj   ggc_force_collect = false;
38*38fd1498Szrj }
39*38fd1498Szrj 
40*38fd1498Szrj /* The various GTY markers must be outside of a namespace to be seen by
41*38fd1498Szrj    gengtype, so we don't put this file within the selftest namespace.  */
42*38fd1498Szrj 
43*38fd1498Szrj 
44*38fd1498Szrj 
45*38fd1498Szrj /* Verify that a simple struct works, and that it can
46*38fd1498Szrj    own references to non-roots, and have them be marked.  */
47*38fd1498Szrj 
48*38fd1498Szrj struct GTY(()) test_struct
49*38fd1498Szrj {
50*38fd1498Szrj   struct test_struct *other;
51*38fd1498Szrj };
52*38fd1498Szrj 
53*38fd1498Szrj static GTY(()) test_struct *root_test_struct;
54*38fd1498Szrj 
55*38fd1498Szrj static void
test_basic_struct()56*38fd1498Szrj test_basic_struct ()
57*38fd1498Szrj {
58*38fd1498Szrj   root_test_struct = ggc_cleared_alloc <test_struct> ();
59*38fd1498Szrj   root_test_struct->other = ggc_cleared_alloc <test_struct> ();
60*38fd1498Szrj 
61*38fd1498Szrj   selftest::forcibly_ggc_collect ();
62*38fd1498Szrj 
63*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_test_struct));
64*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_test_struct->other));
65*38fd1498Szrj }
66*38fd1498Szrj 
67*38fd1498Szrj 
68*38fd1498Szrj 
69*38fd1498Szrj /* Selftest for GTY((length)).  */
70*38fd1498Szrj 
71*38fd1498Szrj /* A test struct using GTY((length)).  */
72*38fd1498Szrj 
73*38fd1498Szrj struct GTY(()) test_of_length
74*38fd1498Szrj {
75*38fd1498Szrj   int num_elem;
76*38fd1498Szrj   struct test_of_length * GTY ((length ("%h.num_elem"))) elem[1];
77*38fd1498Szrj };
78*38fd1498Szrj 
79*38fd1498Szrj static GTY(()) test_of_length *root_test_of_length;
80*38fd1498Szrj 
81*38fd1498Szrj static void
test_length()82*38fd1498Szrj test_length ()
83*38fd1498Szrj {
84*38fd1498Szrj   const int count = 5;
85*38fd1498Szrj   size_t sz = sizeof (test_of_length) + (count- 1) * sizeof (test_of_length *);
86*38fd1498Szrj   root_test_of_length = (test_of_length *)ggc_internal_cleared_alloc (sz);
87*38fd1498Szrj   root_test_of_length->num_elem = count;
88*38fd1498Szrj   for (int i = 0; i < count; i++)
89*38fd1498Szrj     root_test_of_length->elem[i] = ggc_cleared_alloc <test_of_length> ();
90*38fd1498Szrj 
91*38fd1498Szrj   selftest::forcibly_ggc_collect ();
92*38fd1498Szrj 
93*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_test_of_length));
94*38fd1498Szrj   for (int i = 0; i < count; i++)
95*38fd1498Szrj     ASSERT_TRUE (ggc_marked_p (root_test_of_length->elem[i]));
96*38fd1498Szrj }
97*38fd1498Szrj 
98*38fd1498Szrj 
99*38fd1498Szrj 
100*38fd1498Szrj /* Selftest for unions, GTY((tag)), and GTY((desc)).  */
101*38fd1498Szrj 
102*38fd1498Szrj /* A struct with a reference that's an a different offset to test_struct,
103*38fd1498Szrj    to ensure that we're using the correct types.  */
104*38fd1498Szrj 
105*38fd1498Szrj struct GTY(()) test_other
106*38fd1498Szrj {
107*38fd1498Szrj   char dummy[256];
108*38fd1498Szrj   test_struct *m_ptr;
109*38fd1498Szrj };
110*38fd1498Szrj 
111*38fd1498Szrj enum which_field
112*38fd1498Szrj {
113*38fd1498Szrj   WHICH_FIELD_USE_TEST_STRUCT,
114*38fd1498Szrj   WHICH_FIELD_USE_TEST_OTHER
115*38fd1498Szrj };
116*38fd1498Szrj 
117*38fd1498Szrj /* An example function for use by a GTY((desc)) marker.  */
118*38fd1498Szrj 
119*38fd1498Szrj static enum which_field
calc_desc(int kind)120*38fd1498Szrj calc_desc (int kind)
121*38fd1498Szrj {
122*38fd1498Szrj   switch (kind)
123*38fd1498Szrj     {
124*38fd1498Szrj     case 0: return WHICH_FIELD_USE_TEST_STRUCT;
125*38fd1498Szrj     case 1: return WHICH_FIELD_USE_TEST_OTHER;
126*38fd1498Szrj     default:
127*38fd1498Szrj       gcc_unreachable ();
128*38fd1498Szrj     }
129*38fd1498Szrj }
130*38fd1498Szrj 
131*38fd1498Szrj /* A struct containing an example of a union, showing the "tag" and
132*38fd1498Szrj    "desc" markers.  */
133*38fd1498Szrj 
134*38fd1498Szrj struct GTY(()) test_of_union
135*38fd1498Szrj {
136*38fd1498Szrj   int m_kind;
137*38fd1498Szrj   union u {
138*38fd1498Szrj     test_struct * GTY ((tag ("WHICH_FIELD_USE_TEST_STRUCT") )) u_test_struct;
139*38fd1498Szrj     test_other * GTY ((tag ("WHICH_FIELD_USE_TEST_OTHER") )) u_test_other;
140*38fd1498Szrj   } GTY ((desc ("calc_desc (%0.m_kind)"))) m_u;
141*38fd1498Szrj };
142*38fd1498Szrj 
143*38fd1498Szrj /* Example roots.  */
144*38fd1498Szrj 
145*38fd1498Szrj static GTY(()) test_of_union *root_test_of_union_1;
146*38fd1498Szrj static GTY(()) test_of_union *root_test_of_union_2;
147*38fd1498Szrj 
148*38fd1498Szrj /* Verify that the above work correctly.  */
149*38fd1498Szrj 
150*38fd1498Szrj static void
test_union()151*38fd1498Szrj test_union ()
152*38fd1498Szrj {
153*38fd1498Szrj   root_test_of_union_1 = ggc_cleared_alloc <test_of_union> ();
154*38fd1498Szrj   root_test_of_union_1->m_kind = 0;
155*38fd1498Szrj   test_struct *ts = ggc_cleared_alloc <test_struct> ();
156*38fd1498Szrj   root_test_of_union_1->m_u.u_test_struct = ts;
157*38fd1498Szrj 
158*38fd1498Szrj   root_test_of_union_2 = ggc_cleared_alloc <test_of_union> ();
159*38fd1498Szrj   root_test_of_union_2->m_kind = 1;
160*38fd1498Szrj   test_other *other = ggc_cleared_alloc <test_other> ();
161*38fd1498Szrj   root_test_of_union_2->m_u.u_test_other = other;
162*38fd1498Szrj   test_struct *referenced_by_other = ggc_cleared_alloc <test_struct> ();
163*38fd1498Szrj   other->m_ptr = referenced_by_other;
164*38fd1498Szrj 
165*38fd1498Szrj   selftest::forcibly_ggc_collect ();
166*38fd1498Szrj 
167*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_test_of_union_1));
168*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (ts));
169*38fd1498Szrj 
170*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_test_of_union_2));
171*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (other));
172*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (referenced_by_other));
173*38fd1498Szrj }
174*38fd1498Szrj 
175*38fd1498Szrj 
176*38fd1498Szrj 
177*38fd1498Szrj /* Verify that destructors get run when instances are collected.  */
178*38fd1498Szrj 
179*38fd1498Szrj struct GTY(()) test_struct_with_dtor
180*38fd1498Szrj {
181*38fd1498Szrj   /* This struct has a destructor; it *ought* to be called
182*38fd1498Szrj      by the ggc machinery when instances are collected.  */
~test_struct_with_dtortest_struct_with_dtor183*38fd1498Szrj   ~test_struct_with_dtor () { dtor_call_count++; }
184*38fd1498Szrj 
185*38fd1498Szrj   static int dtor_call_count;
186*38fd1498Szrj };
187*38fd1498Szrj 
188*38fd1498Szrj int test_struct_with_dtor::dtor_call_count;
189*38fd1498Szrj 
190*38fd1498Szrj static void
test_finalization()191*38fd1498Szrj test_finalization ()
192*38fd1498Szrj {
193*38fd1498Szrj #if GCC_VERSION >= 4003
194*38fd1498Szrj   ASSERT_FALSE (need_finalization_p <test_struct> ());
195*38fd1498Szrj   ASSERT_TRUE (need_finalization_p <test_struct_with_dtor> ());
196*38fd1498Szrj #endif
197*38fd1498Szrj 
198*38fd1498Szrj   /* Create some garbage.  */
199*38fd1498Szrj   const int count = 10;
200*38fd1498Szrj   for (int i = 0; i < count; i++)
201*38fd1498Szrj     ggc_cleared_alloc <test_struct_with_dtor> ();
202*38fd1498Szrj 
203*38fd1498Szrj   test_struct_with_dtor::dtor_call_count = 0;
204*38fd1498Szrj 
205*38fd1498Szrj   selftest::forcibly_ggc_collect ();
206*38fd1498Szrj 
207*38fd1498Szrj   /* Verify that the destructor was run for each instance.  */
208*38fd1498Szrj   ASSERT_EQ (count, test_struct_with_dtor::dtor_call_count);
209*38fd1498Szrj }
210*38fd1498Szrj 
211*38fd1498Szrj 
212*38fd1498Szrj 
213*38fd1498Szrj /* Verify that a global can be marked as "deletable".  */
214*38fd1498Szrj 
215*38fd1498Szrj static GTY((deletable)) test_struct *test_of_deletable;
216*38fd1498Szrj 
217*38fd1498Szrj static void
test_deletable_global()218*38fd1498Szrj test_deletable_global ()
219*38fd1498Szrj {
220*38fd1498Szrj   test_of_deletable = ggc_cleared_alloc <test_struct> ();
221*38fd1498Szrj   ASSERT_TRUE (test_of_deletable != NULL);
222*38fd1498Szrj 
223*38fd1498Szrj   selftest::forcibly_ggc_collect ();
224*38fd1498Szrj 
225*38fd1498Szrj   ASSERT_EQ (NULL, test_of_deletable);
226*38fd1498Szrj }
227*38fd1498Szrj 
228*38fd1498Szrj 
229*38fd1498Szrj 
230*38fd1498Szrj /* Verify that gengtype etc can cope with inheritance.  */
231*38fd1498Szrj 
232*38fd1498Szrj class GTY((desc("%h.m_kind"), tag("0"))) example_base
233*38fd1498Szrj {
234*38fd1498Szrj  public:
example_base()235*38fd1498Szrj   example_base ()
236*38fd1498Szrj     : m_kind (0),
237*38fd1498Szrj       m_a (ggc_cleared_alloc <test_struct> ())
238*38fd1498Szrj   {}
239*38fd1498Szrj 
240*38fd1498Szrj   void *
new(size_t sz)241*38fd1498Szrj   operator new (size_t sz)
242*38fd1498Szrj   {
243*38fd1498Szrj     return ggc_internal_cleared_alloc (sz);
244*38fd1498Szrj   }
245*38fd1498Szrj 
246*38fd1498Szrj  protected:
example_base(int kind)247*38fd1498Szrj   example_base (int kind)
248*38fd1498Szrj     : m_kind (kind),
249*38fd1498Szrj       m_a (ggc_cleared_alloc <test_struct> ())
250*38fd1498Szrj   {}
251*38fd1498Szrj 
252*38fd1498Szrj  public:
253*38fd1498Szrj   int m_kind;
254*38fd1498Szrj   test_struct *m_a;
255*38fd1498Szrj };
256*38fd1498Szrj 
257*38fd1498Szrj class GTY((tag("1"))) some_subclass : public example_base
258*38fd1498Szrj {
259*38fd1498Szrj  public:
some_subclass()260*38fd1498Szrj   some_subclass ()
261*38fd1498Szrj     : example_base (1),
262*38fd1498Szrj       m_b (ggc_cleared_alloc <test_struct> ())
263*38fd1498Szrj   {}
264*38fd1498Szrj 
265*38fd1498Szrj   test_struct *m_b;
266*38fd1498Szrj };
267*38fd1498Szrj 
268*38fd1498Szrj class GTY((tag("2"))) some_other_subclass : public example_base
269*38fd1498Szrj {
270*38fd1498Szrj  public:
some_other_subclass()271*38fd1498Szrj   some_other_subclass ()
272*38fd1498Szrj     : example_base (2),
273*38fd1498Szrj       m_c (ggc_cleared_alloc <test_struct> ())
274*38fd1498Szrj   {}
275*38fd1498Szrj 
276*38fd1498Szrj   test_struct *m_c;
277*38fd1498Szrj };
278*38fd1498Szrj 
279*38fd1498Szrj /* Various test roots, both expressed as a ptr to the actual class, and
280*38fd1498Szrj    as a ptr to the base class.  */
281*38fd1498Szrj static GTY(()) example_base *test_example_base;
282*38fd1498Szrj static GTY(()) some_subclass *test_some_subclass;
283*38fd1498Szrj static GTY(()) some_other_subclass *test_some_other_subclass;
284*38fd1498Szrj static GTY(()) example_base *test_some_subclass_as_base_ptr;
285*38fd1498Szrj static GTY(()) example_base *test_some_other_subclass_as_base_ptr;
286*38fd1498Szrj 
287*38fd1498Szrj static void
test_inheritance()288*38fd1498Szrj test_inheritance ()
289*38fd1498Szrj {
290*38fd1498Szrj   test_example_base = new example_base ();
291*38fd1498Szrj   test_some_subclass = new some_subclass ();
292*38fd1498Szrj   test_some_other_subclass = new some_other_subclass ();
293*38fd1498Szrj   test_some_subclass_as_base_ptr = new some_subclass ();
294*38fd1498Szrj   test_some_other_subclass_as_base_ptr = new some_other_subclass ();
295*38fd1498Szrj 
296*38fd1498Szrj   selftest::forcibly_ggc_collect ();
297*38fd1498Szrj 
298*38fd1498Szrj   /* Verify that the roots and everything referenced by them got marked
299*38fd1498Szrj      (both for fields in the base class and those in subclasses).  */
300*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_example_base));
301*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_example_base->m_a));
302*38fd1498Szrj 
303*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_subclass));
304*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_subclass->m_a));
305*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_subclass->m_b));
306*38fd1498Szrj 
307*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass));
308*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass->m_a));
309*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass->m_c));
310*38fd1498Szrj 
311*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr));
312*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_subclass_as_base_ptr->m_a));
313*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (((some_subclass *)
314*38fd1498Szrj 			      test_some_subclass_as_base_ptr)->m_b));
315*38fd1498Szrj 
316*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr));
317*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (test_some_other_subclass_as_base_ptr->m_a));
318*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (((some_other_subclass *)
319*38fd1498Szrj 			      test_some_other_subclass_as_base_ptr)->m_c));
320*38fd1498Szrj }
321*38fd1498Szrj 
322*38fd1498Szrj 
323*38fd1498Szrj 
324*38fd1498Szrj /* Test of chain_next/chain_prev
325*38fd1498Szrj 
326*38fd1498Szrj    Construct a very long linked list, so that without
327*38fd1498Szrj    the chain_next/chain_prev optimization we'd have
328*38fd1498Szrj    a stack overflow when gt_ggc_mx_test_node recurses.  */
329*38fd1498Szrj 
330*38fd1498Szrj struct GTY(( chain_next ("%h.m_next"),
331*38fd1498Szrj 	     chain_prev ("%h.m_prev") )) test_node
332*38fd1498Szrj {
333*38fd1498Szrj   test_node *m_prev;
334*38fd1498Szrj   test_node *m_next;
335*38fd1498Szrj   int m_idx;
336*38fd1498Szrj };
337*38fd1498Szrj 
338*38fd1498Szrj static GTY(()) test_node *root_test_node;
339*38fd1498Szrj 
340*38fd1498Szrj static void
test_chain_next()341*38fd1498Szrj test_chain_next ()
342*38fd1498Szrj {
343*38fd1498Szrj   /* Ideally we would construct a long list so that the number of
344*38fd1498Szrj      stack frames would be deep enough to crash if gengtype has created
345*38fd1498Szrj      something that recurses.
346*38fd1498Szrj 
347*38fd1498Szrj      However, as the list is lengthened to increase the chance of
348*38fd1498Szrj      overflowing the stack, the test will require more time and memory
349*38fd1498Szrj      to run.  On a Fedora 20 x86_64 box with 128GB of RAM, count=2000000
350*38fd1498Szrj      without the chain_next optimization reliably overflowed the stack,
351*38fd1498Szrj      but the test took 0.5s to run.
352*38fd1498Szrj 
353*38fd1498Szrj      For now this test runs with a low value for "count", which defeats
354*38fd1498Szrj      the main purpose of the test - though it at least gives us coverage
355*38fd1498Szrj      for walking a GTY((chain_next)) list.
356*38fd1498Szrj 
357*38fd1498Szrj      We could potentially increase this value once we have a better sense
358*38fd1498Szrj      of the time and space requirements of the test on different hosts,
359*38fd1498Szrj      or perhaps find a way to reduce the stack size when running this
360*38fd1498Szrj      testcase.  */
361*38fd1498Szrj   const int count = 10;
362*38fd1498Szrj 
363*38fd1498Szrj   /* Build the linked list.  */
364*38fd1498Szrj   root_test_node = ggc_cleared_alloc <test_node> ();
365*38fd1498Szrj   test_node *tail_node = root_test_node;
366*38fd1498Szrj   for (int i = 0; i < count; i++)
367*38fd1498Szrj     {
368*38fd1498Szrj       test_node *new_node = ggc_cleared_alloc <test_node> ();
369*38fd1498Szrj       tail_node->m_next = new_node;
370*38fd1498Szrj       new_node->m_prev = tail_node;
371*38fd1498Szrj       new_node->m_idx = i;
372*38fd1498Szrj       tail_node = new_node;
373*38fd1498Szrj     }
374*38fd1498Szrj 
375*38fd1498Szrj   selftest::forcibly_ggc_collect ();
376*38fd1498Szrj 
377*38fd1498Szrj   /* If we got here, we survived.  */
378*38fd1498Szrj 
379*38fd1498Szrj   /* Verify that all nodes in the list were marked.  */
380*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_test_node));
381*38fd1498Szrj   test_node *iter_node = root_test_node->m_next;
382*38fd1498Szrj   for (int i = 0; i < count; i++)
383*38fd1498Szrj     {
384*38fd1498Szrj       ASSERT_TRUE (ggc_marked_p (iter_node));
385*38fd1498Szrj       ASSERT_EQ (i, iter_node->m_idx);
386*38fd1498Szrj       iter_node = iter_node->m_next;
387*38fd1498Szrj     }
388*38fd1498Szrj }
389*38fd1498Szrj 
390*38fd1498Szrj 
391*38fd1498Szrj 
392*38fd1498Szrj /* Test for GTY((user)).  */
393*38fd1498Szrj 
394*38fd1498Szrj struct GTY((user)) user_struct
395*38fd1498Szrj {
396*38fd1498Szrj   char dummy[16];
397*38fd1498Szrj   test_struct *m_ptr;
398*38fd1498Szrj };
399*38fd1498Szrj 
400*38fd1498Szrj static GTY(()) user_struct *root_user_struct_ptr;
401*38fd1498Szrj 
402*38fd1498Szrj /* A global for verifying that the user-provided gt_ggc_mx gets
403*38fd1498Szrj    called.  */
404*38fd1498Szrj static int num_calls_to_user_gt_ggc_mx;
405*38fd1498Szrj 
406*38fd1498Szrj /* User-provided implementation of gt_ggc_mx.  */
407*38fd1498Szrj 
408*38fd1498Szrj static void
gt_ggc_mx(user_struct * p)409*38fd1498Szrj gt_ggc_mx (user_struct *p)
410*38fd1498Szrj {
411*38fd1498Szrj   num_calls_to_user_gt_ggc_mx++;
412*38fd1498Szrj   gt_ggc_mx_test_struct (p->m_ptr);
413*38fd1498Szrj }
414*38fd1498Szrj 
415*38fd1498Szrj /* User-provided implementation of gt_pch_nx.  */
416*38fd1498Szrj 
417*38fd1498Szrj static void
gt_pch_nx(user_struct * p)418*38fd1498Szrj gt_pch_nx (user_struct *p)
419*38fd1498Szrj {
420*38fd1498Szrj   gt_pch_nx_test_struct (p->m_ptr);
421*38fd1498Szrj }
422*38fd1498Szrj 
423*38fd1498Szrj /* User-provided implementation of gt_pch_nx.  */
424*38fd1498Szrj 
425*38fd1498Szrj static void
gt_pch_nx(user_struct * p,gt_pointer_operator op,void * cookie)426*38fd1498Szrj gt_pch_nx (user_struct *p, gt_pointer_operator op, void *cookie)
427*38fd1498Szrj {
428*38fd1498Szrj   op (&(p->m_ptr), cookie);
429*38fd1498Szrj }
430*38fd1498Szrj 
431*38fd1498Szrj /* Verify that GTY((user)) works.  */
432*38fd1498Szrj 
433*38fd1498Szrj static void
test_user_struct()434*38fd1498Szrj test_user_struct ()
435*38fd1498Szrj {
436*38fd1498Szrj   root_user_struct_ptr = ggc_cleared_alloc <user_struct> ();
437*38fd1498Szrj   test_struct *referenced = ggc_cleared_alloc <test_struct> ();
438*38fd1498Szrj   root_user_struct_ptr->m_ptr = referenced;
439*38fd1498Szrj 
440*38fd1498Szrj   num_calls_to_user_gt_ggc_mx = 0;
441*38fd1498Szrj 
442*38fd1498Szrj   selftest::forcibly_ggc_collect ();
443*38fd1498Szrj 
444*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (root_user_struct_ptr));
445*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (referenced));
446*38fd1498Szrj   ASSERT_TRUE (num_calls_to_user_gt_ggc_mx > 0);
447*38fd1498Szrj }
448*38fd1498Szrj 
449*38fd1498Szrj 
450*38fd1498Szrj 
451*38fd1498Szrj /* Smoketest to ensure that the tree type is marked.  */
452*38fd1498Szrj 
453*38fd1498Szrj static GTY(()) tree dummy_unittesting_tree;
454*38fd1498Szrj 
455*38fd1498Szrj static void
test_tree_marking()456*38fd1498Szrj test_tree_marking ()
457*38fd1498Szrj {
458*38fd1498Szrj   dummy_unittesting_tree = build_int_cst (integer_type_node, 1066);
459*38fd1498Szrj 
460*38fd1498Szrj   selftest::forcibly_ggc_collect ();
461*38fd1498Szrj 
462*38fd1498Szrj   ASSERT_TRUE (ggc_marked_p (dummy_unittesting_tree));
463*38fd1498Szrj }
464*38fd1498Szrj 
465*38fd1498Szrj 
466*38fd1498Szrj 
467*38fd1498Szrj /* Ideas for other tests:
468*38fd1498Szrj    - pch-handling  */
469*38fd1498Szrj 
470*38fd1498Szrj namespace selftest {
471*38fd1498Szrj 
472*38fd1498Szrj /* Run all of the selftests within this file.  */
473*38fd1498Szrj 
474*38fd1498Szrj void
ggc_tests_c_tests()475*38fd1498Szrj ggc_tests_c_tests ()
476*38fd1498Szrj {
477*38fd1498Szrj   test_basic_struct ();
478*38fd1498Szrj   test_length ();
479*38fd1498Szrj   test_union ();
480*38fd1498Szrj   test_finalization ();
481*38fd1498Szrj   test_deletable_global ();
482*38fd1498Szrj   test_inheritance ();
483*38fd1498Szrj   test_chain_next ();
484*38fd1498Szrj   test_user_struct ();
485*38fd1498Szrj   test_tree_marking ();
486*38fd1498Szrj }
487*38fd1498Szrj 
488*38fd1498Szrj } // namespace selftest
489*38fd1498Szrj 
490*38fd1498Szrj #include "gt-ggc-tests.h"
491*38fd1498Szrj 
492*38fd1498Szrj #else /* #if CHECKING_P */
493*38fd1498Szrj 
494*38fd1498Szrj /* The #if CHECKING_P code above has various GTY-marked roots.
495*38fd1498Szrj    gengtype has no knowledge of the preprocessor, and so detects
496*38fd1498Szrj    these roots and writes them out to gt-ggc-tests.h.
497*38fd1498Szrj    In a !CHECKING_P build we can ignore gt-ggc-tests.h, but the
498*38fd1498Szrj    root tables are referenced in the various generated gtype-*.c
499*38fd1498Szrj    files like this:
500*38fd1498Szrj 
501*38fd1498Szrj       ...snip...
502*38fd1498Szrj       extern const struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[];
503*38fd1498Szrj       ...snip...
504*38fd1498Szrj 
505*38fd1498Szrj       EXPORTED_CONST struct ggc_root_tab * const gt_ggc_rtab[] = {
506*38fd1498Szrj         ...snip...
507*38fd1498Szrj         gt_ggc_r_gt_ggc_tests_h,
508*38fd1498Szrj         ...snip...
509*38fd1498Szrj       };
510*38fd1498Szrj 
511*38fd1498Szrj     Hence to avoid a link failure, we provide dummy implementations
512*38fd1498Szrj     of these root tables in an unchecked build.
513*38fd1498Szrj 
514*38fd1498Szrj     Note that these conditional roots imply that PCH files are
515*38fd1498Szrj     incompatible between checked and unchecked builds.  */
516*38fd1498Szrj 
517*38fd1498Szrj EXPORTED_CONST struct ggc_root_tab gt_ggc_r_gt_ggc_tests_h[] = {
518*38fd1498Szrj   LAST_GGC_ROOT_TAB
519*38fd1498Szrj };
520*38fd1498Szrj 
521*38fd1498Szrj EXPORTED_CONST struct ggc_root_tab gt_ggc_rd_gt_ggc_tests_h[] = {
522*38fd1498Szrj   LAST_GGC_ROOT_TAB
523*38fd1498Szrj };
524*38fd1498Szrj 
525*38fd1498Szrj #endif /* #else clause of #if CHECKING_P */
526