1*4c3eb207Smrg /* Paths through the code associated with a diagnostic.
2*4c3eb207Smrg Copyright (C) 2019-2020 Free Software Foundation, Inc.
3*4c3eb207Smrg Contributed by David Malcolm <dmalcolm@redhat.com>
4*4c3eb207Smrg
5*4c3eb207Smrg This file is part of GCC.
6*4c3eb207Smrg
7*4c3eb207Smrg GCC is free software; you can redistribute it and/or modify it under
8*4c3eb207Smrg the terms of the GNU General Public License as published by the Free
9*4c3eb207Smrg Software Foundation; either version 3, or (at your option) any later
10*4c3eb207Smrg version.
11*4c3eb207Smrg
12*4c3eb207Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*4c3eb207Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*4c3eb207Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15*4c3eb207Smrg for more details.
16*4c3eb207Smrg
17*4c3eb207Smrg You should have received a copy of the GNU General Public License
18*4c3eb207Smrg along with GCC; see the file COPYING3. If not see
19*4c3eb207Smrg <http://www.gnu.org/licenses/>. */
20*4c3eb207Smrg
21*4c3eb207Smrg #include "config.h"
22*4c3eb207Smrg #include "system.h"
23*4c3eb207Smrg #include "coretypes.h"
24*4c3eb207Smrg #include "tree.h"
25*4c3eb207Smrg #include "diagnostic.h"
26*4c3eb207Smrg #include "tree-pretty-print.h"
27*4c3eb207Smrg #include "gimple-pretty-print.h"
28*4c3eb207Smrg #include "tree-diagnostic.h"
29*4c3eb207Smrg #include "langhooks.h"
30*4c3eb207Smrg #include "intl.h"
31*4c3eb207Smrg #include "diagnostic-path.h"
32*4c3eb207Smrg #include "json.h"
33*4c3eb207Smrg #include "gcc-rich-location.h"
34*4c3eb207Smrg #include "diagnostic-color.h"
35*4c3eb207Smrg #include "diagnostic-event-id.h"
36*4c3eb207Smrg #include "selftest.h"
37*4c3eb207Smrg #include "selftest-diagnostic.h"
38*4c3eb207Smrg
39*4c3eb207Smrg /* Anonymous namespace for path-printing code. */
40*4c3eb207Smrg
41*4c3eb207Smrg namespace {
42*4c3eb207Smrg
43*4c3eb207Smrg /* Subclass of range_label for showing a particular event
44*4c3eb207Smrg when showing a consecutive run of events within a diagnostic_path as
45*4c3eb207Smrg labelled ranges within one gcc_rich_location. */
46*4c3eb207Smrg
47*4c3eb207Smrg class path_label : public range_label
48*4c3eb207Smrg {
49*4c3eb207Smrg public:
path_label(const diagnostic_path * path,unsigned start_idx)50*4c3eb207Smrg path_label (const diagnostic_path *path, unsigned start_idx)
51*4c3eb207Smrg : m_path (path), m_start_idx (start_idx)
52*4c3eb207Smrg {}
53*4c3eb207Smrg
get_text(unsigned range_idx) const54*4c3eb207Smrg label_text get_text (unsigned range_idx) const FINAL OVERRIDE
55*4c3eb207Smrg {
56*4c3eb207Smrg unsigned event_idx = m_start_idx + range_idx;
57*4c3eb207Smrg const diagnostic_event &event = m_path->get_event (event_idx);
58*4c3eb207Smrg
59*4c3eb207Smrg /* Get the description of the event, perhaps with colorization:
60*4c3eb207Smrg normally, we don't colorize within a range_label, but this
61*4c3eb207Smrg is special-cased for diagnostic paths. */
62*4c3eb207Smrg bool colorize = pp_show_color (global_dc->printer);
63*4c3eb207Smrg label_text event_text (event.get_desc (colorize));
64*4c3eb207Smrg gcc_assert (event_text.m_buffer);
65*4c3eb207Smrg pretty_printer pp;
66*4c3eb207Smrg pp_show_color (&pp) = pp_show_color (global_dc->printer);
67*4c3eb207Smrg diagnostic_event_id_t event_id (event_idx);
68*4c3eb207Smrg pp_printf (&pp, "%@ %s", &event_id, event_text.m_buffer);
69*4c3eb207Smrg event_text.maybe_free ();
70*4c3eb207Smrg label_text result = label_text::take (xstrdup (pp_formatted_text (&pp)));
71*4c3eb207Smrg return result;
72*4c3eb207Smrg }
73*4c3eb207Smrg
74*4c3eb207Smrg private:
75*4c3eb207Smrg const diagnostic_path *m_path;
76*4c3eb207Smrg unsigned m_start_idx;
77*4c3eb207Smrg };
78*4c3eb207Smrg
79*4c3eb207Smrg /* Return true if E1 and E2 can be consolidated into the same run of events
80*4c3eb207Smrg when printing a diagnostic_path. */
81*4c3eb207Smrg
82*4c3eb207Smrg static bool
can_consolidate_events(const diagnostic_event & e1,const diagnostic_event & e2,bool check_locations)83*4c3eb207Smrg can_consolidate_events (const diagnostic_event &e1,
84*4c3eb207Smrg const diagnostic_event &e2,
85*4c3eb207Smrg bool check_locations)
86*4c3eb207Smrg {
87*4c3eb207Smrg if (e1.get_fndecl () != e2.get_fndecl ())
88*4c3eb207Smrg return false;
89*4c3eb207Smrg
90*4c3eb207Smrg if (e1.get_stack_depth () != e2.get_stack_depth ())
91*4c3eb207Smrg return false;
92*4c3eb207Smrg
93*4c3eb207Smrg if (check_locations)
94*4c3eb207Smrg {
95*4c3eb207Smrg location_t loc1 = e1.get_location ();
96*4c3eb207Smrg location_t loc2 = e2.get_location ();
97*4c3eb207Smrg
98*4c3eb207Smrg if (loc1 < RESERVED_LOCATION_COUNT
99*4c3eb207Smrg || loc2 < RESERVED_LOCATION_COUNT)
100*4c3eb207Smrg return false;
101*4c3eb207Smrg
102*4c3eb207Smrg /* Neither can be macro-based. */
103*4c3eb207Smrg if (linemap_location_from_macro_expansion_p (line_table, loc1))
104*4c3eb207Smrg return false;
105*4c3eb207Smrg if (linemap_location_from_macro_expansion_p (line_table, loc2))
106*4c3eb207Smrg return false;
107*4c3eb207Smrg }
108*4c3eb207Smrg
109*4c3eb207Smrg /* Passed all the tests. */
110*4c3eb207Smrg return true;
111*4c3eb207Smrg }
112*4c3eb207Smrg
113*4c3eb207Smrg /* A class for grouing together the events in a diagnostic_path into
114*4c3eb207Smrg ranges of events, partitioned by stack frame (i.e. by fndecl and
115*4c3eb207Smrg stack depth). */
116*4c3eb207Smrg
117*4c3eb207Smrg class path_summary
118*4c3eb207Smrg {
119*4c3eb207Smrg /* A range of consecutive events within a diagnostic_path,
120*4c3eb207Smrg all with the same fndecl and stack_depth, and which are suitable
121*4c3eb207Smrg to print with a single call to diagnostic_show_locus. */
122*4c3eb207Smrg struct event_range
123*4c3eb207Smrg {
event_range__anon1e00e3a70111::path_summary::event_range124*4c3eb207Smrg event_range (const diagnostic_path *path, unsigned start_idx,
125*4c3eb207Smrg const diagnostic_event &initial_event)
126*4c3eb207Smrg : m_path (path),
127*4c3eb207Smrg m_initial_event (initial_event),
128*4c3eb207Smrg m_fndecl (initial_event.get_fndecl ()),
129*4c3eb207Smrg m_stack_depth (initial_event.get_stack_depth ()),
130*4c3eb207Smrg m_start_idx (start_idx), m_end_idx (start_idx),
131*4c3eb207Smrg m_path_label (path, start_idx),
132*4c3eb207Smrg m_richloc (initial_event.get_location (), &m_path_label)
133*4c3eb207Smrg {}
134*4c3eb207Smrg
maybe_add_event__anon1e00e3a70111::path_summary::event_range135*4c3eb207Smrg bool maybe_add_event (const diagnostic_event &new_ev, unsigned idx,
136*4c3eb207Smrg bool check_rich_locations)
137*4c3eb207Smrg {
138*4c3eb207Smrg if (!can_consolidate_events (m_initial_event, new_ev,
139*4c3eb207Smrg check_rich_locations))
140*4c3eb207Smrg return false;
141*4c3eb207Smrg if (check_rich_locations)
142*4c3eb207Smrg if (!m_richloc.add_location_if_nearby (new_ev.get_location (),
143*4c3eb207Smrg false, &m_path_label))
144*4c3eb207Smrg return false;
145*4c3eb207Smrg m_end_idx = idx;
146*4c3eb207Smrg return true;
147*4c3eb207Smrg }
148*4c3eb207Smrg
149*4c3eb207Smrg /* Print the events in this range to DC, typically as a single
150*4c3eb207Smrg call to the printer's diagnostic_show_locus. */
151*4c3eb207Smrg
print__anon1e00e3a70111::path_summary::event_range152*4c3eb207Smrg void print (diagnostic_context *dc)
153*4c3eb207Smrg {
154*4c3eb207Smrg location_t initial_loc = m_initial_event.get_location ();
155*4c3eb207Smrg
156*4c3eb207Smrg /* Emit a span indicating the filename (and line/column) if the
157*4c3eb207Smrg line has changed relative to the last call to
158*4c3eb207Smrg diagnostic_show_locus. */
159*4c3eb207Smrg if (dc->show_caret)
160*4c3eb207Smrg {
161*4c3eb207Smrg expanded_location exploc
162*4c3eb207Smrg = linemap_client_expand_location_to_spelling_point
163*4c3eb207Smrg (initial_loc, LOCATION_ASPECT_CARET);
164*4c3eb207Smrg if (exploc.file != LOCATION_FILE (dc->last_location))
165*4c3eb207Smrg dc->start_span (dc, exploc);
166*4c3eb207Smrg }
167*4c3eb207Smrg
168*4c3eb207Smrg /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
169*4c3eb207Smrg primary location for an event, diagnostic_show_locus won't print
170*4c3eb207Smrg anything.
171*4c3eb207Smrg
172*4c3eb207Smrg In particular the label for the event won't get printed.
173*4c3eb207Smrg Fail more gracefully in this case by showing the event
174*4c3eb207Smrg index and text, at no particular location. */
175*4c3eb207Smrg if (get_pure_location (initial_loc) <= BUILTINS_LOCATION)
176*4c3eb207Smrg {
177*4c3eb207Smrg for (unsigned i = m_start_idx; i <= m_end_idx; i++)
178*4c3eb207Smrg {
179*4c3eb207Smrg const diagnostic_event &iter_event = m_path->get_event (i);
180*4c3eb207Smrg diagnostic_event_id_t event_id (i);
181*4c3eb207Smrg label_text event_text (iter_event.get_desc (true));
182*4c3eb207Smrg pretty_printer *pp = dc->printer;
183*4c3eb207Smrg pp_printf (pp, " %@: %s", &event_id, event_text.m_buffer);
184*4c3eb207Smrg pp_newline (pp);
185*4c3eb207Smrg event_text.maybe_free ();
186*4c3eb207Smrg }
187*4c3eb207Smrg return;
188*4c3eb207Smrg }
189*4c3eb207Smrg
190*4c3eb207Smrg /* Call diagnostic_show_locus to show the events using labels. */
191*4c3eb207Smrg diagnostic_show_locus (dc, &m_richloc, DK_DIAGNOSTIC_PATH);
192*4c3eb207Smrg
193*4c3eb207Smrg /* If we have a macro expansion, show the expansion to the user. */
194*4c3eb207Smrg if (linemap_location_from_macro_expansion_p (line_table, initial_loc))
195*4c3eb207Smrg {
196*4c3eb207Smrg gcc_assert (m_start_idx == m_end_idx);
197*4c3eb207Smrg maybe_unwind_expanded_macro_loc (dc, initial_loc);
198*4c3eb207Smrg }
199*4c3eb207Smrg }
200*4c3eb207Smrg
201*4c3eb207Smrg const diagnostic_path *m_path;
202*4c3eb207Smrg const diagnostic_event &m_initial_event;
203*4c3eb207Smrg tree m_fndecl;
204*4c3eb207Smrg int m_stack_depth;
205*4c3eb207Smrg unsigned m_start_idx;
206*4c3eb207Smrg unsigned m_end_idx;
207*4c3eb207Smrg path_label m_path_label;
208*4c3eb207Smrg gcc_rich_location m_richloc;
209*4c3eb207Smrg };
210*4c3eb207Smrg
211*4c3eb207Smrg public:
212*4c3eb207Smrg path_summary (const diagnostic_path &path, bool check_rich_locations);
213*4c3eb207Smrg
214*4c3eb207Smrg void print (diagnostic_context *dc, bool show_depths) const;
215*4c3eb207Smrg
get_num_ranges() const216*4c3eb207Smrg unsigned get_num_ranges () const { return m_ranges.length (); }
217*4c3eb207Smrg
218*4c3eb207Smrg private:
219*4c3eb207Smrg auto_delete_vec <event_range> m_ranges;
220*4c3eb207Smrg };
221*4c3eb207Smrg
222*4c3eb207Smrg /* path_summary's ctor. */
223*4c3eb207Smrg
path_summary(const diagnostic_path & path,bool check_rich_locations)224*4c3eb207Smrg path_summary::path_summary (const diagnostic_path &path,
225*4c3eb207Smrg bool check_rich_locations)
226*4c3eb207Smrg {
227*4c3eb207Smrg const unsigned num_events = path.num_events ();
228*4c3eb207Smrg
229*4c3eb207Smrg event_range *cur_event_range = NULL;
230*4c3eb207Smrg for (unsigned idx = 0; idx < num_events; idx++)
231*4c3eb207Smrg {
232*4c3eb207Smrg const diagnostic_event &event = path.get_event (idx);
233*4c3eb207Smrg if (cur_event_range)
234*4c3eb207Smrg if (cur_event_range->maybe_add_event (event, idx, check_rich_locations))
235*4c3eb207Smrg continue;
236*4c3eb207Smrg
237*4c3eb207Smrg cur_event_range = new event_range (&path, idx, event);
238*4c3eb207Smrg m_ranges.safe_push (cur_event_range);
239*4c3eb207Smrg }
240*4c3eb207Smrg }
241*4c3eb207Smrg
242*4c3eb207Smrg /* Write SPACES to PP. */
243*4c3eb207Smrg
244*4c3eb207Smrg static void
write_indent(pretty_printer * pp,int spaces)245*4c3eb207Smrg write_indent (pretty_printer *pp, int spaces)
246*4c3eb207Smrg {
247*4c3eb207Smrg for (int i = 0; i < spaces; i++)
248*4c3eb207Smrg pp_space (pp);
249*4c3eb207Smrg }
250*4c3eb207Smrg
251*4c3eb207Smrg /* Print FNDDECL to PP, quoting it if QUOTED is true.
252*4c3eb207Smrg
253*4c3eb207Smrg We can't use "%qE" here since we can't guarantee the capabilities
254*4c3eb207Smrg of PP. */
255*4c3eb207Smrg
256*4c3eb207Smrg static void
print_fndecl(pretty_printer * pp,tree fndecl,bool quoted)257*4c3eb207Smrg print_fndecl (pretty_printer *pp, tree fndecl, bool quoted)
258*4c3eb207Smrg {
259*4c3eb207Smrg const char *n = DECL_NAME (fndecl)
260*4c3eb207Smrg ? identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2))
261*4c3eb207Smrg : _("<anonymous>");
262*4c3eb207Smrg if (quoted)
263*4c3eb207Smrg pp_printf (pp, "%qs", n);
264*4c3eb207Smrg else
265*4c3eb207Smrg pp_string (pp, n);
266*4c3eb207Smrg }
267*4c3eb207Smrg
268*4c3eb207Smrg /* Print this path_summary to DC, giving an overview of the interprocedural
269*4c3eb207Smrg calls and returns.
270*4c3eb207Smrg
271*4c3eb207Smrg Print the event descriptions in a nested form, printing the event
272*4c3eb207Smrg descriptions within calls to diagnostic_show_locus, using labels to
273*4c3eb207Smrg show the events:
274*4c3eb207Smrg
275*4c3eb207Smrg 'foo' (events 1-2)
276*4c3eb207Smrg | NN |
277*4c3eb207Smrg | |
278*4c3eb207Smrg +--> 'bar' (events 3-4)
279*4c3eb207Smrg | NN |
280*4c3eb207Smrg | |
281*4c3eb207Smrg +--> 'baz' (events 5-6)
282*4c3eb207Smrg | NN |
283*4c3eb207Smrg | |
284*4c3eb207Smrg <------------ +
285*4c3eb207Smrg |
286*4c3eb207Smrg 'foo' (events 7-8)
287*4c3eb207Smrg | NN |
288*4c3eb207Smrg | |
289*4c3eb207Smrg +--> 'bar' (events 9-10)
290*4c3eb207Smrg | NN |
291*4c3eb207Smrg | |
292*4c3eb207Smrg +--> 'baz' (events 11-12)
293*4c3eb207Smrg | NN |
294*4c3eb207Smrg | |
295*4c3eb207Smrg
296*4c3eb207Smrg If SHOW_DEPTHS is true, append " (depth N)" to the header of each run
297*4c3eb207Smrg of events.
298*4c3eb207Smrg
299*4c3eb207Smrg For events with UNKNOWN_LOCATION, print a summary of each the event. */
300*4c3eb207Smrg
301*4c3eb207Smrg void
print(diagnostic_context * dc,bool show_depths) const302*4c3eb207Smrg path_summary::print (diagnostic_context *dc, bool show_depths) const
303*4c3eb207Smrg {
304*4c3eb207Smrg pretty_printer *pp = dc->printer;
305*4c3eb207Smrg
306*4c3eb207Smrg const int per_frame_indent = 2;
307*4c3eb207Smrg
308*4c3eb207Smrg const char *const line_color = "path";
309*4c3eb207Smrg const char *start_line_color
310*4c3eb207Smrg = colorize_start (pp_show_color (pp), line_color);
311*4c3eb207Smrg const char *end_line_color = colorize_stop (pp_show_color (pp));
312*4c3eb207Smrg
313*4c3eb207Smrg /* Keep track of column numbers of existing '|' characters for
314*4c3eb207Smrg stack depths we've already printed. */
315*4c3eb207Smrg const int EMPTY = -1;
316*4c3eb207Smrg const int DELETED = -2;
317*4c3eb207Smrg typedef int_hash <int, EMPTY, DELETED> vbar_hash;
318*4c3eb207Smrg hash_map <vbar_hash, int> vbar_column_for_depth;
319*4c3eb207Smrg
320*4c3eb207Smrg /* Print the ranges. */
321*4c3eb207Smrg const int base_indent = 2;
322*4c3eb207Smrg int cur_indent = base_indent;
323*4c3eb207Smrg unsigned i;
324*4c3eb207Smrg event_range *range;
325*4c3eb207Smrg FOR_EACH_VEC_ELT (m_ranges, i, range)
326*4c3eb207Smrg {
327*4c3eb207Smrg write_indent (pp, cur_indent);
328*4c3eb207Smrg if (i > 0)
329*4c3eb207Smrg {
330*4c3eb207Smrg const path_summary::event_range *prev_range
331*4c3eb207Smrg = m_ranges[i - 1];
332*4c3eb207Smrg if (range->m_stack_depth > prev_range->m_stack_depth)
333*4c3eb207Smrg {
334*4c3eb207Smrg /* Show pushed stack frame(s). */
335*4c3eb207Smrg const char *push_prefix = "+--> ";
336*4c3eb207Smrg pp_string (pp, start_line_color);
337*4c3eb207Smrg pp_string (pp, push_prefix);
338*4c3eb207Smrg pp_string (pp, end_line_color);
339*4c3eb207Smrg cur_indent += strlen (push_prefix);
340*4c3eb207Smrg }
341*4c3eb207Smrg }
342*4c3eb207Smrg if (range->m_fndecl)
343*4c3eb207Smrg {
344*4c3eb207Smrg print_fndecl (pp, range->m_fndecl, true);
345*4c3eb207Smrg pp_string (pp, ": ");
346*4c3eb207Smrg }
347*4c3eb207Smrg if (range->m_start_idx == range->m_end_idx)
348*4c3eb207Smrg pp_printf (pp, "event %i",
349*4c3eb207Smrg range->m_start_idx + 1);
350*4c3eb207Smrg else
351*4c3eb207Smrg pp_printf (pp, "events %i-%i",
352*4c3eb207Smrg range->m_start_idx + 1, range->m_end_idx + 1);
353*4c3eb207Smrg if (show_depths)
354*4c3eb207Smrg pp_printf (pp, " (depth %i)", range->m_stack_depth);
355*4c3eb207Smrg pp_newline (pp);
356*4c3eb207Smrg
357*4c3eb207Smrg /* Print a run of events. */
358*4c3eb207Smrg {
359*4c3eb207Smrg write_indent (pp, cur_indent + per_frame_indent);
360*4c3eb207Smrg pp_string (pp, start_line_color);
361*4c3eb207Smrg pp_string (pp, "|");
362*4c3eb207Smrg pp_string (pp, end_line_color);
363*4c3eb207Smrg pp_newline (pp);
364*4c3eb207Smrg
365*4c3eb207Smrg char *saved_prefix = pp_take_prefix (pp);
366*4c3eb207Smrg char *prefix;
367*4c3eb207Smrg {
368*4c3eb207Smrg pretty_printer tmp_pp;
369*4c3eb207Smrg write_indent (&tmp_pp, cur_indent + per_frame_indent);
370*4c3eb207Smrg pp_string (&tmp_pp, start_line_color);
371*4c3eb207Smrg pp_string (&tmp_pp, "|");
372*4c3eb207Smrg pp_string (&tmp_pp, end_line_color);
373*4c3eb207Smrg prefix = xstrdup (pp_formatted_text (&tmp_pp));
374*4c3eb207Smrg }
375*4c3eb207Smrg pp_set_prefix (pp, prefix);
376*4c3eb207Smrg pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
377*4c3eb207Smrg range->print (dc);
378*4c3eb207Smrg pp_set_prefix (pp, saved_prefix);
379*4c3eb207Smrg
380*4c3eb207Smrg write_indent (pp, cur_indent + per_frame_indent);
381*4c3eb207Smrg pp_string (pp, start_line_color);
382*4c3eb207Smrg pp_string (pp, "|");
383*4c3eb207Smrg pp_string (pp, end_line_color);
384*4c3eb207Smrg pp_newline (pp);
385*4c3eb207Smrg }
386*4c3eb207Smrg
387*4c3eb207Smrg if (i < m_ranges.length () - 1)
388*4c3eb207Smrg {
389*4c3eb207Smrg const path_summary::event_range *next_range
390*4c3eb207Smrg = m_ranges[i + 1];
391*4c3eb207Smrg
392*4c3eb207Smrg if (range->m_stack_depth > next_range->m_stack_depth)
393*4c3eb207Smrg {
394*4c3eb207Smrg if (vbar_column_for_depth.get (next_range->m_stack_depth))
395*4c3eb207Smrg {
396*4c3eb207Smrg /* Show returning from stack frame(s), by printing
397*4c3eb207Smrg something like:
398*4c3eb207Smrg " |\n"
399*4c3eb207Smrg " <------------ +\n"
400*4c3eb207Smrg " |\n". */
401*4c3eb207Smrg int vbar_for_next_frame
402*4c3eb207Smrg = *vbar_column_for_depth.get (next_range->m_stack_depth);
403*4c3eb207Smrg
404*4c3eb207Smrg int indent_for_next_frame
405*4c3eb207Smrg = vbar_for_next_frame - per_frame_indent;
406*4c3eb207Smrg write_indent (pp, vbar_for_next_frame);
407*4c3eb207Smrg pp_string (pp, start_line_color);
408*4c3eb207Smrg pp_character (pp, '<');
409*4c3eb207Smrg for (int i = indent_for_next_frame + per_frame_indent;
410*4c3eb207Smrg i < cur_indent + per_frame_indent - 1; i++)
411*4c3eb207Smrg pp_character (pp, '-');
412*4c3eb207Smrg pp_character (pp, '+');
413*4c3eb207Smrg pp_string (pp, end_line_color);
414*4c3eb207Smrg pp_newline (pp);
415*4c3eb207Smrg cur_indent = indent_for_next_frame;
416*4c3eb207Smrg
417*4c3eb207Smrg write_indent (pp, vbar_for_next_frame);
418*4c3eb207Smrg pp_string (pp, start_line_color);
419*4c3eb207Smrg pp_printf (pp, "|");
420*4c3eb207Smrg pp_string (pp, end_line_color);
421*4c3eb207Smrg pp_newline (pp);
422*4c3eb207Smrg }
423*4c3eb207Smrg else
424*4c3eb207Smrg {
425*4c3eb207Smrg /* Handle disjoint paths (e.g. a callback at some later
426*4c3eb207Smrg time). */
427*4c3eb207Smrg cur_indent = base_indent;
428*4c3eb207Smrg }
429*4c3eb207Smrg }
430*4c3eb207Smrg else if (range->m_stack_depth < next_range->m_stack_depth)
431*4c3eb207Smrg {
432*4c3eb207Smrg /* Prepare to show pushed stack frame. */
433*4c3eb207Smrg gcc_assert (range->m_stack_depth != EMPTY);
434*4c3eb207Smrg gcc_assert (range->m_stack_depth != DELETED);
435*4c3eb207Smrg vbar_column_for_depth.put (range->m_stack_depth,
436*4c3eb207Smrg cur_indent + per_frame_indent);
437*4c3eb207Smrg cur_indent += per_frame_indent;
438*4c3eb207Smrg }
439*4c3eb207Smrg
440*4c3eb207Smrg }
441*4c3eb207Smrg }
442*4c3eb207Smrg }
443*4c3eb207Smrg
444*4c3eb207Smrg } /* end of anonymous namespace for path-printing code. */
445*4c3eb207Smrg
446*4c3eb207Smrg /* Print PATH to CONTEXT, according to CONTEXT's path_format. */
447*4c3eb207Smrg
448*4c3eb207Smrg void
default_tree_diagnostic_path_printer(diagnostic_context * context,const diagnostic_path * path)449*4c3eb207Smrg default_tree_diagnostic_path_printer (diagnostic_context *context,
450*4c3eb207Smrg const diagnostic_path *path)
451*4c3eb207Smrg {
452*4c3eb207Smrg gcc_assert (path);
453*4c3eb207Smrg
454*4c3eb207Smrg const unsigned num_events = path->num_events ();
455*4c3eb207Smrg
456*4c3eb207Smrg switch (context->path_format)
457*4c3eb207Smrg {
458*4c3eb207Smrg case DPF_NONE:
459*4c3eb207Smrg /* Do nothing. */
460*4c3eb207Smrg return;
461*4c3eb207Smrg
462*4c3eb207Smrg case DPF_SEPARATE_EVENTS:
463*4c3eb207Smrg {
464*4c3eb207Smrg /* A note per event. */
465*4c3eb207Smrg for (unsigned i = 0; i < num_events; i++)
466*4c3eb207Smrg {
467*4c3eb207Smrg const diagnostic_event &event = path->get_event (i);
468*4c3eb207Smrg label_text event_text (event.get_desc (false));
469*4c3eb207Smrg gcc_assert (event_text.m_buffer);
470*4c3eb207Smrg diagnostic_event_id_t event_id (i);
471*4c3eb207Smrg inform (event.get_location (),
472*4c3eb207Smrg "%@ %s", &event_id, event_text.m_buffer);
473*4c3eb207Smrg event_text.maybe_free ();
474*4c3eb207Smrg }
475*4c3eb207Smrg }
476*4c3eb207Smrg break;
477*4c3eb207Smrg
478*4c3eb207Smrg case DPF_INLINE_EVENTS:
479*4c3eb207Smrg {
480*4c3eb207Smrg /* Consolidate related events. */
481*4c3eb207Smrg path_summary summary (*path, true);
482*4c3eb207Smrg char *saved_prefix = pp_take_prefix (context->printer);
483*4c3eb207Smrg pp_set_prefix (context->printer, NULL);
484*4c3eb207Smrg summary.print (context, context->show_path_depths);
485*4c3eb207Smrg pp_flush (context->printer);
486*4c3eb207Smrg pp_set_prefix (context->printer, saved_prefix);
487*4c3eb207Smrg }
488*4c3eb207Smrg }
489*4c3eb207Smrg }
490*4c3eb207Smrg
491*4c3eb207Smrg /* This has to be here, rather than diagnostic-format-json.cc,
492*4c3eb207Smrg since diagnostic-format-json.o is within OBJS-libcommon and thus
493*4c3eb207Smrg doesn't have access to trees (for m_fndecl). */
494*4c3eb207Smrg
495*4c3eb207Smrg json::value *
default_tree_make_json_for_path(diagnostic_context *,const diagnostic_path * path)496*4c3eb207Smrg default_tree_make_json_for_path (diagnostic_context *,
497*4c3eb207Smrg const diagnostic_path *path)
498*4c3eb207Smrg {
499*4c3eb207Smrg json::array *path_array = new json::array ();
500*4c3eb207Smrg for (unsigned i = 0; i < path->num_events (); i++)
501*4c3eb207Smrg {
502*4c3eb207Smrg const diagnostic_event &event = path->get_event (i);
503*4c3eb207Smrg
504*4c3eb207Smrg json::object *event_obj = new json::object ();
505*4c3eb207Smrg if (event.get_location ())
506*4c3eb207Smrg event_obj->set ("location",
507*4c3eb207Smrg json_from_expanded_location (event.get_location ()));
508*4c3eb207Smrg label_text event_text (event.get_desc (false));
509*4c3eb207Smrg event_obj->set ("description", new json::string (event_text.m_buffer));
510*4c3eb207Smrg event_text.maybe_free ();
511*4c3eb207Smrg if (tree fndecl = event.get_fndecl ())
512*4c3eb207Smrg {
513*4c3eb207Smrg const char *function
514*4c3eb207Smrg = identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2));
515*4c3eb207Smrg event_obj->set ("function", new json::string (function));
516*4c3eb207Smrg }
517*4c3eb207Smrg event_obj->set ("depth",
518*4c3eb207Smrg new json::integer_number (event.get_stack_depth ()));
519*4c3eb207Smrg path_array->append (event_obj);
520*4c3eb207Smrg }
521*4c3eb207Smrg return path_array;
522*4c3eb207Smrg }
523*4c3eb207Smrg
524*4c3eb207Smrg #if CHECKING_P
525*4c3eb207Smrg
526*4c3eb207Smrg namespace selftest {
527*4c3eb207Smrg
528*4c3eb207Smrg /* A subclass of simple_diagnostic_path that adds member functions
529*4c3eb207Smrg for adding test events. */
530*4c3eb207Smrg
531*4c3eb207Smrg class test_diagnostic_path : public simple_diagnostic_path
532*4c3eb207Smrg {
533*4c3eb207Smrg public:
test_diagnostic_path(pretty_printer * event_pp)534*4c3eb207Smrg test_diagnostic_path (pretty_printer *event_pp)
535*4c3eb207Smrg : simple_diagnostic_path (event_pp)
536*4c3eb207Smrg {
537*4c3eb207Smrg }
538*4c3eb207Smrg
add_entry(tree fndecl,int stack_depth)539*4c3eb207Smrg void add_entry (tree fndecl, int stack_depth)
540*4c3eb207Smrg {
541*4c3eb207Smrg add_event (UNKNOWN_LOCATION, fndecl, stack_depth,
542*4c3eb207Smrg "entering %qE", fndecl);
543*4c3eb207Smrg }
544*4c3eb207Smrg
add_return(tree fndecl,int stack_depth)545*4c3eb207Smrg void add_return (tree fndecl, int stack_depth)
546*4c3eb207Smrg {
547*4c3eb207Smrg add_event (UNKNOWN_LOCATION, fndecl, stack_depth,
548*4c3eb207Smrg "returning to %qE", fndecl);
549*4c3eb207Smrg }
550*4c3eb207Smrg
add_call(tree caller,int caller_stack_depth,tree callee)551*4c3eb207Smrg void add_call (tree caller, int caller_stack_depth, tree callee)
552*4c3eb207Smrg {
553*4c3eb207Smrg add_event (UNKNOWN_LOCATION, caller, caller_stack_depth,
554*4c3eb207Smrg "calling %qE", callee);
555*4c3eb207Smrg add_entry (callee, caller_stack_depth + 1);
556*4c3eb207Smrg }
557*4c3eb207Smrg };
558*4c3eb207Smrg
559*4c3eb207Smrg /* Verify that empty paths are handled gracefully. */
560*4c3eb207Smrg
561*4c3eb207Smrg static void
test_empty_path(pretty_printer * event_pp)562*4c3eb207Smrg test_empty_path (pretty_printer *event_pp)
563*4c3eb207Smrg {
564*4c3eb207Smrg test_diagnostic_path path (event_pp);
565*4c3eb207Smrg ASSERT_FALSE (path.interprocedural_p ());
566*4c3eb207Smrg
567*4c3eb207Smrg path_summary summary (path, false);
568*4c3eb207Smrg ASSERT_EQ (summary.get_num_ranges (), 0);
569*4c3eb207Smrg
570*4c3eb207Smrg test_diagnostic_context dc;
571*4c3eb207Smrg summary.print (&dc, true);
572*4c3eb207Smrg ASSERT_STREQ ("",
573*4c3eb207Smrg pp_formatted_text (dc.printer));
574*4c3eb207Smrg }
575*4c3eb207Smrg
576*4c3eb207Smrg /* Verify that print_path_summary works on a purely intraprocedural path. */
577*4c3eb207Smrg
578*4c3eb207Smrg static void
test_intraprocedural_path(pretty_printer * event_pp)579*4c3eb207Smrg test_intraprocedural_path (pretty_printer *event_pp)
580*4c3eb207Smrg {
581*4c3eb207Smrg tree fntype_void_void
582*4c3eb207Smrg = build_function_type_array (void_type_node, 0, NULL);
583*4c3eb207Smrg tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
584*4c3eb207Smrg
585*4c3eb207Smrg test_diagnostic_path path (event_pp);
586*4c3eb207Smrg path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "first %qs", "free");
587*4c3eb207Smrg path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "double %qs", "free");
588*4c3eb207Smrg
589*4c3eb207Smrg ASSERT_FALSE (path.interprocedural_p ());
590*4c3eb207Smrg
591*4c3eb207Smrg path_summary summary (path, false);
592*4c3eb207Smrg ASSERT_EQ (summary.get_num_ranges (), 1);
593*4c3eb207Smrg
594*4c3eb207Smrg test_diagnostic_context dc;
595*4c3eb207Smrg summary.print (&dc, true);
596*4c3eb207Smrg ASSERT_STREQ (" `foo': events 1-2 (depth 0)\n"
597*4c3eb207Smrg " |\n"
598*4c3eb207Smrg " | (1): first `free'\n"
599*4c3eb207Smrg " | (2): double `free'\n"
600*4c3eb207Smrg " |\n",
601*4c3eb207Smrg pp_formatted_text (dc.printer));
602*4c3eb207Smrg }
603*4c3eb207Smrg
604*4c3eb207Smrg /* Verify that print_path_summary works on an interprocedural path. */
605*4c3eb207Smrg
606*4c3eb207Smrg static void
test_interprocedural_path_1(pretty_printer * event_pp)607*4c3eb207Smrg test_interprocedural_path_1 (pretty_printer *event_pp)
608*4c3eb207Smrg {
609*4c3eb207Smrg /* Build fndecls. The types aren't quite right, but that
610*4c3eb207Smrg doesn't matter for the purposes of this test. */
611*4c3eb207Smrg tree fntype_void_void
612*4c3eb207Smrg = build_function_type_array (void_type_node, 0, NULL);
613*4c3eb207Smrg tree fndecl_test = build_fn_decl ("test", fntype_void_void);
614*4c3eb207Smrg tree fndecl_make_boxed_int
615*4c3eb207Smrg = build_fn_decl ("make_boxed_int", fntype_void_void);
616*4c3eb207Smrg tree fndecl_wrapped_malloc
617*4c3eb207Smrg = build_fn_decl ("wrapped_malloc", fntype_void_void);
618*4c3eb207Smrg tree fndecl_free_boxed_int
619*4c3eb207Smrg = build_fn_decl ("free_boxed_int", fntype_void_void);
620*4c3eb207Smrg tree fndecl_wrapped_free
621*4c3eb207Smrg = build_fn_decl ("wrapped_free", fntype_void_void);
622*4c3eb207Smrg
623*4c3eb207Smrg test_diagnostic_path path (event_pp);
624*4c3eb207Smrg path.add_entry (fndecl_test, 0);
625*4c3eb207Smrg path.add_call (fndecl_test, 0, fndecl_make_boxed_int);
626*4c3eb207Smrg path.add_call (fndecl_make_boxed_int, 1, fndecl_wrapped_malloc);
627*4c3eb207Smrg path.add_event (UNKNOWN_LOCATION, fndecl_wrapped_malloc, 2, "calling malloc");
628*4c3eb207Smrg path.add_return (fndecl_test, 0);
629*4c3eb207Smrg path.add_call (fndecl_test, 0, fndecl_free_boxed_int);
630*4c3eb207Smrg path.add_call (fndecl_free_boxed_int, 1, fndecl_wrapped_free);
631*4c3eb207Smrg path.add_event (UNKNOWN_LOCATION, fndecl_wrapped_free, 2, "calling free");
632*4c3eb207Smrg path.add_return (fndecl_test, 0);
633*4c3eb207Smrg path.add_call (fndecl_test, 0, fndecl_free_boxed_int);
634*4c3eb207Smrg path.add_call (fndecl_free_boxed_int, 1, fndecl_wrapped_free);
635*4c3eb207Smrg path.add_event (UNKNOWN_LOCATION, fndecl_wrapped_free, 2, "calling free");
636*4c3eb207Smrg ASSERT_EQ (path.num_events (), 18);
637*4c3eb207Smrg
638*4c3eb207Smrg ASSERT_TRUE (path.interprocedural_p ());
639*4c3eb207Smrg
640*4c3eb207Smrg path_summary summary (path, false);
641*4c3eb207Smrg ASSERT_EQ (summary.get_num_ranges (), 9);
642*4c3eb207Smrg
643*4c3eb207Smrg test_diagnostic_context dc;
644*4c3eb207Smrg summary.print (&dc, true);
645*4c3eb207Smrg ASSERT_STREQ
646*4c3eb207Smrg (" `test': events 1-2 (depth 0)\n"
647*4c3eb207Smrg " |\n"
648*4c3eb207Smrg " | (1): entering `test'\n"
649*4c3eb207Smrg " | (2): calling `make_boxed_int'\n"
650*4c3eb207Smrg " |\n"
651*4c3eb207Smrg " +--> `make_boxed_int': events 3-4 (depth 1)\n"
652*4c3eb207Smrg " |\n"
653*4c3eb207Smrg " | (3): entering `make_boxed_int'\n"
654*4c3eb207Smrg " | (4): calling `wrapped_malloc'\n"
655*4c3eb207Smrg " |\n"
656*4c3eb207Smrg " +--> `wrapped_malloc': events 5-6 (depth 2)\n"
657*4c3eb207Smrg " |\n"
658*4c3eb207Smrg " | (5): entering `wrapped_malloc'\n"
659*4c3eb207Smrg " | (6): calling malloc\n"
660*4c3eb207Smrg " |\n"
661*4c3eb207Smrg " <-------------+\n"
662*4c3eb207Smrg " |\n"
663*4c3eb207Smrg " `test': events 7-8 (depth 0)\n"
664*4c3eb207Smrg " |\n"
665*4c3eb207Smrg " | (7): returning to `test'\n"
666*4c3eb207Smrg " | (8): calling `free_boxed_int'\n"
667*4c3eb207Smrg " |\n"
668*4c3eb207Smrg " +--> `free_boxed_int': events 9-10 (depth 1)\n"
669*4c3eb207Smrg " |\n"
670*4c3eb207Smrg " | (9): entering `free_boxed_int'\n"
671*4c3eb207Smrg " | (10): calling `wrapped_free'\n"
672*4c3eb207Smrg " |\n"
673*4c3eb207Smrg " +--> `wrapped_free': events 11-12 (depth 2)\n"
674*4c3eb207Smrg " |\n"
675*4c3eb207Smrg " | (11): entering `wrapped_free'\n"
676*4c3eb207Smrg " | (12): calling free\n"
677*4c3eb207Smrg " |\n"
678*4c3eb207Smrg " <-------------+\n"
679*4c3eb207Smrg " |\n"
680*4c3eb207Smrg " `test': events 13-14 (depth 0)\n"
681*4c3eb207Smrg " |\n"
682*4c3eb207Smrg " | (13): returning to `test'\n"
683*4c3eb207Smrg " | (14): calling `free_boxed_int'\n"
684*4c3eb207Smrg " |\n"
685*4c3eb207Smrg " +--> `free_boxed_int': events 15-16 (depth 1)\n"
686*4c3eb207Smrg " |\n"
687*4c3eb207Smrg " | (15): entering `free_boxed_int'\n"
688*4c3eb207Smrg " | (16): calling `wrapped_free'\n"
689*4c3eb207Smrg " |\n"
690*4c3eb207Smrg " +--> `wrapped_free': events 17-18 (depth 2)\n"
691*4c3eb207Smrg " |\n"
692*4c3eb207Smrg " | (17): entering `wrapped_free'\n"
693*4c3eb207Smrg " | (18): calling free\n"
694*4c3eb207Smrg " |\n",
695*4c3eb207Smrg pp_formatted_text (dc.printer));
696*4c3eb207Smrg }
697*4c3eb207Smrg
698*4c3eb207Smrg /* Example where we pop the stack to an intermediate frame, rather than the
699*4c3eb207Smrg initial one. */
700*4c3eb207Smrg
701*4c3eb207Smrg static void
test_interprocedural_path_2(pretty_printer * event_pp)702*4c3eb207Smrg test_interprocedural_path_2 (pretty_printer *event_pp)
703*4c3eb207Smrg {
704*4c3eb207Smrg /* Build fndecls. The types aren't quite right, but that
705*4c3eb207Smrg doesn't matter for the purposes of this test. */
706*4c3eb207Smrg tree fntype_void_void
707*4c3eb207Smrg = build_function_type_array (void_type_node, 0, NULL);
708*4c3eb207Smrg tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
709*4c3eb207Smrg tree fndecl_bar = build_fn_decl ("bar", fntype_void_void);
710*4c3eb207Smrg tree fndecl_baz = build_fn_decl ("baz", fntype_void_void);
711*4c3eb207Smrg
712*4c3eb207Smrg test_diagnostic_path path (event_pp);
713*4c3eb207Smrg path.add_entry (fndecl_foo, 0);
714*4c3eb207Smrg path.add_call (fndecl_foo, 0, fndecl_bar);
715*4c3eb207Smrg path.add_call (fndecl_bar, 1, fndecl_baz);
716*4c3eb207Smrg path.add_return (fndecl_bar, 1);
717*4c3eb207Smrg path.add_call (fndecl_bar, 1, fndecl_baz);
718*4c3eb207Smrg ASSERT_EQ (path.num_events (), 8);
719*4c3eb207Smrg
720*4c3eb207Smrg ASSERT_TRUE (path.interprocedural_p ());
721*4c3eb207Smrg
722*4c3eb207Smrg path_summary summary (path, false);
723*4c3eb207Smrg ASSERT_EQ (summary.get_num_ranges (), 5);
724*4c3eb207Smrg
725*4c3eb207Smrg test_diagnostic_context dc;
726*4c3eb207Smrg summary.print (&dc, true);
727*4c3eb207Smrg ASSERT_STREQ
728*4c3eb207Smrg (" `foo': events 1-2 (depth 0)\n"
729*4c3eb207Smrg " |\n"
730*4c3eb207Smrg " | (1): entering `foo'\n"
731*4c3eb207Smrg " | (2): calling `bar'\n"
732*4c3eb207Smrg " |\n"
733*4c3eb207Smrg " +--> `bar': events 3-4 (depth 1)\n"
734*4c3eb207Smrg " |\n"
735*4c3eb207Smrg " | (3): entering `bar'\n"
736*4c3eb207Smrg " | (4): calling `baz'\n"
737*4c3eb207Smrg " |\n"
738*4c3eb207Smrg " +--> `baz': event 5 (depth 2)\n"
739*4c3eb207Smrg " |\n"
740*4c3eb207Smrg " | (5): entering `baz'\n"
741*4c3eb207Smrg " |\n"
742*4c3eb207Smrg " <------+\n"
743*4c3eb207Smrg " |\n"
744*4c3eb207Smrg " `bar': events 6-7 (depth 1)\n"
745*4c3eb207Smrg " |\n"
746*4c3eb207Smrg " | (6): returning to `bar'\n"
747*4c3eb207Smrg " | (7): calling `baz'\n"
748*4c3eb207Smrg " |\n"
749*4c3eb207Smrg " +--> `baz': event 8 (depth 2)\n"
750*4c3eb207Smrg " |\n"
751*4c3eb207Smrg " | (8): entering `baz'\n"
752*4c3eb207Smrg " |\n",
753*4c3eb207Smrg pp_formatted_text (dc.printer));
754*4c3eb207Smrg }
755*4c3eb207Smrg
756*4c3eb207Smrg /* Verify that print_path_summary is sane in the face of a recursive
757*4c3eb207Smrg diagnostic_path. */
758*4c3eb207Smrg
759*4c3eb207Smrg static void
test_recursion(pretty_printer * event_pp)760*4c3eb207Smrg test_recursion (pretty_printer *event_pp)
761*4c3eb207Smrg {
762*4c3eb207Smrg tree fntype_void_void
763*4c3eb207Smrg = build_function_type_array (void_type_node, 0, NULL);
764*4c3eb207Smrg tree fndecl_factorial = build_fn_decl ("factorial", fntype_void_void);
765*4c3eb207Smrg
766*4c3eb207Smrg test_diagnostic_path path (event_pp);
767*4c3eb207Smrg path.add_entry (fndecl_factorial, 0);
768*4c3eb207Smrg for (int depth = 0; depth < 3; depth++)
769*4c3eb207Smrg path.add_call (fndecl_factorial, depth, fndecl_factorial);
770*4c3eb207Smrg ASSERT_EQ (path.num_events (), 7);
771*4c3eb207Smrg
772*4c3eb207Smrg ASSERT_TRUE (path.interprocedural_p ());
773*4c3eb207Smrg
774*4c3eb207Smrg path_summary summary (path, false);
775*4c3eb207Smrg ASSERT_EQ (summary.get_num_ranges (), 4);
776*4c3eb207Smrg
777*4c3eb207Smrg test_diagnostic_context dc;
778*4c3eb207Smrg summary.print (&dc, true);
779*4c3eb207Smrg ASSERT_STREQ
780*4c3eb207Smrg (" `factorial': events 1-2 (depth 0)\n"
781*4c3eb207Smrg " |\n"
782*4c3eb207Smrg " | (1): entering `factorial'\n"
783*4c3eb207Smrg " | (2): calling `factorial'\n"
784*4c3eb207Smrg " |\n"
785*4c3eb207Smrg " +--> `factorial': events 3-4 (depth 1)\n"
786*4c3eb207Smrg " |\n"
787*4c3eb207Smrg " | (3): entering `factorial'\n"
788*4c3eb207Smrg " | (4): calling `factorial'\n"
789*4c3eb207Smrg " |\n"
790*4c3eb207Smrg " +--> `factorial': events 5-6 (depth 2)\n"
791*4c3eb207Smrg " |\n"
792*4c3eb207Smrg " | (5): entering `factorial'\n"
793*4c3eb207Smrg " | (6): calling `factorial'\n"
794*4c3eb207Smrg " |\n"
795*4c3eb207Smrg " +--> `factorial': event 7 (depth 3)\n"
796*4c3eb207Smrg " |\n"
797*4c3eb207Smrg " | (7): entering `factorial'\n"
798*4c3eb207Smrg " |\n",
799*4c3eb207Smrg pp_formatted_text (dc.printer));
800*4c3eb207Smrg }
801*4c3eb207Smrg
802*4c3eb207Smrg /* Run all of the selftests within this file. */
803*4c3eb207Smrg
804*4c3eb207Smrg void
tree_diagnostic_path_cc_tests()805*4c3eb207Smrg tree_diagnostic_path_cc_tests ()
806*4c3eb207Smrg {
807*4c3eb207Smrg auto_fix_quotes fix_quotes;
808*4c3eb207Smrg pretty_printer *event_pp = global_dc->printer->clone ();
809*4c3eb207Smrg pp_show_color (event_pp) = 0;
810*4c3eb207Smrg test_empty_path (event_pp);
811*4c3eb207Smrg test_intraprocedural_path (event_pp);
812*4c3eb207Smrg test_interprocedural_path_1 (event_pp);
813*4c3eb207Smrg test_interprocedural_path_2 (event_pp);
814*4c3eb207Smrg test_recursion (event_pp);
815*4c3eb207Smrg delete event_pp;
816*4c3eb207Smrg }
817*4c3eb207Smrg
818*4c3eb207Smrg } // namespace selftest
819*4c3eb207Smrg
820*4c3eb207Smrg #endif /* #if CHECKING_P */
821