[PATCH] RISC-V: Move UNSPEC_SSP_SET and UNSPEC_SSP_TEST to correct enum
[gcc.git] / gcc / simple-diagnostic-path.cc
blobb7fb74fd5605033d29ded3867a61442d77434046
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
10 version.
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
15 for more details.
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/>. */
22 #include "config.h"
23 #define INCLUDE_VECTOR
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "version.h"
28 #include "demangle.h"
29 #include "intl.h"
30 #include "backtrace.h"
31 #include "diagnostic.h"
32 #include "simple-diagnostic-path.h"
33 #include "selftest.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)
41 add_thread ("main");
44 /* Implementation of diagnostic_path::num_events vfunc for
45 simple_diagnostic_path: simply get the number of events in the vec. */
47 unsigned
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];
62 unsigned
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];
74 bool
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
90 stack depth DEPTH.
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. */
97 diagnostic_event_id_t
98 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
99 const char *fmt, ...)
101 pretty_printer *pp = m_event_pp;
102 pp_clear_output_area (pp);
104 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
106 va_list ap;
108 va_start (ap, fmt);
110 text_info ti (m_localize_events ? _(fmt) : fmt,
111 &ap, 0, nullptr, &rich_loc);
112 pp_format (pp, &ti);
113 pp_output_formatted_text (pp);
115 va_end (ap);
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,
128 location_t loc,
129 tree fndecl,
130 int depth,
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);
138 va_list ap;
140 va_start (ap, fmt);
142 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
144 pp_format (pp, &ti);
145 pp_output_formatted_text (pp);
147 va_end (ap);
149 simple_diagnostic_event *new_event
150 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
151 thread_id);
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. */
162 void
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,
175 tree fndecl,
176 int depth,
177 const char *desc,
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 ()
190 free (m_desc);
193 void
194 simple_diagnostic_event::print_desc (pretty_printer &pp) const
196 pp_string (&pp, m_desc);
199 #if CHECKING_P
201 namespace selftest {
203 static void
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 (),
218 "first `free'");
219 ASSERT_STREQ (path.get_event (1).get_desc (*event_pp).get (),
220 "double `free'");
223 /* Run all of the selftests within this file. */
225 void
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 */