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