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 : 64417 : 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 : : enum class noun
102 : : {
103 : : unknown,
104 : :
105 : : taint,
106 : : sensitive, // this one isn't in SARIF v2.1.0; filed as https://github.com/oasis-tcs/sarif-spec/issues/530
107 : : function,
108 : : lock,
109 : : memory,
110 : : resource
111 : : };
112 : : enum class property
113 : : {
114 : : unknown,
115 : :
116 : : true_,
117 : : false_
118 : : };
119 : : /* A bundle of such enums, allowing for descriptions of the meaning of
120 : : an event, such as
121 : : - "acquire memory": meaning (verb::acquire, noun::memory)
122 : : - "take true branch"": meaning (verb::branch, property::true)
123 : : - "return from function": meaning (verb::return, noun::function)
124 : : etc, as per SARIF's threadFlowLocation "kinds" property
125 : : (SARIF v2.1.0 section 3.38.8). */
126 : : struct meaning
127 : : {
128 : 3612 : meaning ()
129 : : : m_verb (verb::unknown),
130 : : m_noun (noun::unknown),
131 : : m_property (property::unknown)
132 : : {
133 : : }
134 : 951 : meaning (enum verb verb, enum noun noun)
135 : : : m_verb (verb), m_noun (noun), m_property (property::unknown)
136 : : {
137 : : }
138 : 242 : meaning (enum verb verb, enum property property)
139 : : : m_verb (verb), m_noun (noun::unknown), m_property (property)
140 : : {
141 : : }
142 : :
143 : : void dump_to_pp (pretty_printer *pp) const;
144 : :
145 : : static const char *maybe_get_verb_str (enum verb);
146 : : static const char *maybe_get_noun_str (enum noun);
147 : : static const char *maybe_get_property_str (enum property);
148 : :
149 : : enum verb m_verb;
150 : : enum noun m_noun;
151 : : enum property m_property;
152 : : };
153 : :
154 : 5022 : virtual ~event () {}
155 : :
156 : : virtual location_t get_location () const = 0;
157 : :
158 : : /* Stack depth, so that consumers can visualize the interprocedural
159 : : calls, returns, and frame nesting. */
160 : : virtual int get_stack_depth () const = 0;
161 : :
162 : : /* Print a localized (and possibly colorized) description of this event. */
163 : : virtual void print_desc (pretty_printer &pp) const = 0;
164 : :
165 : : /* Get a logical location for this event, or null if there is none. */
166 : : virtual logical_locations::key get_logical_location () const = 0;
167 : :
168 : : virtual meaning get_meaning () const = 0;
169 : :
170 : : /* True iff we should draw a line connecting this event to the
171 : : next event (e.g. to highlight control flow). */
172 : : virtual bool connect_to_next_event_p () const = 0;
173 : :
174 : : virtual thread_id_t get_thread_id () const = 0;
175 : :
176 : : /* Hook for SARIF output to allow for adding diagnostic-specific
177 : : properties to the threadFlowLocation object's property bag. */
178 : : virtual void
179 : 9 : maybe_add_sarif_properties (sarif_builder &,
180 : : sarif_object &/*thread_flow_loc_obj*/) const
181 : : {
182 : 9 : }
183 : :
184 : : /* Hook for capturing state at this event, potentially for visualizing
185 : : in HTML output, or for adding to SARIF. */
186 : : virtual std::unique_ptr<digraphs::digraph>
187 : : maybe_make_diagnostic_state_graph (bool debug) const;
188 : :
189 : : label_text get_desc (pretty_printer &ref_pp) const;
190 : : };
191 : :
192 : : /* Abstract base class representing a thread of execution within
193 : : a diagnostics::paths::path.
194 : : Each event is associated with one thread.
195 : : Typically there is just one thread per diagnostics::paths::path. */
196 : :
197 : 11407 : class thread
198 : : {
199 : : public:
200 : : virtual ~thread () {}
201 : : virtual label_text get_name (bool can_colorize) const = 0;
202 : : };
203 : :
204 : : /* Abstract base class for getting at a sequence of events. */
205 : :
206 : : class path
207 : : {
208 : : public:
209 : : virtual ~path () {}
210 : : virtual unsigned num_events () const = 0;
211 : : virtual const event & get_event (int idx) const = 0;
212 : : virtual unsigned num_threads () const = 0;
213 : : virtual const thread &
214 : : get_thread (thread_id_t) const = 0;
215 : :
216 : : /* Return true iff the two events are both within the same function,
217 : : or both outside of any function. */
218 : : virtual bool
219 : : same_function_p (int event_idx_a,
220 : : int event_idx_b) const = 0;
221 : :
222 : : bool interprocedural_p () const;
223 : : bool multithreaded_p () const;
224 : :
225 : 10936 : const logical_locations::manager &get_logical_location_manager () const
226 : : {
227 : 10936 : return m_logical_loc_mgr;
228 : : }
229 : :
230 : : protected:
231 : 872887 : path (const logical_locations::manager &logical_loc_mgr)
232 : 872887 : : m_logical_loc_mgr (logical_loc_mgr)
233 : : {
234 : : }
235 : :
236 : : private:
237 : : bool get_first_event_in_a_function (unsigned *out_idx) const;
238 : :
239 : : const logical_locations::manager &m_logical_loc_mgr;
240 : : };
241 : :
242 : : } // namespace paths
243 : : } // namespace diagnostics
244 : :
245 : : /* Concrete subclasses of the above can be found in
246 : : simple-diagnostic-path.h. */
247 : :
248 : : extern void debug (diagnostics::paths::path *path);
249 : :
250 : : #endif /* ! GCC_DIAGNOSTICS_PATHS_H */
|