Branch data Line data Source code
1 : : /* Concrete classes for selftests involving diagnostic paths.
2 : : Copyright (C) 2019-2024 Free Software Foundation, Inc.
3 : : Contributed by David Malcolm <dmalcolm@redhat.com>
4 : :
5 : : This file is part of GCC.
6 : :
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.
11 : :
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.
16 : :
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/>. */
20 : :
21 : :
22 : : #include "config.h"
23 : : #define INCLUDE_VECTOR
24 : : #include "system.h"
25 : : #include "coretypes.h"
26 : : #include "version.h"
27 : : #include "demangle.h"
28 : : #include "backtrace.h"
29 : : #include "diagnostic.h"
30 : : #include "selftest-diagnostic-path.h"
31 : :
32 : : #if CHECKING_P
33 : :
34 : : namespace selftest {
35 : :
36 : : /* class test_diagnostic_path : public diagnostic_path. */
37 : :
38 : 1652 : test_diagnostic_path::test_diagnostic_path (pretty_printer *event_pp)
39 : 1652 : : m_event_pp (event_pp)
40 : : {
41 : 1652 : add_thread ("main");
42 : 1652 : }
43 : :
44 : : /* Implementation of diagnostic_path::num_events vfunc for
45 : : test_diagnostic_path: simply get the number of events in the vec. */
46 : :
47 : : unsigned
48 : 5720 : test_diagnostic_path::num_events () const
49 : : {
50 : 5720 : return m_events.length ();
51 : : }
52 : :
53 : : /* Implementation of diagnostic_path::get_event vfunc for
54 : : test_diagnostic_path: simply return the event in the vec. */
55 : :
56 : : const diagnostic_event &
57 : 18952 : test_diagnostic_path::get_event (int idx) const
58 : : {
59 : 18952 : return *m_events[idx];
60 : : }
61 : :
62 : : unsigned
63 : 0 : test_diagnostic_path::num_threads () const
64 : : {
65 : 0 : return m_threads.length ();
66 : : }
67 : :
68 : : const diagnostic_thread &
69 : 1280 : test_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
70 : : {
71 : 1280 : return *m_threads[idx];
72 : : }
73 : :
74 : : bool
75 : 6240 : test_diagnostic_path::same_function_p (int event_idx_a,
76 : : int event_idx_b) const
77 : : {
78 : 6240 : const char *name_a = m_events[event_idx_a]->get_function_name ();
79 : 6240 : const char *name_b = m_events[event_idx_b]->get_function_name ();
80 : :
81 : 6240 : if (name_a && name_b)
82 : 564 : return 0 == strcmp (name_a, name_b);
83 : 5676 : return name_a == name_b;
84 : : }
85 : :
86 : : diagnostic_thread_id_t
87 : 1652 : test_diagnostic_path::add_thread (const char *name)
88 : : {
89 : 1652 : m_threads.safe_push (new test_diagnostic_thread (name));
90 : 1652 : return m_threads.length () - 1;
91 : : }
92 : :
93 : : /* Add an event to this path at LOC within function FNDECL at
94 : : stack depth DEPTH.
95 : :
96 : : Use m_context's printer to format FMT, as the text of the new
97 : : event.
98 : :
99 : : Return the id of the new event. */
100 : :
101 : : diagnostic_event_id_t
102 : 4532 : test_diagnostic_path::add_event (location_t loc,
103 : : const char *funcname,
104 : : int depth,
105 : : const char *fmt, ...)
106 : : {
107 : 4532 : pretty_printer *pp = m_event_pp;
108 : 4532 : pp_clear_output_area (pp);
109 : :
110 : 4532 : rich_location rich_loc (line_table, UNKNOWN_LOCATION);
111 : :
112 : 4532 : va_list ap;
113 : :
114 : 4532 : va_start (ap, fmt);
115 : :
116 : : /* No localization is done on FMT. */
117 : 4532 : text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
118 : 4532 : pp_format (pp, &ti);
119 : 4532 : pp_output_formatted_text (pp);
120 : :
121 : 4532 : va_end (ap);
122 : :
123 : 4532 : test_diagnostic_event *new_event
124 : 4532 : = new test_diagnostic_event (loc, funcname, depth, pp_formatted_text (pp));
125 : 4532 : m_events.safe_push (new_event);
126 : :
127 : 4532 : pp_clear_output_area (pp);
128 : :
129 : 9064 : return diagnostic_event_id_t (m_events.length () - 1);
130 : 4532 : }
131 : :
132 : : diagnostic_event_id_t
133 : 120 : test_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
134 : : location_t loc,
135 : : const char *funcname,
136 : : int depth,
137 : : const char *fmt, ...)
138 : : {
139 : 120 : pretty_printer *pp = m_event_pp;
140 : 120 : pp_clear_output_area (pp);
141 : :
142 : 120 : rich_location rich_loc (line_table, UNKNOWN_LOCATION);
143 : :
144 : 120 : va_list ap;
145 : :
146 : 120 : va_start (ap, fmt);
147 : :
148 : : /* No localization is done on FMT. */
149 : 120 : text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
150 : :
151 : 120 : pp_format (pp, &ti);
152 : 120 : pp_output_formatted_text (pp);
153 : :
154 : 120 : va_end (ap);
155 : :
156 : 120 : test_diagnostic_event *new_event
157 : : = new test_diagnostic_event (loc, funcname, depth, pp_formatted_text (pp),
158 : 120 : thread_id);
159 : 120 : m_events.safe_push (new_event);
160 : :
161 : 120 : pp_clear_output_area (pp);
162 : :
163 : 240 : return diagnostic_event_id_t (m_events.length () - 1);
164 : 120 : }
165 : :
166 : : /* Mark the most recent event on this path (which must exist) as being
167 : : connected to the next one to be added. */
168 : :
169 : : void
170 : 2016 : test_diagnostic_path::connect_to_next_event ()
171 : : {
172 : 2016 : gcc_assert (m_events.length () > 0);
173 : 2016 : m_events[m_events.length () - 1]->connect_to_next_event ();
174 : 2016 : }
175 : :
176 : : void
177 : 60 : test_diagnostic_path::add_entry (const char *callee_name,
178 : : int stack_depth,
179 : : diagnostic_thread_id_t thread_id)
180 : : {
181 : 60 : add_thread_event (thread_id, UNKNOWN_LOCATION, callee_name, stack_depth,
182 : : "entering %qs", callee_name);
183 : 60 : }
184 : :
185 : : void
186 : 12 : test_diagnostic_path::add_return (const char *caller_name,
187 : : int stack_depth,
188 : : diagnostic_thread_id_t thread_id)
189 : : {
190 : 12 : add_thread_event (thread_id, UNKNOWN_LOCATION, caller_name, stack_depth,
191 : : "returning to %qs", caller_name);
192 : 12 : }
193 : :
194 : : void
195 : 48 : test_diagnostic_path::add_call (const char *caller_name,
196 : : int caller_stack_depth,
197 : : const char *callee_name,
198 : : diagnostic_thread_id_t thread_id)
199 : : {
200 : 48 : add_thread_event (thread_id, UNKNOWN_LOCATION,
201 : : caller_name, caller_stack_depth,
202 : : "calling %qs", callee_name);
203 : 48 : add_entry (callee_name, caller_stack_depth + 1, thread_id);
204 : 48 : }
205 : :
206 : : /* struct test_diagnostic_event. */
207 : :
208 : : /* test_diagnostic_event's ctor. */
209 : :
210 : 4652 : test_diagnostic_event::
211 : : test_diagnostic_event (location_t loc,
212 : : const char *funcname,
213 : : int depth,
214 : : const char *desc,
215 : 4652 : diagnostic_thread_id_t thread_id)
216 : 4652 : : m_loc (loc),
217 : 4652 : m_logical_loc (LOGICAL_LOCATION_KIND_FUNCTION, funcname),
218 : 4652 : m_depth (depth), m_desc (xstrdup (desc)),
219 : 4652 : m_connected_to_next_event (false),
220 : 4652 : m_thread_id (thread_id)
221 : : {
222 : 4652 : }
223 : :
224 : : /* test_diagnostic_event's dtor. */
225 : :
226 : 9304 : test_diagnostic_event::~test_diagnostic_event ()
227 : : {
228 : 4652 : free (m_desc);
229 : 9304 : }
230 : :
231 : : } // namespace selftest
232 : :
233 : : #endif /* #if CHECKING_P */
|