Branch data Line data Source code
1 : : /* Paths through the code associated with a diagnostic.
2 : : Copyright (C) 2019-2025 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 : : #ifndef GCC_DIAGNOSTICS_PATHS_H
22 : : #define GCC_DIAGNOSTICS_PATHS_H
23 : :
24 : : #include "diagnostic.h" /* for ATTRIBUTE_GCC_DIAG. */
25 : : #include "diagnostics/event-id.h"
26 : : #include "diagnostics/logical-locations.h"
27 : :
28 : : namespace diagnostics {
29 : : namespace digraphs {
30 : : class digraph;
31 : : } // namespace digraphs
32 : : namespace logical_locations {
33 : : class manager;
34 : : } // logical_locations
35 : : class sarif_builder;
36 : : class sarif_object;
37 : : } //namespace diagnostics
38 : :
39 : : namespace diagnostics {
40 : : namespace paths {
41 : :
42 : : /* A diagnostics::paths::path is an optional additional piece of metadata associated
43 : : with a diagnostic (via its rich_location).
44 : :
45 : : It describes a sequence of events predicted by the compiler that
46 : : lead to the problem occurring, with their locations in the user's source,
47 : : and text descriptions.
48 : :
49 : : For example, the following error has a 3-event path:
50 : :
51 : : test.c: In function 'demo':
52 : : test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
53 : : requires a non-NULL parameter
54 : : 29 | PyList_Append(list, item);
55 : : | ^~~~~~~~~~~~~~~~~~~~~~~~~
56 : : 'demo': events 1-3
57 : : 25 | list = PyList_New(0);
58 : : | ^~~~~~~~~~~~~
59 : : | |
60 : : | (1) when 'PyList_New' fails, returning NULL
61 : : 26 |
62 : : 27 | for (i = 0; i < count; i++) {
63 : : | ~~~
64 : : | |
65 : : | (2) when 'i < count'
66 : : 28 | item = PyLong_FromLong(random());
67 : : 29 | PyList_Append(list, item);
68 : : | ~~~~~~~~~~~~~~~~~~~~~~~~~
69 : : | |
70 : : | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
71 : :
72 : : The diagnostic-printing code has consolidated the path into a single
73 : : run of events, since all the events are near each other and within the same
74 : : function; more complicated examples (such as interprocedural paths)
75 : : might be printed as multiple runs of events. */
76 : :
77 : : /* Abstract base classes, describing events within a path, and the paths
78 : : themselves. */
79 : :
80 : : /* One event within a path. */
81 : :
82 : 66125 : class event
83 : : {
84 : : public:
85 : : /* Enums for giving a sense of what this event means.
86 : : Roughly corresponds to SARIF v2.1.0 section 3.38.8. */
87 : : enum class verb
88 : : {
89 : : unknown,
90 : :
91 : : acquire,
92 : : release,
93 : : enter,
94 : : exit,
95 : : call,
96 : : return_,
97 : : branch,
98 : :
99 : : danger,
100 : :
101 : : // Special control flow operations:
102 : : throw_,
103 : : catch_,
104 : : unwind_, // unwinding stack frame(s) during exception-handling
105 : : setjmp_,
106 : : longjmp_
107 : : };
108 : : enum class noun
109 : : {
110 : : unknown,
111 : :
112 : : taint,
113 : : sensitive, // this one isn't in SARIF v2.1.0; filed as https://github.com/oasis-tcs/sarif-spec/issues/530
114 : : function,
115 : : lock,
116 : : memory,
117 : : resource
118 : : };
119 : : enum class property
120 : : {
121 : : unknown,
122 : :
123 : : true_,
124 : : false_
125 : : };
126 : : /* A bundle of such enums, allowing for descriptions of the meaning of
127 : : an event, such as
128 : : - "acquire memory": meaning (verb::acquire, noun::memory)
129 : : - "take true branch"": meaning (verb::branch, property::true)
130 : : - "return from function": meaning (verb::return, noun::function)
131 : : etc, as per SARIF's threadFlowLocation "kinds" property
132 : : (SARIF v2.1.0 section 3.38.8). */
133 : : struct meaning
134 : : {
135 : 3612 : meaning ()
136 : : : m_verb (verb::unknown),
137 : : m_noun (noun::unknown),
138 : : m_property (property::unknown)
139 : : {
140 : : }
141 : 58 : meaning (enum verb verb)
142 : : : m_verb (verb), m_noun (noun::unknown), m_property (property::unknown)
143 : : {
144 : : }
145 : 997 : meaning (enum verb verb, enum noun noun)
146 : : : m_verb (verb), m_noun (noun), m_property (property::unknown)
147 : : {
148 : : }
149 : 252 : meaning (enum verb verb, enum property property)
150 : : : m_verb (verb), m_noun (noun::unknown), m_property (property)
151 : : {
152 : : }
153 : :
154 : : void dump_to_pp (pretty_printer *pp) const;
155 : :
156 : : static const char *maybe_get_verb_str (enum verb);
157 : : static const char *maybe_get_noun_str (enum noun);
158 : : static const char *maybe_get_property_str (enum property);
159 : :
160 : : enum verb m_verb;
161 : : enum noun m_noun;
162 : : enum property m_property;
163 : : };
164 : :
165 : 5730 : virtual ~event () {}
166 : :
167 : : virtual location_t get_location () const = 0;
168 : :
169 : : /* Stack depth, so that consumers can visualize the interprocedural
170 : : calls, returns, and frame nesting. */
171 : : virtual int get_stack_depth () const = 0;
172 : :
173 : : /* Print a localized (and possibly colorized) description of this event. */
174 : : virtual void print_desc (pretty_printer &pp) const = 0;
175 : :
176 : : /* Get a logical location for this event, or null if there is none. */
177 : : virtual logical_locations::key get_logical_location () const = 0;
178 : :
179 : : virtual meaning get_meaning () const = 0;
180 : :
181 : : /* True iff we should draw a line connecting this event to the
182 : : next event (e.g. to highlight control flow). */
183 : : virtual bool connect_to_next_event_p () const = 0;
184 : :
185 : : virtual thread_id_t get_thread_id () const = 0;
186 : :
187 : : /* Hook for SARIF output to allow for adding diagnostic-specific
188 : : properties to the threadFlowLocation object's property bag. */
189 : : virtual void
190 : 9 : maybe_add_sarif_properties (sarif_builder &,
191 : : sarif_object &/*thread_flow_loc_obj*/) const
192 : : {
193 : 9 : }
194 : :
195 : : /* Hook for capturing state at this event, potentially for visualizing
196 : : in HTML output, or for adding to SARIF. */
197 : : virtual std::unique_ptr<digraphs::digraph>
198 : : maybe_make_diagnostic_state_graph (bool debug) const;
199 : :
200 : : label_text get_desc (pretty_printer &ref_pp) const;
201 : : };
202 : :
203 : : /* Abstract base class representing a thread of execution within
204 : : a diagnostics::paths::path.
205 : : Each event is associated with one thread.
206 : : Typically there is just one thread per diagnostics::paths::path. */
207 : :
208 : 11405 : class thread
209 : : {
210 : : public:
211 : : virtual ~thread () {}
212 : : virtual label_text get_name (bool can_colorize) const = 0;
213 : : };
214 : :
215 : : /* Abstract base class for getting at a sequence of events. */
216 : :
217 : : class path
218 : : {
219 : : public:
220 : : virtual ~path () {}
221 : : virtual unsigned num_events () const = 0;
222 : : virtual const event & get_event (int idx) const = 0;
223 : : virtual unsigned num_threads () const = 0;
224 : : virtual const thread &
225 : : get_thread (thread_id_t) const = 0;
226 : :
227 : : /* Return true iff the two events are both within the same function,
228 : : or both outside of any function. */
229 : : virtual bool
230 : : same_function_p (int event_idx_a,
231 : : int event_idx_b) const = 0;
232 : :
233 : : bool interprocedural_p () const;
234 : : bool multithreaded_p () const;
235 : :
236 : 10934 : const logical_locations::manager &get_logical_location_manager () const
237 : : {
238 : 10934 : return m_logical_loc_mgr;
239 : : }
240 : :
241 : : protected:
242 : 874605 : path (const logical_locations::manager &logical_loc_mgr)
243 : 874605 : : m_logical_loc_mgr (logical_loc_mgr)
244 : : {
245 : : }
246 : :
247 : : private:
248 : : bool get_first_event_in_a_function (unsigned *out_idx) const;
249 : :
250 : : const logical_locations::manager &m_logical_loc_mgr;
251 : : };
252 : :
253 : : } // namespace paths
254 : : } // namespace diagnostics
255 : :
256 : : /* Concrete subclasses of the above can be found in
257 : : simple-diagnostic-path.h. */
258 : :
259 : : extern void debug (diagnostics::paths::path *path);
260 : :
261 : : #endif /* ! GCC_DIAGNOSTICS_PATHS_H */
|