1 /* Concrete classes for implementing diagnostic paths.
2 Copyright (C) 2019-2025 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 #define INCLUDE_VECTOR
25 #include "coretypes.h"
30 #include "backtrace.h"
31 #include "diagnostic.h"
32 #include "simple-diagnostic-path.h"
35 /* class simple_diagnostic_path : public diagnostic_path. */
37 simple_diagnostic_path::simple_diagnostic_path (pretty_printer
*event_pp
)
38 : m_event_pp (event_pp
),
39 m_localize_events (true)
44 /* Implementation of diagnostic_path::num_events vfunc for
45 simple_diagnostic_path: simply get the number of events in the vec. */
48 simple_diagnostic_path::num_events () const
50 return m_events
.length ();
53 /* Implementation of diagnostic_path::get_event vfunc for
54 simple_diagnostic_path: simply return the event in the vec. */
56 const diagnostic_event
&
57 simple_diagnostic_path::get_event (int idx
) const
59 return *m_events
[idx
];
63 simple_diagnostic_path::num_threads () const
65 return m_threads
.length ();
68 const diagnostic_thread
&
69 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx
) const
71 return *m_threads
[idx
];
75 simple_diagnostic_path::same_function_p (int event_idx_a
,
76 int event_idx_b
) const
78 return (m_events
[event_idx_a
]->get_fndecl ()
79 == m_events
[event_idx_b
]->get_fndecl ());
82 diagnostic_thread_id_t
83 simple_diagnostic_path::add_thread (const char *name
)
85 m_threads
.safe_push (new simple_diagnostic_thread (name
));
86 return m_threads
.length () - 1;
89 /* Add an event to this path at LOC within function FNDECL at
92 Use m_context's printer to format FMT, as the text of the new
93 event. Localize FMT iff m_localize_events is set.
95 Return the id of the new event. */
98 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
101 pretty_printer
*pp
= m_event_pp
;
102 pp_clear_output_area (pp
);
104 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
110 text_info
ti (m_localize_events
? _(fmt
) : fmt
,
111 &ap
, 0, nullptr, &rich_loc
);
113 pp_output_formatted_text (pp
);
117 simple_diagnostic_event
*new_event
118 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
119 m_events
.safe_push (new_event
);
121 pp_clear_output_area (pp
);
123 return diagnostic_event_id_t (m_events
.length () - 1);
126 diagnostic_event_id_t
127 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id
,
131 const char *fmt
, ...)
133 pretty_printer
*pp
= m_event_pp
;
134 pp_clear_output_area (pp
);
136 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
142 text_info
ti (_(fmt
), &ap
, 0, nullptr, &rich_loc
);
145 pp_output_formatted_text (pp
);
149 simple_diagnostic_event
*new_event
150 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
),
152 m_events
.safe_push (new_event
);
154 pp_clear_output_area (pp
);
156 return diagnostic_event_id_t (m_events
.length () - 1);
159 /* Mark the most recent event on this path (which must exist) as being
160 connected to the next one to be added. */
163 simple_diagnostic_path::connect_to_next_event ()
165 gcc_assert (m_events
.length () > 0);
166 m_events
[m_events
.length () - 1]->connect_to_next_event ();
169 /* struct simple_diagnostic_event. */
171 /* simple_diagnostic_event's ctor. */
173 simple_diagnostic_event::
174 simple_diagnostic_event (location_t loc
,
178 diagnostic_thread_id_t thread_id
)
179 : m_loc (loc
), m_fndecl (fndecl
), m_logical_loc (fndecl
),
180 m_depth (depth
), m_desc (xstrdup (desc
)),
181 m_connected_to_next_event (false),
182 m_thread_id (thread_id
)
186 /* simple_diagnostic_event's dtor. */
188 simple_diagnostic_event::~simple_diagnostic_event ()
194 simple_diagnostic_event::print_desc (pretty_printer
&pp
) const
196 pp_string (&pp
, m_desc
);
204 test_intraprocedural_path (pretty_printer
*event_pp
)
206 tree fntype_void_void
207 = build_function_type_array (void_type_node
, 0, NULL
);
208 tree fndecl_foo
= build_fn_decl ("foo", fntype_void_void
);
210 simple_diagnostic_path
path (event_pp
);
211 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "first %qs", "free");
212 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "double %qs", "free");
214 ASSERT_EQ (path
.num_events (), 2);
215 ASSERT_EQ (path
.num_threads (), 1);
216 ASSERT_FALSE (path
.interprocedural_p ());
217 ASSERT_STREQ (path
.get_event (0).get_desc (*event_pp
).get (),
219 ASSERT_STREQ (path
.get_event (1).get_desc (*event_pp
).get (),
223 /* Run all of the selftests within this file. */
226 simple_diagnostic_path_cc_tests ()
228 /* In a few places we use the global dc's printer to determine
229 colorization so ensure this off during the tests. */
230 pretty_printer
*global_pp
= global_dc
->get_reference_printer ();
231 const bool saved_show_color
= pp_show_color (global_pp
);
232 pp_show_color (global_pp
) = false;
234 auto_fix_quotes fix_quotes
;
235 std::unique_ptr
<pretty_printer
> event_pp
236 = std::unique_ptr
<pretty_printer
> (global_pp
->clone ());
238 test_intraprocedural_path (event_pp
.get ());
240 pp_show_color (global_pp
) = saved_show_color
;
243 } // namespace selftest
245 #endif /* #if CHECKING_P */