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 : : #include "config.h"
22 : : #define INCLUDE_ALGORITHM
23 : : #define INCLUDE_MAP
24 : : #define INCLUDE_STRING
25 : : #define INCLUDE_VECTOR
26 : : #include "system.h"
27 : : #include "coretypes.h"
28 : : #include "diagnostics/paths.h"
29 : : #include "diagnostics/state-graphs.h"
30 : :
31 : : /* Disable warnings about missing quoting in GCC diagnostics for the print
32 : : calls below. */
33 : : #if __GNUC__ >= 10
34 : : # pragma GCC diagnostic push
35 : : # pragma GCC diagnostic ignored "-Wformat-diag"
36 : : #endif
37 : :
38 : : using namespace diagnostics;
39 : : using namespace diagnostics::paths;
40 : :
41 : : /* class diagnostics::paths::event. */
42 : :
43 : : /* struct event::meaning. */
44 : :
45 : : void
46 : 144 : event::meaning::dump_to_pp (pretty_printer *pp) const
47 : : {
48 : 144 : bool need_comma = false;
49 : 144 : pp_character (pp, '{');
50 : 144 : if (const char *verb_str = maybe_get_verb_str (m_verb))
51 : : {
52 : 112 : pp_printf (pp, "verb: %qs", verb_str);
53 : 112 : need_comma = true;
54 : : }
55 : 144 : if (const char *noun_str = maybe_get_noun_str (m_noun))
56 : : {
57 : 112 : if (need_comma)
58 : 112 : pp_string (pp, ", ");
59 : 112 : pp_printf (pp, "noun: %qs", noun_str);
60 : 112 : need_comma = true;
61 : : }
62 : 144 : if (const char *property_str = maybe_get_property_str (m_property))
63 : : {
64 : 0 : if (need_comma)
65 : 0 : pp_string (pp, ", ");
66 : 0 : pp_printf (pp, "property: %qs", property_str);
67 : 0 : need_comma = true;
68 : : }
69 : 144 : pp_character (pp, '}');
70 : 144 : }
71 : :
72 : : /* Get a string (or nullptr) for V suitable for use within a SARIF
73 : : threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
74 : :
75 : : const char *
76 : 212 : event::meaning::maybe_get_verb_str (enum verb v)
77 : : {
78 : 212 : switch (v)
79 : : {
80 : 0 : default:
81 : 0 : gcc_unreachable ();
82 : : case verb::unknown:
83 : : return nullptr;
84 : 81 : case verb::acquire:
85 : 81 : return "acquire";
86 : 50 : case verb::release:
87 : 50 : return "release";
88 : 4 : case verb::enter:
89 : 4 : return "enter";
90 : 0 : case verb::exit:
91 : 0 : return "exit";
92 : 3 : case verb::call:
93 : 3 : return "call";
94 : 3 : case verb::return_:
95 : 3 : return "return";
96 : 20 : case verb::branch:
97 : 20 : return "branch";
98 : 19 : case verb::danger:
99 : 19 : return "danger";
100 : : }
101 : : }
102 : :
103 : : /* Get a string (or nullptr) for N suitable for use within a SARIF
104 : : threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
105 : :
106 : : const char *
107 : 212 : event::meaning::maybe_get_noun_str (enum noun n)
108 : : {
109 : 212 : switch (n)
110 : : {
111 : 0 : default:
112 : 0 : gcc_unreachable ();
113 : : case noun::unknown:
114 : : return nullptr;
115 : 0 : case noun::taint:
116 : 0 : return "taint";
117 : 0 : case noun::sensitive:
118 : 0 : return "sensitive";
119 : 10 : case noun::function:
120 : 10 : return "function";
121 : 0 : case noun::lock:
122 : 0 : return "lock";
123 : 35 : case noun::memory:
124 : 35 : return "memory";
125 : 96 : case noun::resource:
126 : 96 : return "resource";
127 : : }
128 : : }
129 : :
130 : : /* Get a string (or nullptr) for P suitable for use within a SARIF
131 : : threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
132 : :
133 : : const char *
134 : 212 : event::meaning::maybe_get_property_str (enum property p)
135 : : {
136 : 212 : switch (p)
137 : : {
138 : 0 : default:
139 : 0 : gcc_unreachable ();
140 : : case property::unknown:
141 : : return nullptr;
142 : 8 : case property::true_:
143 : 8 : return "true";
144 : 12 : case property::false_:
145 : 12 : return "false";
146 : : }
147 : : }
148 : :
149 : : /* Generate a label_text containing the description of this event
150 : : (for debugging/logging purposes). */
151 : :
152 : : label_text
153 : 16 : event::get_desc (pretty_printer &ref_pp) const
154 : : {
155 : 16 : auto pp = ref_pp.clone ();
156 : 16 : pp_show_color (pp.get ()) = false;
157 : 16 : print_desc (*pp.get ());
158 : 16 : return label_text::take (xstrdup (pp_formatted_text (pp.get ())));
159 : 16 : }
160 : :
161 : : // Base implementation of event::maybe_make_diagnostic_state_graph
162 : :
163 : : std::unique_ptr<digraphs::digraph>
164 : 0 : event::maybe_make_diagnostic_state_graph (bool) const
165 : : {
166 : : // Don't attempt to make a state graph:
167 : 0 : return nullptr;
168 : : }
169 : :
170 : : /* class diagnostics::paths::path. */
171 : :
172 : : /* Subroutine of path::interprocedural_p.
173 : : Look for the first event in this path that is within a function
174 : : i.e. has a non-null logical location for which function_p is true.
175 : : If found, write its index to *OUT_IDX and return true.
176 : : Otherwise return false. */
177 : :
178 : : bool
179 : 4002 : path::get_first_event_in_a_function (unsigned *out_idx) const
180 : : {
181 : 4002 : const unsigned num = num_events ();
182 : 4139 : for (unsigned i = 0; i < num; i++)
183 : : {
184 : 4134 : const event &event = get_event (i);
185 : 4134 : if (logical_locations::key logical_loc = event.get_logical_location ())
186 : 3997 : if (m_logical_loc_mgr.function_p (logical_loc))
187 : : {
188 : 3997 : *out_idx = i;
189 : 3997 : return true;
190 : : }
191 : : }
192 : : return false;
193 : : }
194 : :
195 : : /* Return true if the events in this path involve more than one
196 : : function, or false if it is purely intraprocedural. */
197 : :
198 : : bool
199 : 4002 : path::interprocedural_p () const
200 : : {
201 : : /* Ignore leading events that are outside of any function. */
202 : 4002 : unsigned first_fn_event_idx;
203 : 4002 : if (!get_first_event_in_a_function (&first_fn_event_idx))
204 : : return false;
205 : :
206 : 3997 : const event &first_fn_event = get_event (first_fn_event_idx);
207 : 3997 : int first_fn_stack_depth = first_fn_event.get_stack_depth ();
208 : :
209 : 3997 : const unsigned num = num_events ();
210 : 12373 : for (unsigned i = first_fn_event_idx + 1; i < num; i++)
211 : : {
212 : 9179 : if (!same_function_p (first_fn_event_idx, i))
213 : : return true;
214 : 8603 : if (get_event (i).get_stack_depth () != first_fn_stack_depth)
215 : : return true;
216 : : }
217 : : return false;
218 : : }
219 : :
220 : : /* Print PATH by emitting a dummy "note" associated with it. */
221 : :
222 : : DEBUG_FUNCTION
223 : 0 : void debug (path *p)
224 : : {
225 : 0 : rich_location richloc (line_table, UNKNOWN_LOCATION);
226 : 0 : richloc.set_path (p);
227 : 0 : inform (&richloc, "debug path");
228 : 0 : }
229 : :
230 : : #if __GNUC__ >= 10
231 : : # pragma GCC diagnostic pop
232 : : #endif
|