1 /* Paths through the code associated with a diagnostic.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "diagnostic.h"
26 #include "tree-pretty-print.h"
27 #include "gimple-pretty-print.h"
28 #include "tree-diagnostic.h"
29 #include "langhooks.h"
31 #include "diagnostic-path.h"
33 #include "gcc-rich-location.h"
34 #include "diagnostic-color.h"
35 #include "diagnostic-event-id.h"
37 #include "selftest-diagnostic.h"
39 /* Anonymous namespace for path-printing code. */
43 /* Subclass of range_label for showing a particular event
44 when showing a consecutive run of events within a diagnostic_path as
45 labelled ranges within one gcc_rich_location. */
47 class path_label
: public range_label
50 path_label (const diagnostic_path
*path
, unsigned start_idx
)
51 : m_path (path
), m_start_idx (start_idx
)
54 label_text
get_text (unsigned range_idx
) const FINAL OVERRIDE
56 unsigned event_idx
= m_start_idx
+ range_idx
;
57 const diagnostic_event
&event
= m_path
->get_event (event_idx
);
59 /* Get the description of the event, perhaps with colorization:
60 normally, we don't colorize within a range_label, but this
61 is special-cased for diagnostic paths. */
62 bool colorize
= pp_show_color (global_dc
->printer
);
63 label_text
event_text (event
.get_desc (colorize
));
64 gcc_assert (event_text
.m_buffer
);
66 pp_show_color (&pp
) = pp_show_color (global_dc
->printer
);
67 diagnostic_event_id_t
event_id (event_idx
);
68 pp_printf (&pp
, "%@ %s", &event_id
, event_text
.m_buffer
);
69 event_text
.maybe_free ();
70 label_text result
= label_text::take (xstrdup (pp_formatted_text (&pp
)));
75 const diagnostic_path
*m_path
;
79 /* Return true if E1 and E2 can be consolidated into the same run of events
80 when printing a diagnostic_path. */
83 can_consolidate_events (const diagnostic_event
&e1
,
84 const diagnostic_event
&e2
,
87 if (e1
.get_fndecl () != e2
.get_fndecl ())
90 if (e1
.get_stack_depth () != e2
.get_stack_depth ())
95 location_t loc1
= e1
.get_location ();
96 location_t loc2
= e2
.get_location ();
98 if (loc1
< RESERVED_LOCATION_COUNT
99 || loc2
< RESERVED_LOCATION_COUNT
)
102 /* Neither can be macro-based. */
103 if (linemap_location_from_macro_expansion_p (line_table
, loc1
))
105 if (linemap_location_from_macro_expansion_p (line_table
, loc2
))
109 /* Passed all the tests. */
113 /* A class for grouing together the events in a diagnostic_path into
114 ranges of events, partitioned by stack frame (i.e. by fndecl and
119 /* A range of consecutive events within a diagnostic_path,
120 all with the same fndecl and stack_depth, and which are suitable
121 to print with a single call to diagnostic_show_locus. */
124 event_range (const diagnostic_path
*path
, unsigned start_idx
,
125 const diagnostic_event
&initial_event
)
127 m_initial_event (initial_event
),
128 m_fndecl (initial_event
.get_fndecl ()),
129 m_stack_depth (initial_event
.get_stack_depth ()),
130 m_start_idx (start_idx
), m_end_idx (start_idx
),
131 m_path_label (path
, start_idx
),
132 m_richloc (initial_event
.get_location (), &m_path_label
)
135 bool maybe_add_event (const diagnostic_event
&new_ev
, unsigned idx
,
136 bool check_rich_locations
)
138 if (!can_consolidate_events (m_initial_event
, new_ev
,
139 check_rich_locations
))
141 if (check_rich_locations
)
142 if (!m_richloc
.add_location_if_nearby (new_ev
.get_location (),
143 false, &m_path_label
))
149 /* Print the events in this range to DC, typically as a single
150 call to the printer's diagnostic_show_locus. */
152 void print (diagnostic_context
*dc
)
154 location_t initial_loc
= m_initial_event
.get_location ();
156 /* Emit a span indicating the filename (and line/column) if the
157 line has changed relative to the last call to
158 diagnostic_show_locus. */
161 expanded_location exploc
162 = linemap_client_expand_location_to_spelling_point
163 (initial_loc
, LOCATION_ASPECT_CARET
);
164 if (exploc
.file
!= LOCATION_FILE (dc
->last_location
))
165 dc
->start_span (dc
, exploc
);
168 /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
169 primary location for an event, diagnostic_show_locus won't print
172 In particular the label for the event won't get printed.
173 Fail more gracefully in this case by showing the event
174 index and text, at no particular location. */
175 if (get_pure_location (initial_loc
) <= BUILTINS_LOCATION
)
177 for (unsigned i
= m_start_idx
; i
<= m_end_idx
; i
++)
179 const diagnostic_event
&iter_event
= m_path
->get_event (i
);
180 diagnostic_event_id_t
event_id (i
);
181 label_text
event_text (iter_event
.get_desc (true));
182 pretty_printer
*pp
= dc
->printer
;
183 pp_printf (pp
, " %@: %s", &event_id
, event_text
.m_buffer
);
185 event_text
.maybe_free ();
190 /* Call diagnostic_show_locus to show the events using labels. */
191 diagnostic_show_locus (dc
, &m_richloc
, DK_DIAGNOSTIC_PATH
);
193 /* If we have a macro expansion, show the expansion to the user. */
194 if (linemap_location_from_macro_expansion_p (line_table
, initial_loc
))
196 gcc_assert (m_start_idx
== m_end_idx
);
197 maybe_unwind_expanded_macro_loc (dc
, initial_loc
);
201 const diagnostic_path
*m_path
;
202 const diagnostic_event
&m_initial_event
;
205 unsigned m_start_idx
;
207 path_label m_path_label
;
208 gcc_rich_location m_richloc
;
212 path_summary (const diagnostic_path
&path
, bool check_rich_locations
);
214 void print (diagnostic_context
*dc
, bool show_depths
) const;
216 unsigned get_num_ranges () const { return m_ranges
.length (); }
219 auto_delete_vec
<event_range
> m_ranges
;
222 /* path_summary's ctor. */
224 path_summary::path_summary (const diagnostic_path
&path
,
225 bool check_rich_locations
)
227 const unsigned num_events
= path
.num_events ();
229 event_range
*cur_event_range
= NULL
;
230 for (unsigned idx
= 0; idx
< num_events
; idx
++)
232 const diagnostic_event
&event
= path
.get_event (idx
);
234 if (cur_event_range
->maybe_add_event (event
, idx
, check_rich_locations
))
237 cur_event_range
= new event_range (&path
, idx
, event
);
238 m_ranges
.safe_push (cur_event_range
);
242 /* Write SPACES to PP. */
245 write_indent (pretty_printer
*pp
, int spaces
)
247 for (int i
= 0; i
< spaces
; i
++)
251 /* Print FNDDECL to PP, quoting it if QUOTED is true.
253 We can't use "%qE" here since we can't guarantee the capabilities
257 print_fndecl (pretty_printer
*pp
, tree fndecl
, bool quoted
)
259 const char *n
= DECL_NAME (fndecl
)
260 ? identifier_to_locale (lang_hooks
.decl_printable_name (fndecl
, 2))
263 pp_printf (pp
, "%qs", n
);
268 /* Print this path_summary to DC, giving an overview of the interprocedural
271 Print the event descriptions in a nested form, printing the event
272 descriptions within calls to diagnostic_show_locus, using labels to
278 +--> 'bar' (events 3-4)
281 +--> 'baz' (events 5-6)
289 +--> 'bar' (events 9-10)
292 +--> 'baz' (events 11-12)
296 If SHOW_DEPTHS is true, append " (depth N)" to the header of each run
299 For events with UNKNOWN_LOCATION, print a summary of each the event. */
302 path_summary::print (diagnostic_context
*dc
, bool show_depths
) const
304 pretty_printer
*pp
= dc
->printer
;
306 const int per_frame_indent
= 2;
308 const char *const line_color
= "path";
309 const char *start_line_color
310 = colorize_start (pp_show_color (pp
), line_color
);
311 const char *end_line_color
= colorize_stop (pp_show_color (pp
));
313 /* Keep track of column numbers of existing '|' characters for
314 stack depths we've already printed. */
315 const int EMPTY
= -1;
316 const int DELETED
= -2;
317 typedef int_hash
<int, EMPTY
, DELETED
> vbar_hash
;
318 hash_map
<vbar_hash
, int> vbar_column_for_depth
;
320 /* Print the ranges. */
321 const int base_indent
= 2;
322 int cur_indent
= base_indent
;
325 FOR_EACH_VEC_ELT (m_ranges
, i
, range
)
327 write_indent (pp
, cur_indent
);
330 const path_summary::event_range
*prev_range
332 if (range
->m_stack_depth
> prev_range
->m_stack_depth
)
334 /* Show pushed stack frame(s). */
335 const char *push_prefix
= "+--> ";
336 pp_string (pp
, start_line_color
);
337 pp_string (pp
, push_prefix
);
338 pp_string (pp
, end_line_color
);
339 cur_indent
+= strlen (push_prefix
);
344 print_fndecl (pp
, range
->m_fndecl
, true);
345 pp_string (pp
, ": ");
347 if (range
->m_start_idx
== range
->m_end_idx
)
348 pp_printf (pp
, "event %i",
349 range
->m_start_idx
+ 1);
351 pp_printf (pp
, "events %i-%i",
352 range
->m_start_idx
+ 1, range
->m_end_idx
+ 1);
354 pp_printf (pp
, " (depth %i)", range
->m_stack_depth
);
357 /* Print a run of events. */
359 write_indent (pp
, cur_indent
+ per_frame_indent
);
360 pp_string (pp
, start_line_color
);
362 pp_string (pp
, end_line_color
);
365 char *saved_prefix
= pp_take_prefix (pp
);
368 pretty_printer tmp_pp
;
369 write_indent (&tmp_pp
, cur_indent
+ per_frame_indent
);
370 pp_string (&tmp_pp
, start_line_color
);
371 pp_string (&tmp_pp
, "|");
372 pp_string (&tmp_pp
, end_line_color
);
373 prefix
= xstrdup (pp_formatted_text (&tmp_pp
));
375 pp_set_prefix (pp
, prefix
);
376 pp_prefixing_rule (pp
) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE
;
378 pp_set_prefix (pp
, saved_prefix
);
380 write_indent (pp
, cur_indent
+ per_frame_indent
);
381 pp_string (pp
, start_line_color
);
383 pp_string (pp
, end_line_color
);
387 if (i
< m_ranges
.length () - 1)
389 const path_summary::event_range
*next_range
392 if (range
->m_stack_depth
> next_range
->m_stack_depth
)
394 if (vbar_column_for_depth
.get (next_range
->m_stack_depth
))
396 /* Show returning from stack frame(s), by printing
401 int vbar_for_next_frame
402 = *vbar_column_for_depth
.get (next_range
->m_stack_depth
);
404 int indent_for_next_frame
405 = vbar_for_next_frame
- per_frame_indent
;
406 write_indent (pp
, vbar_for_next_frame
);
407 pp_string (pp
, start_line_color
);
408 pp_character (pp
, '<');
409 for (int i
= indent_for_next_frame
+ per_frame_indent
;
410 i
< cur_indent
+ per_frame_indent
- 1; i
++)
411 pp_character (pp
, '-');
412 pp_character (pp
, '+');
413 pp_string (pp
, end_line_color
);
415 cur_indent
= indent_for_next_frame
;
417 write_indent (pp
, vbar_for_next_frame
);
418 pp_string (pp
, start_line_color
);
420 pp_string (pp
, end_line_color
);
425 /* Handle disjoint paths (e.g. a callback at some later
427 cur_indent
= base_indent
;
430 else if (range
->m_stack_depth
< next_range
->m_stack_depth
)
432 /* Prepare to show pushed stack frame. */
433 gcc_assert (range
->m_stack_depth
!= EMPTY
);
434 gcc_assert (range
->m_stack_depth
!= DELETED
);
435 vbar_column_for_depth
.put (range
->m_stack_depth
,
436 cur_indent
+ per_frame_indent
);
437 cur_indent
+= per_frame_indent
;
444 } /* end of anonymous namespace for path-printing code. */
446 /* Print PATH to CONTEXT, according to CONTEXT's path_format. */
449 default_tree_diagnostic_path_printer (diagnostic_context
*context
,
450 const diagnostic_path
*path
)
454 const unsigned num_events
= path
->num_events ();
456 switch (context
->path_format
)
462 case DPF_SEPARATE_EVENTS
:
464 /* A note per event. */
465 for (unsigned i
= 0; i
< num_events
; i
++)
467 const diagnostic_event
&event
= path
->get_event (i
);
468 label_text
event_text (event
.get_desc (false));
469 gcc_assert (event_text
.m_buffer
);
470 diagnostic_event_id_t
event_id (i
);
471 inform (event
.get_location (),
472 "%@ %s", &event_id
, event_text
.m_buffer
);
473 event_text
.maybe_free ();
478 case DPF_INLINE_EVENTS
:
480 /* Consolidate related events. */
481 path_summary
summary (*path
, true);
482 char *saved_prefix
= pp_take_prefix (context
->printer
);
483 pp_set_prefix (context
->printer
, NULL
);
484 summary
.print (context
, context
->show_path_depths
);
485 pp_flush (context
->printer
);
486 pp_set_prefix (context
->printer
, saved_prefix
);
491 /* This has to be here, rather than diagnostic-format-json.cc,
492 since diagnostic-format-json.o is within OBJS-libcommon and thus
493 doesn't have access to trees (for m_fndecl). */
496 default_tree_make_json_for_path (diagnostic_context
*context
,
497 const diagnostic_path
*path
)
499 json::array
*path_array
= new json::array ();
500 for (unsigned i
= 0; i
< path
->num_events (); i
++)
502 const diagnostic_event
&event
= path
->get_event (i
);
504 json::object
*event_obj
= new json::object ();
505 if (event
.get_location ())
506 event_obj
->set ("location",
507 json_from_expanded_location (context
,
508 event
.get_location ()));
509 label_text
event_text (event
.get_desc (false));
510 event_obj
->set ("description", new json::string (event_text
.m_buffer
));
511 event_text
.maybe_free ();
512 if (tree fndecl
= event
.get_fndecl ())
515 = identifier_to_locale (lang_hooks
.decl_printable_name (fndecl
, 2));
516 event_obj
->set ("function", new json::string (function
));
518 event_obj
->set ("depth",
519 new json::integer_number (event
.get_stack_depth ()));
520 path_array
->append (event_obj
);
529 /* A subclass of simple_diagnostic_path that adds member functions
530 for adding test events. */
532 class test_diagnostic_path
: public simple_diagnostic_path
535 test_diagnostic_path (pretty_printer
*event_pp
)
536 : simple_diagnostic_path (event_pp
)
540 void add_entry (tree fndecl
, int stack_depth
)
542 add_event (UNKNOWN_LOCATION
, fndecl
, stack_depth
,
543 "entering %qE", fndecl
);
546 void add_return (tree fndecl
, int stack_depth
)
548 add_event (UNKNOWN_LOCATION
, fndecl
, stack_depth
,
549 "returning to %qE", fndecl
);
552 void add_call (tree caller
, int caller_stack_depth
, tree callee
)
554 add_event (UNKNOWN_LOCATION
, caller
, caller_stack_depth
,
555 "calling %qE", callee
);
556 add_entry (callee
, caller_stack_depth
+ 1);
560 /* Verify that empty paths are handled gracefully. */
563 test_empty_path (pretty_printer
*event_pp
)
565 test_diagnostic_path
path (event_pp
);
566 ASSERT_FALSE (path
.interprocedural_p ());
568 path_summary
summary (path
, false);
569 ASSERT_EQ (summary
.get_num_ranges (), 0);
571 test_diagnostic_context dc
;
572 summary
.print (&dc
, true);
574 pp_formatted_text (dc
.printer
));
577 /* Verify that print_path_summary works on a purely intraprocedural path. */
580 test_intraprocedural_path (pretty_printer
*event_pp
)
582 tree fntype_void_void
583 = build_function_type_array (void_type_node
, 0, NULL
);
584 tree fndecl_foo
= build_fn_decl ("foo", fntype_void_void
);
586 test_diagnostic_path
path (event_pp
);
587 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "first %qs", "free");
588 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "double %qs", "free");
590 ASSERT_FALSE (path
.interprocedural_p ());
592 path_summary
summary (path
, false);
593 ASSERT_EQ (summary
.get_num_ranges (), 1);
595 test_diagnostic_context dc
;
596 summary
.print (&dc
, true);
597 ASSERT_STREQ (" `foo': events 1-2 (depth 0)\n"
599 " | (1): first `free'\n"
600 " | (2): double `free'\n"
602 pp_formatted_text (dc
.printer
));
605 /* Verify that print_path_summary works on an interprocedural path. */
608 test_interprocedural_path_1 (pretty_printer
*event_pp
)
610 /* Build fndecls. The types aren't quite right, but that
611 doesn't matter for the purposes of this test. */
612 tree fntype_void_void
613 = build_function_type_array (void_type_node
, 0, NULL
);
614 tree fndecl_test
= build_fn_decl ("test", fntype_void_void
);
615 tree fndecl_make_boxed_int
616 = build_fn_decl ("make_boxed_int", fntype_void_void
);
617 tree fndecl_wrapped_malloc
618 = build_fn_decl ("wrapped_malloc", fntype_void_void
);
619 tree fndecl_free_boxed_int
620 = build_fn_decl ("free_boxed_int", fntype_void_void
);
621 tree fndecl_wrapped_free
622 = build_fn_decl ("wrapped_free", fntype_void_void
);
624 test_diagnostic_path
path (event_pp
);
625 path
.add_entry (fndecl_test
, 0);
626 path
.add_call (fndecl_test
, 0, fndecl_make_boxed_int
);
627 path
.add_call (fndecl_make_boxed_int
, 1, fndecl_wrapped_malloc
);
628 path
.add_event (UNKNOWN_LOCATION
, fndecl_wrapped_malloc
, 2, "calling malloc");
629 path
.add_return (fndecl_test
, 0);
630 path
.add_call (fndecl_test
, 0, fndecl_free_boxed_int
);
631 path
.add_call (fndecl_free_boxed_int
, 1, fndecl_wrapped_free
);
632 path
.add_event (UNKNOWN_LOCATION
, fndecl_wrapped_free
, 2, "calling free");
633 path
.add_return (fndecl_test
, 0);
634 path
.add_call (fndecl_test
, 0, fndecl_free_boxed_int
);
635 path
.add_call (fndecl_free_boxed_int
, 1, fndecl_wrapped_free
);
636 path
.add_event (UNKNOWN_LOCATION
, fndecl_wrapped_free
, 2, "calling free");
637 ASSERT_EQ (path
.num_events (), 18);
639 ASSERT_TRUE (path
.interprocedural_p ());
641 path_summary
summary (path
, false);
642 ASSERT_EQ (summary
.get_num_ranges (), 9);
644 test_diagnostic_context dc
;
645 summary
.print (&dc
, true);
647 (" `test': events 1-2 (depth 0)\n"
649 " | (1): entering `test'\n"
650 " | (2): calling `make_boxed_int'\n"
652 " +--> `make_boxed_int': events 3-4 (depth 1)\n"
654 " | (3): entering `make_boxed_int'\n"
655 " | (4): calling `wrapped_malloc'\n"
657 " +--> `wrapped_malloc': events 5-6 (depth 2)\n"
659 " | (5): entering `wrapped_malloc'\n"
660 " | (6): calling malloc\n"
664 " `test': events 7-8 (depth 0)\n"
666 " | (7): returning to `test'\n"
667 " | (8): calling `free_boxed_int'\n"
669 " +--> `free_boxed_int': events 9-10 (depth 1)\n"
671 " | (9): entering `free_boxed_int'\n"
672 " | (10): calling `wrapped_free'\n"
674 " +--> `wrapped_free': events 11-12 (depth 2)\n"
676 " | (11): entering `wrapped_free'\n"
677 " | (12): calling free\n"
681 " `test': events 13-14 (depth 0)\n"
683 " | (13): returning to `test'\n"
684 " | (14): calling `free_boxed_int'\n"
686 " +--> `free_boxed_int': events 15-16 (depth 1)\n"
688 " | (15): entering `free_boxed_int'\n"
689 " | (16): calling `wrapped_free'\n"
691 " +--> `wrapped_free': events 17-18 (depth 2)\n"
693 " | (17): entering `wrapped_free'\n"
694 " | (18): calling free\n"
696 pp_formatted_text (dc
.printer
));
699 /* Example where we pop the stack to an intermediate frame, rather than the
703 test_interprocedural_path_2 (pretty_printer
*event_pp
)
705 /* Build fndecls. The types aren't quite right, but that
706 doesn't matter for the purposes of this test. */
707 tree fntype_void_void
708 = build_function_type_array (void_type_node
, 0, NULL
);
709 tree fndecl_foo
= build_fn_decl ("foo", fntype_void_void
);
710 tree fndecl_bar
= build_fn_decl ("bar", fntype_void_void
);
711 tree fndecl_baz
= build_fn_decl ("baz", fntype_void_void
);
713 test_diagnostic_path
path (event_pp
);
714 path
.add_entry (fndecl_foo
, 0);
715 path
.add_call (fndecl_foo
, 0, fndecl_bar
);
716 path
.add_call (fndecl_bar
, 1, fndecl_baz
);
717 path
.add_return (fndecl_bar
, 1);
718 path
.add_call (fndecl_bar
, 1, fndecl_baz
);
719 ASSERT_EQ (path
.num_events (), 8);
721 ASSERT_TRUE (path
.interprocedural_p ());
723 path_summary
summary (path
, false);
724 ASSERT_EQ (summary
.get_num_ranges (), 5);
726 test_diagnostic_context dc
;
727 summary
.print (&dc
, true);
729 (" `foo': events 1-2 (depth 0)\n"
731 " | (1): entering `foo'\n"
732 " | (2): calling `bar'\n"
734 " +--> `bar': events 3-4 (depth 1)\n"
736 " | (3): entering `bar'\n"
737 " | (4): calling `baz'\n"
739 " +--> `baz': event 5 (depth 2)\n"
741 " | (5): entering `baz'\n"
745 " `bar': events 6-7 (depth 1)\n"
747 " | (6): returning to `bar'\n"
748 " | (7): calling `baz'\n"
750 " +--> `baz': event 8 (depth 2)\n"
752 " | (8): entering `baz'\n"
754 pp_formatted_text (dc
.printer
));
757 /* Verify that print_path_summary is sane in the face of a recursive
761 test_recursion (pretty_printer
*event_pp
)
763 tree fntype_void_void
764 = build_function_type_array (void_type_node
, 0, NULL
);
765 tree fndecl_factorial
= build_fn_decl ("factorial", fntype_void_void
);
767 test_diagnostic_path
path (event_pp
);
768 path
.add_entry (fndecl_factorial
, 0);
769 for (int depth
= 0; depth
< 3; depth
++)
770 path
.add_call (fndecl_factorial
, depth
, fndecl_factorial
);
771 ASSERT_EQ (path
.num_events (), 7);
773 ASSERT_TRUE (path
.interprocedural_p ());
775 path_summary
summary (path
, false);
776 ASSERT_EQ (summary
.get_num_ranges (), 4);
778 test_diagnostic_context dc
;
779 summary
.print (&dc
, true);
781 (" `factorial': events 1-2 (depth 0)\n"
783 " | (1): entering `factorial'\n"
784 " | (2): calling `factorial'\n"
786 " +--> `factorial': events 3-4 (depth 1)\n"
788 " | (3): entering `factorial'\n"
789 " | (4): calling `factorial'\n"
791 " +--> `factorial': events 5-6 (depth 2)\n"
793 " | (5): entering `factorial'\n"
794 " | (6): calling `factorial'\n"
796 " +--> `factorial': event 7 (depth 3)\n"
798 " | (7): entering `factorial'\n"
800 pp_formatted_text (dc
.printer
));
803 /* Run all of the selftests within this file. */
806 tree_diagnostic_path_cc_tests ()
808 auto_fix_quotes fix_quotes
;
809 pretty_printer
*event_pp
= global_dc
->printer
->clone ();
810 pp_show_color (event_pp
) = 0;
811 test_empty_path (event_pp
);
812 test_intraprocedural_path (event_pp
);
813 test_interprocedural_path_1 (event_pp
);
814 test_interprocedural_path_2 (event_pp
);
815 test_recursion (event_pp
);
819 } // namespace selftest
821 #endif /* #if CHECKING_P */