1 /* Concrete classes for implementing diagnostic paths.
2 Copyright (C) 2019-2024 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_MEMORY
24 #define INCLUDE_VECTOR
26 #include "coretypes.h"
31 #include "backtrace.h"
32 #include "diagnostic.h"
33 #include "simple-diagnostic-path.h"
36 /* class simple_diagnostic_path : public diagnostic_path. */
38 simple_diagnostic_path::simple_diagnostic_path (pretty_printer
*event_pp
)
39 : m_event_pp (event_pp
),
40 m_localize_events (true)
45 /* Implementation of diagnostic_path::num_events vfunc for
46 simple_diagnostic_path: simply get the number of events in the vec. */
49 simple_diagnostic_path::num_events () const
51 return m_events
.length ();
54 /* Implementation of diagnostic_path::get_event vfunc for
55 simple_diagnostic_path: simply return the event in the vec. */
57 const diagnostic_event
&
58 simple_diagnostic_path::get_event (int idx
) const
60 return *m_events
[idx
];
64 simple_diagnostic_path::num_threads () const
66 return m_threads
.length ();
69 const diagnostic_thread
&
70 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx
) const
72 return *m_threads
[idx
];
76 simple_diagnostic_path::same_function_p (int event_idx_a
,
77 int event_idx_b
) const
79 return (m_events
[event_idx_a
]->get_fndecl ()
80 == m_events
[event_idx_b
]->get_fndecl ());
83 diagnostic_thread_id_t
84 simple_diagnostic_path::add_thread (const char *name
)
86 m_threads
.safe_push (new simple_diagnostic_thread (name
));
87 return m_threads
.length () - 1;
90 /* Add an event to this path at LOC within function FNDECL at
93 Use m_context's printer to format FMT, as the text of the new
94 event. Localize FMT iff m_localize_events is set.
96 Return the id of the new event. */
99 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
100 const char *fmt
, ...)
102 pretty_printer
*pp
= m_event_pp
;
103 pp_clear_output_area (pp
);
105 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
111 text_info
ti (m_localize_events
? _(fmt
) : fmt
,
112 &ap
, 0, nullptr, &rich_loc
);
114 pp_output_formatted_text (pp
);
118 simple_diagnostic_event
*new_event
119 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
120 m_events
.safe_push (new_event
);
122 pp_clear_output_area (pp
);
124 return diagnostic_event_id_t (m_events
.length () - 1);
127 diagnostic_event_id_t
128 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id
,
132 const char *fmt
, ...)
134 pretty_printer
*pp
= m_event_pp
;
135 pp_clear_output_area (pp
);
137 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
143 text_info
ti (_(fmt
), &ap
, 0, nullptr, &rich_loc
);
146 pp_output_formatted_text (pp
);
150 simple_diagnostic_event
*new_event
151 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
),
153 m_events
.safe_push (new_event
);
155 pp_clear_output_area (pp
);
157 return diagnostic_event_id_t (m_events
.length () - 1);
160 /* Mark the most recent event on this path (which must exist) as being
161 connected to the next one to be added. */
164 simple_diagnostic_path::connect_to_next_event ()
166 gcc_assert (m_events
.length () > 0);
167 m_events
[m_events
.length () - 1]->connect_to_next_event ();
170 /* struct simple_diagnostic_event. */
172 /* simple_diagnostic_event's ctor. */
174 simple_diagnostic_event::
175 simple_diagnostic_event (location_t loc
,
179 diagnostic_thread_id_t thread_id
)
180 : m_loc (loc
), m_fndecl (fndecl
), m_logical_loc (fndecl
),
181 m_depth (depth
), m_desc (xstrdup (desc
)),
182 m_connected_to_next_event (false),
183 m_thread_id (thread_id
)
187 /* simple_diagnostic_event's dtor. */
189 simple_diagnostic_event::~simple_diagnostic_event ()
199 test_intraprocedural_path (pretty_printer
*event_pp
)
201 tree fntype_void_void
202 = build_function_type_array (void_type_node
, 0, NULL
);
203 tree fndecl_foo
= build_fn_decl ("foo", fntype_void_void
);
205 simple_diagnostic_path
path (event_pp
);
206 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "first %qs", "free");
207 path
.add_event (UNKNOWN_LOCATION
, fndecl_foo
, 0, "double %qs", "free");
209 ASSERT_EQ (path
.num_events (), 2);
210 ASSERT_EQ (path
.num_threads (), 1);
211 ASSERT_FALSE (path
.interprocedural_p ());
212 ASSERT_STREQ (path
.get_event (0).get_desc (false).get (), "first `free'");
213 ASSERT_STREQ (path
.get_event (1).get_desc (false).get (), "double `free'");
216 /* Run all of the selftests within this file. */
219 simple_diagnostic_path_cc_tests ()
221 /* In a few places we use the global dc's printer to determine
222 colorization so ensure this off during the tests. */
223 pretty_printer
*global_pp
= global_dc
->m_printer
;
224 const bool saved_show_color
= pp_show_color (global_pp
);
225 pp_show_color (global_pp
) = false;
227 auto_fix_quotes fix_quotes
;
228 std::unique_ptr
<pretty_printer
> event_pp
229 = std::unique_ptr
<pretty_printer
> (global_pp
->clone ());
231 test_intraprocedural_path (event_pp
.get ());
233 pp_show_color (global_pp
) = saved_show_color
;
236 } // namespace selftest
238 #endif /* #if CHECKING_P */