1 /* Paths through the code associated with a diagnostic.
2 Copyright (C) 2019-2021 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 range of consecutive events within a diagnostic_path,
114 all with the same fndecl and stack_depth, and which are suitable
115 to print with a single call to diagnostic_show_locus. */
118 event_range (const diagnostic_path
*path
, unsigned start_idx
,
119 const diagnostic_event
&initial_event
)
121 m_initial_event (initial_event
),
122 m_fndecl (initial_event
.get_fndecl ()),
123 m_stack_depth (initial_event
.get_stack_depth ()),
124 m_start_idx (start_idx
), m_end_idx (start_idx
),
125 m_path_label (path
, start_idx
),
126 m_richloc (initial_event
.get_location (), &m_path_label
)
129 bool maybe_add_event (const diagnostic_event
&new_ev
, unsigned idx
,
130 bool check_rich_locations
)
132 if (!can_consolidate_events (m_initial_event
, new_ev
,
133 check_rich_locations
))
135 if (check_rich_locations
)
136 if (!m_richloc
.add_location_if_nearby (new_ev
.get_location (),
137 false, &m_path_label
))
143 /* Print the events in this range to DC, typically as a single
144 call to the printer's diagnostic_show_locus. */
146 void print (diagnostic_context
*dc
)
148 location_t initial_loc
= m_initial_event
.get_location ();
150 /* Emit a span indicating the filename (and line/column) if the
151 line has changed relative to the last call to
152 diagnostic_show_locus. */
155 expanded_location exploc
156 = linemap_client_expand_location_to_spelling_point
157 (initial_loc
, LOCATION_ASPECT_CARET
);
158 if (exploc
.file
!= LOCATION_FILE (dc
->last_location
))
159 dc
->start_span (dc
, exploc
);
162 /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
163 primary location for an event, diagnostic_show_locus won't print
166 In particular the label for the event won't get printed.
167 Fail more gracefully in this case by showing the event
168 index and text, at no particular location. */
169 if (get_pure_location (initial_loc
) <= BUILTINS_LOCATION
)
171 for (unsigned i
= m_start_idx
; i
<= m_end_idx
; i
++)
173 const diagnostic_event
&iter_event
= m_path
->get_event (i
);
174 diagnostic_event_id_t
event_id (i
);
175 label_text
event_text (iter_event
.get_desc (true));
176 pretty_printer
*pp
= dc
->printer
;
177 pp_printf (pp
, " %@: %s", &event_id
, event_text
.m_buffer
);
179 event_text
.maybe_free ();
184 /* Call diagnostic_show_locus to show the events using labels. */
185 diagnostic_show_locus (dc
, &m_richloc
, DK_DIAGNOSTIC_PATH
);
187 /* If we have a macro expansion, show the expansion to the user. */
188 if (linemap_location_from_macro_expansion_p (line_table
, initial_loc
))
190 gcc_assert (m_start_idx
== m_end_idx
);
191 maybe_unwind_expanded_macro_loc (dc
, initial_loc
);
195 const diagnostic_path
*m_path
;
196 const diagnostic_event
&m_initial_event
;
199 unsigned m_start_idx
;
201 path_label m_path_label
;
202 gcc_rich_location m_richloc
;
205 /* A struct for grouping together the events in a diagnostic_path into
206 ranges of events, partitioned by stack frame (i.e. by fndecl and
211 path_summary (const diagnostic_path
&path
, bool check_rich_locations
);
213 unsigned get_num_ranges () const { return m_ranges
.length (); }
215 auto_delete_vec
<event_range
> m_ranges
;
218 /* path_summary's ctor. */
220 path_summary::path_summary (const diagnostic_path
&path
,
221 bool check_rich_locations
)
223 const unsigned num_events
= path
.num_events ();
225 event_range
*cur_event_range
= NULL
;
226 for (unsigned idx
= 0; idx
< num_events
; idx
++)
228 const diagnostic_event
&event
= path
.get_event (idx
);
230 if (cur_event_range
->maybe_add_event (event
, idx
, check_rich_locations
))
233 cur_event_range
= new event_range (&path
, idx
, event
);
234 m_ranges
.safe_push (cur_event_range
);
238 /* Write SPACES to PP. */
241 write_indent (pretty_printer
*pp
, int spaces
)
243 for (int i
= 0; i
< spaces
; i
++)
247 /* Print FNDDECL to PP, quoting it if QUOTED is true.
249 We can't use "%qE" here since we can't guarantee the capabilities
253 print_fndecl (pretty_printer
*pp
, tree fndecl
, bool quoted
)
255 const char *n
= DECL_NAME (fndecl
)
256 ? identifier_to_locale (lang_hooks
.decl_printable_name (fndecl
, 2))
259 pp_printf (pp
, "%qs", n
);
264 /* Print path_summary PS to DC, giving an overview of the interprocedural
267 Print the event descriptions in a nested form, printing the event
268 descriptions within calls to diagnostic_show_locus, using labels to
274 +--> 'bar' (events 3-4)
277 +--> 'baz' (events 5-6)
285 +--> 'bar' (events 9-10)
288 +--> 'baz' (events 11-12)
292 If SHOW_DEPTHS is true, append " (depth N)" to the header of each run
295 For events with UNKNOWN_LOCATION, print a summary of each the event. */
298 print_path_summary_as_text (const path_summary
*ps
, diagnostic_context
*dc
,
301 pretty_printer
*pp
= dc
->printer
;
303 const int per_frame_indent
= 2;
305 const char *const line_color
= "path";
306 const char *start_line_color
307 = colorize_start (pp_show_color (pp
), line_color
);
308 const char *end_line_color
= colorize_stop (pp_show_color (pp
));
310 /* Keep track of column numbers of existing '|' characters for
311 stack depths we've already printed. */
312 const int EMPTY
= -1;
313 const int DELETED
= -2;
314 typedef int_hash
<int, EMPTY
, DELETED
> vbar_hash
;
315 hash_map
<vbar_hash
, int> vbar_column_for_depth
;
317 /* Print the ranges. */
318 const int base_indent
= 2;
319 int cur_indent
= base_indent
;
322 FOR_EACH_VEC_ELT (ps
->m_ranges
, i
, range
)
324 write_indent (pp
, cur_indent
);
327 const event_range
*prev_range
= ps
->m_ranges
[i
- 1];
328 if (range
->m_stack_depth
> prev_range
->m_stack_depth
)
330 /* Show pushed stack frame(s). */
331 const char *push_prefix
= "+--> ";
332 pp_string (pp
, start_line_color
);
333 pp_string (pp
, push_prefix
);
334 pp_string (pp
, end_line_color
);
335 cur_indent
+= strlen (push_prefix
);
340 print_fndecl (pp
, range
->m_fndecl
, true);
341 pp_string (pp
, ": ");
343 if (range
->m_start_idx
== range
->m_end_idx
)
344 pp_printf (pp
, "event %i",
345 range
->m_start_idx
+ 1);
347 pp_printf (pp
, "events %i-%i",
348 range
->m_start_idx
+ 1, range
->m_end_idx
+ 1);
350 pp_printf (pp
, " (depth %i)", range
->m_stack_depth
);
353 /* Print a run of events. */
355 write_indent (pp
, cur_indent
+ per_frame_indent
);
356 pp_string (pp
, start_line_color
);
358 pp_string (pp
, end_line_color
);
361 char *saved_prefix
= pp_take_prefix (pp
);
364 pretty_printer tmp_pp
;
365 write_indent (&tmp_pp
, cur_indent
+ per_frame_indent
);
366 pp_string (&tmp_pp
, start_line_color
);
367 pp_string (&tmp_pp
, "|");
368 pp_string (&tmp_pp
, end_line_color
);
369 prefix
= xstrdup (pp_formatted_text (&tmp_pp
));
371 pp_set_prefix (pp
, prefix
);
372 pp_prefixing_rule (pp
) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE
;
374 pp_set_prefix (pp
, saved_prefix
);
376 write_indent (pp
, cur_indent
+ per_frame_indent
);
377 pp_string (pp
, start_line_color
);
379 pp_string (pp
, end_line_color
);
383 if (i
< ps
->m_ranges
.length () - 1)
385 const event_range
*next_range
= ps
->m_ranges
[i
+ 1];
387 if (range
->m_stack_depth
> next_range
->m_stack_depth
)
389 if (vbar_column_for_depth
.get (next_range
->m_stack_depth
))
391 /* Show returning from stack frame(s), by printing
396 int vbar_for_next_frame
397 = *vbar_column_for_depth
.get (next_range
->m_stack_depth
);
399 int indent_for_next_frame
400 = vbar_for_next_frame
- per_frame_indent
;
401 write_indent (pp
, vbar_for_next_frame
);
402 pp_string (pp
, start_line_color
);
403 pp_character (pp
, '<');
404 for (int i
= indent_for_next_frame
+ per_frame_indent
;
405 i
< cur_indent
+ per_frame_indent
- 1; i
++)
406 pp_character (pp
, '-');
407 pp_character (pp
, '+');
408 pp_string (pp
, end_line_color
);
410 cur_indent
= indent_for_next_frame
;
412 write_indent (pp
, vbar_for_next_frame
);
413 pp_string (pp
, start_line_color
);
414 pp_character (pp
, '|');
415 pp_string (pp
, end_line_color
);
420 /* Handle disjoint paths (e.g. a callback at some later
422 cur_indent
= base_indent
;
425 else if (range
->m_stack_depth
< next_range
->m_stack_depth
)
427 /* Prepare to show pushed stack frame. */
428 gcc_assert (range
->m_stack_depth
!= EMPTY
);
429 gcc_assert (range
->m_stack_depth
!= DELETED
);
430 vbar_column_for_depth
.put (range
->m_stack_depth
,
431 cur_indent
+ per_frame_indent
);
432 cur_indent
+= per_frame_indent
;
439 } /* end of anonymous namespace for path-printing code. */
441 /* Print PATH to CONTEXT, according to CONTEXT's path_format. */
444 default_tree_diagnostic_path_printer (diagnostic_context
*context
,
445 const diagnostic_path
*path
)
449 const unsigned num_events
= path
->num_events ();
451 switch (context
->path_format
)
457 case DPF_SEPARATE_EVENTS
:
459 /* A note per event. */
460 for (unsigned i
= 0; i
< num_events
; i
++)
462 const diagnostic_event
&event
= path
->get_event (i
);
463 label_text
event_text (event
.get_desc (false));
464 gcc_assert (event_text
.m_buffer
);
465 diagnostic_event_id_t
event_id (i
);
466 inform (event
.get_location (),
467 "%@ %s", &event_id
, event_text
.m_buffer
);
468 event_text
.maybe_free ();
473 case DPF_INLINE_EVENTS
:
475 /* Consolidate related events. */
476 path_summary
summary (*path
, true);
477 char *saved_prefix
= pp_take_prefix (context
->printer
);
478 pp_set_prefix (context
->printer
, NULL
);
479 print_path_summary_as_text (&summary
, context
,
480 context
->show_path_depths
);
481 pp_flush (context
->printer
);
482 pp_set_prefix (context
->printer
, saved_prefix
);
487 /* This has to be here, rather than diagnostic-format-json.cc,
488 since diagnostic-format-json.o is within OBJS-libcommon and thus
489 doesn't have access to trees (for m_fndecl). */
492 default_tree_make_json_for_path (diagnostic_context
*context
,
493 const diagnostic_path
*path
)
495 json::array
*path_array
= new json::array ();
496 for (unsigned i
= 0; i
< path
->num_events (); i
++)
498 const diagnostic_event
&event
= path
->get_event (i
);
500 json::object
*event_obj
= new json::object ();
501 if (event
.get_location ())
502 event_obj
->set ("location",
503 json_from_expanded_location (context
,
504 event
.get_location ()));
505 label_text
event_text (event
.get_desc (false));
506 event_obj
->set ("description", new json::string (event_text
.m_buffer
));
507 event_text
.maybe_free ();
508 if (tree fndecl
= event
.get_fndecl ())
511 = identifier_to_locale (lang_hooks
.decl_printable_name (fndecl
, 2));
512 event_obj
->set ("function", new json::string (function
));
514 event_obj
->set ("depth",
515 new json::integer_number (event
.get_stack_depth ()));
516 path_array
->append (event_obj
);
523 /* Disable warnings about missing quoting in GCC diagnostics for the print
524 calls in the tests below. */
526 # pragma GCC diagnostic push
527 # pragma GCC diagnostic ignored "-Wformat-diag"
532 /* A subclass of simple_diagnostic_path that adds member functions
533 for adding test events. */
535 class test_diagnostic_path
: public simple_diagnostic_path
538 test_diagnostic_path (pretty_printer
*event_pp
)
539 : simple_diagnostic_path (event_pp
)
543 void add_entry (tree fndecl
, int stack_depth
)
545 add_event (UNKNOWN_LOCATION
, fndecl
, stack_depth
,
546 "entering %qE", fndecl
);
549 void add_return (tree fndecl
, int stack_depth
)
551 add_event (UNKNOWN_LOCATION
, fndecl
, stack_depth
,
552 "returning to %qE", fndecl
);
555 void add_call (tree caller
, int caller_stack_depth
, tree callee
)
557 add_event (UNKNOWN_LOCATION
, caller
, caller_stack_depth
,
558 "calling %qE", callee
);
559 add_entry (callee
, caller_stack_depth
+ 1);
563 /* Verify that empty paths are handled gracefully. */
566 test_empty_path (pretty_printer
*event_pp
)
568 test_diagnostic_path
path (event_pp
);
569 ASSERT_FALSE (path
.interprocedural_p ());
571 path_summary
summary (path
, false);
572 ASSERT_EQ (summary
.get_num_ranges (), 0);
574 test_diagnostic_context dc
;
575 print_path_summary_as_text (&summary
, &dc
, true);
577 pp_formatted_text (dc
.printer
));
580 /* Verify that print_path_summary works on a purely intraprocedural path. */
583 test_intraprocedural_path (pretty_printer
*event_pp
)
585 tree fntype_void_void
586 = build_function_type_array (void_type_node
, 0, NULL
);
587 tree fndecl_foo
= build_fn_decl ("foo", fntype_void_void
);
589 test_diagnostic_path
path (event_pp
);
590 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "first %qs", "free");
591 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "double %qs", "free");
593 ASSERT_FALSE (path
.interprocedural_p ());
595 path_summary
summary (path
, false);
596 ASSERT_EQ (summary
.get_num_ranges (), 1);
598 test_diagnostic_context dc
;
599 print_path_summary_as_text (&summary
, &dc
, true);
600 ASSERT_STREQ (" `foo': events 1-2 (depth 0)\n"
602 " | (1): first `free'\n"
603 " | (2): double `free'\n"
605 pp_formatted_text (dc
.printer
));
608 /* Verify that print_path_summary works on an interprocedural path. */
611 test_interprocedural_path_1 (pretty_printer
*event_pp
)
613 /* Build fndecls. The types aren't quite right, but that
614 doesn't matter for the purposes of this test. */
615 tree fntype_void_void
616 = build_function_type_array (void_type_node
, 0, NULL
);
617 tree fndecl_test
= build_fn_decl ("test", fntype_void_void
);
618 tree fndecl_make_boxed_int
619 = build_fn_decl ("make_boxed_int", fntype_void_void
);
620 tree fndecl_wrapped_malloc
621 = build_fn_decl ("wrapped_malloc", fntype_void_void
);
622 tree fndecl_free_boxed_int
623 = build_fn_decl ("free_boxed_int", fntype_void_void
);
624 tree fndecl_wrapped_free
625 = build_fn_decl ("wrapped_free", fntype_void_void
);
627 test_diagnostic_path
path (event_pp
);
628 path
.add_entry (fndecl_test
, 0);
629 path
.add_call (fndecl_test
, 0, fndecl_make_boxed_int
);
630 path
.add_call (fndecl_make_boxed_int
, 1, fndecl_wrapped_malloc
);
631 path
.add_event (UNKNOWN_LOCATION
, fndecl_wrapped_malloc
, 2, "calling malloc");
632 path
.add_return (fndecl_test
, 0);
633 path
.add_call (fndecl_test
, 0, fndecl_free_boxed_int
);
634 path
.add_call (fndecl_free_boxed_int
, 1, fndecl_wrapped_free
);
635 path
.add_event (UNKNOWN_LOCATION
, fndecl_wrapped_free
, 2, "calling free");
636 path
.add_return (fndecl_test
, 0);
637 path
.add_call (fndecl_test
, 0, fndecl_free_boxed_int
);
638 path
.add_call (fndecl_free_boxed_int
, 1, fndecl_wrapped_free
);
639 path
.add_event (UNKNOWN_LOCATION
, fndecl_wrapped_free
, 2, "calling free");
640 ASSERT_EQ (path
.num_events (), 18);
642 ASSERT_TRUE (path
.interprocedural_p ());
644 path_summary
summary (path
, false);
645 ASSERT_EQ (summary
.get_num_ranges (), 9);
647 test_diagnostic_context dc
;
648 print_path_summary_as_text (&summary
, &dc
, true);
650 (" `test': events 1-2 (depth 0)\n"
652 " | (1): entering `test'\n"
653 " | (2): calling `make_boxed_int'\n"
655 " +--> `make_boxed_int': events 3-4 (depth 1)\n"
657 " | (3): entering `make_boxed_int'\n"
658 " | (4): calling `wrapped_malloc'\n"
660 " +--> `wrapped_malloc': events 5-6 (depth 2)\n"
662 " | (5): entering `wrapped_malloc'\n"
663 " | (6): calling malloc\n"
667 " `test': events 7-8 (depth 0)\n"
669 " | (7): returning to `test'\n"
670 " | (8): calling `free_boxed_int'\n"
672 " +--> `free_boxed_int': events 9-10 (depth 1)\n"
674 " | (9): entering `free_boxed_int'\n"
675 " | (10): calling `wrapped_free'\n"
677 " +--> `wrapped_free': events 11-12 (depth 2)\n"
679 " | (11): entering `wrapped_free'\n"
680 " | (12): calling free\n"
684 " `test': events 13-14 (depth 0)\n"
686 " | (13): returning to `test'\n"
687 " | (14): calling `free_boxed_int'\n"
689 " +--> `free_boxed_int': events 15-16 (depth 1)\n"
691 " | (15): entering `free_boxed_int'\n"
692 " | (16): calling `wrapped_free'\n"
694 " +--> `wrapped_free': events 17-18 (depth 2)\n"
696 " | (17): entering `wrapped_free'\n"
697 " | (18): calling free\n"
699 pp_formatted_text (dc
.printer
));
702 /* Example where we pop the stack to an intermediate frame, rather than the
706 test_interprocedural_path_2 (pretty_printer
*event_pp
)
708 /* Build fndecls. The types aren't quite right, but that
709 doesn't matter for the purposes of this test. */
710 tree fntype_void_void
711 = build_function_type_array (void_type_node
, 0, NULL
);
712 tree fndecl_foo
= build_fn_decl ("foo", fntype_void_void
);
713 tree fndecl_bar
= build_fn_decl ("bar", fntype_void_void
);
714 tree fndecl_baz
= build_fn_decl ("baz", fntype_void_void
);
716 test_diagnostic_path
path (event_pp
);
717 path
.add_entry (fndecl_foo
, 0);
718 path
.add_call (fndecl_foo
, 0, fndecl_bar
);
719 path
.add_call (fndecl_bar
, 1, fndecl_baz
);
720 path
.add_return (fndecl_bar
, 1);
721 path
.add_call (fndecl_bar
, 1, fndecl_baz
);
722 ASSERT_EQ (path
.num_events (), 8);
724 ASSERT_TRUE (path
.interprocedural_p ());
726 path_summary
summary (path
, false);
727 ASSERT_EQ (summary
.get_num_ranges (), 5);
729 test_diagnostic_context dc
;
730 print_path_summary_as_text (&summary
, &dc
, true);
732 (" `foo': events 1-2 (depth 0)\n"
734 " | (1): entering `foo'\n"
735 " | (2): calling `bar'\n"
737 " +--> `bar': events 3-4 (depth 1)\n"
739 " | (3): entering `bar'\n"
740 " | (4): calling `baz'\n"
742 " +--> `baz': event 5 (depth 2)\n"
744 " | (5): entering `baz'\n"
748 " `bar': events 6-7 (depth 1)\n"
750 " | (6): returning to `bar'\n"
751 " | (7): calling `baz'\n"
753 " +--> `baz': event 8 (depth 2)\n"
755 " | (8): entering `baz'\n"
757 pp_formatted_text (dc
.printer
));
760 /* Verify that print_path_summary is sane in the face of a recursive
764 test_recursion (pretty_printer
*event_pp
)
766 tree fntype_void_void
767 = build_function_type_array (void_type_node
, 0, NULL
);
768 tree fndecl_factorial
= build_fn_decl ("factorial", fntype_void_void
);
770 test_diagnostic_path
path (event_pp
);
771 path
.add_entry (fndecl_factorial
, 0);
772 for (int depth
= 0; depth
< 3; depth
++)
773 path
.add_call (fndecl_factorial
, depth
, fndecl_factorial
);
774 ASSERT_EQ (path
.num_events (), 7);
776 ASSERT_TRUE (path
.interprocedural_p ());
778 path_summary
summary (path
, false);
779 ASSERT_EQ (summary
.get_num_ranges (), 4);
781 test_diagnostic_context dc
;
782 print_path_summary_as_text (&summary
, &dc
, true);
784 (" `factorial': events 1-2 (depth 0)\n"
786 " | (1): entering `factorial'\n"
787 " | (2): calling `factorial'\n"
789 " +--> `factorial': events 3-4 (depth 1)\n"
791 " | (3): entering `factorial'\n"
792 " | (4): calling `factorial'\n"
794 " +--> `factorial': events 5-6 (depth 2)\n"
796 " | (5): entering `factorial'\n"
797 " | (6): calling `factorial'\n"
799 " +--> `factorial': event 7 (depth 3)\n"
801 " | (7): entering `factorial'\n"
803 pp_formatted_text (dc
.printer
));
806 /* Run all of the selftests within this file. */
809 tree_diagnostic_path_cc_tests ()
811 auto_fix_quotes fix_quotes
;
812 pretty_printer
*event_pp
= global_dc
->printer
->clone ();
813 pp_show_color (event_pp
) = 0;
814 test_empty_path (event_pp
);
815 test_intraprocedural_path (event_pp
);
816 test_interprocedural_path_1 (event_pp
);
817 test_interprocedural_path_2 (event_pp
);
818 test_recursion (event_pp
);
822 } // namespace selftest
825 # pragma GCC diagnostic pop
828 #endif /* #if CHECKING_P */