Line data Source code
1 : /* Functions to enable and disable individual warnings on an expression
2 : and statement basis.
3 :
4 : Copyright (C) 2021-2026 Free Software Foundation, Inc.
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it under
9 : the terms of the GNU General Public License as published by the Free
10 : Software Foundation; either version 3, or (at your option) any later
11 : version.
12 :
13 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING3. If not see
20 : <http://www.gnu.org/licenses/>. */
21 :
22 : #include "config.h"
23 : #include "system.h"
24 : #include "coretypes.h"
25 : #include "backend.h"
26 : #include "bitmap.h"
27 : #include "tree.h"
28 : #include "gimple.h"
29 : #include "cgraph.h"
30 : #include "hash-map.h"
31 : #include "gcc-diagnostic-spec.h"
32 :
33 : /* Return the no-warning bit for EXPR. */
34 :
35 : static inline bool
36 3352775202 : get_no_warning_bit (const_tree expr)
37 : {
38 3352775202 : return expr->base.nowarning_flag;
39 : }
40 :
41 : /* Return the no-warning bit for statement STMT. */
42 :
43 : static inline bool
44 1508497161 : get_no_warning_bit (const gimple *stmt)
45 : {
46 1508497161 : return stmt->no_warning;
47 : }
48 :
49 : /* Set the no-warning bit for EXPR to VALUE. */
50 :
51 : static inline void
52 1089415758 : set_no_warning_bit (tree expr, bool value)
53 : {
54 1089415758 : expr->base.nowarning_flag = value;
55 482876082 : }
56 :
57 : /* Set the no-warning bit for statement STMT to VALUE. */
58 :
59 : static inline void
60 19498991 : set_no_warning_bit (gimple *stmt, bool value)
61 : {
62 19498991 : stmt->no_warning = value;
63 99011 : }
64 :
65 : /* Return EXPR location or 'UNKNOWN_LOCATION'. */
66 :
67 : static inline location_t
68 2898020026 : get_location (const_tree expr)
69 : {
70 2898020026 : if (DECL_P (expr))
71 213886975 : return DECL_SOURCE_LOCATION (expr);
72 2684133051 : if (EXPR_P (expr))
73 2622650769 : return EXPR_LOCATION (expr);
74 : return UNKNOWN_LOCATION;
75 : }
76 :
77 : /* Return STMT location (may be 'UNKNOWN_LOCATION'). */
78 :
79 : static inline location_t
80 833485326 : get_location (const gimple *stmt)
81 : {
82 833485326 : return gimple_location (stmt);
83 : }
84 :
85 : /* Return the no-warning bitmap for decl/expression EXPR. */
86 :
87 : static nowarn_spec_t *
88 1791876874 : get_nowarn_spec (const_tree expr)
89 : {
90 1791876874 : const location_t loc = get_location (expr);
91 :
92 1791876874 : if (RESERVED_LOCATION_P (loc))
93 : return NULL;
94 :
95 1546846626 : if (!get_no_warning_bit (expr))
96 : return NULL;
97 :
98 277061884 : return nowarn_map ? nowarn_map->get (loc) : NULL;
99 : }
100 :
101 : /* Return the no-warning bitmap for statement STMT. */
102 :
103 : static nowarn_spec_t *
104 813986335 : get_nowarn_spec (const gimple *stmt)
105 : {
106 813986335 : const location_t loc = get_location (stmt);
107 :
108 813986335 : if (RESERVED_LOCATION_P (loc))
109 : return NULL;
110 :
111 694510826 : if (!get_no_warning_bit (stmt))
112 : return NULL;
113 :
114 10345964 : return nowarn_map ? nowarn_map->get (loc) : NULL;
115 : }
116 :
117 : /* Return true if warning OPT is suppressed for decl/expression EXPR.
118 : By default tests the disposition for any warning. */
119 :
120 : bool
121 1172125516 : warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
122 : {
123 1172125516 : const nowarn_spec_t *spec = get_nowarn_spec (expr);
124 :
125 1172125516 : if (!spec)
126 992455614 : return get_no_warning_bit (expr);
127 :
128 179669902 : const nowarn_spec_t optspec (opt);
129 179669902 : bool dis = *spec & optspec;
130 179669902 : gcc_assert (get_no_warning_bit (expr) || !dis);
131 : return dis;
132 : }
133 :
134 : /* Return true if warning OPT is suppressed for statement STMT.
135 : By default tests the disposition for any warning. */
136 :
137 : bool
138 807394652 : warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
139 : {
140 807394652 : const nowarn_spec_t *spec = get_nowarn_spec (stmt);
141 :
142 807394652 : if (!spec)
143 : /* Fall back on the single no-warning bit. */
144 797637914 : return get_no_warning_bit (stmt);
145 :
146 9756738 : const nowarn_spec_t optspec (opt);
147 9756738 : bool dis = *spec & optspec;
148 9756738 : gcc_assert (get_no_warning_bit (stmt) || !dis);
149 : return dis;
150 : }
151 :
152 : /* Enable, or by default disable, a warning for the expression.
153 : The wildcard OPT of -1 controls all warnings. */
154 :
155 : void
156 482876082 : suppress_warning (tree expr, opt_code opt /* = all_warnings */,
157 : bool supp /* = true */)
158 : {
159 482876082 : if (opt == no_warning)
160 : return;
161 :
162 482876082 : const location_t loc = get_location (expr);
163 :
164 482876082 : if (!RESERVED_LOCATION_P (loc))
165 413146064 : supp = suppress_warning_at (loc, opt, supp) || supp;
166 482876082 : set_no_warning_bit (expr, supp);
167 : }
168 :
169 : /* Enable, or by default disable, a warning for the statement STMT.
170 : The wildcard OPT of -1 controls all warnings. */
171 :
172 : void
173 248086 : suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
174 : bool supp /* = true */)
175 : {
176 248086 : if (opt == no_warning)
177 : return;
178 :
179 99011 : const location_t loc = get_location (stmt);
180 :
181 99011 : if (!RESERVED_LOCATION_P (loc))
182 98989 : supp = suppress_warning_at (loc, opt, supp) || supp;
183 99011 : set_no_warning_bit (stmt, supp);
184 : }
185 :
186 : /* Copy the warning disposition mapping between an expression and/or
187 : a statement. */
188 :
189 : template <class ToType, class FromType>
190 625939656 : void copy_warning (ToType to, FromType from)
191 : {
192 625939656 : const location_t to_loc = get_location (to);
193 :
194 625939656 : const bool supp = get_no_warning_bit (from);
195 :
196 625939656 : nowarn_spec_t *from_spec = get_nowarn_spec (from);
197 625939656 : if (RESERVED_LOCATION_P (to_loc))
198 : /* We cannot set no-warning dispositions for 'to', so we have no chance but
199 : lose those potentially set for 'from'. */
200 : ;
201 : else
202 : {
203 514031181 : if (from_spec)
204 : {
205 : /* If there's an entry in the map the no-warning bit must be set. */
206 68595923 : gcc_assert (supp);
207 :
208 68595923 : gcc_checking_assert (nowarn_map);
209 68595923 : nowarn_spec_t tem = *from_spec;
210 68595923 : nowarn_map->put (to_loc, tem);
211 : }
212 445435258 : else if (supp)
213 : {
214 120665 : if (nowarn_map)
215 116488 : nowarn_map->remove (to_loc);
216 : }
217 : }
218 :
219 : /* The no-warning bit might be set even if the map has not been consulted, or
220 : otherwise if there's no entry in the map. */
221 625939656 : set_no_warning_bit (to, supp);
222 625939656 : }
223 :
224 : /* Copy the warning disposition mapping from one expression to another. */
225 :
226 : void
227 2725084964 : copy_warning (tree to, const_tree from)
228 : {
229 2725084964 : if (to == from)
230 : return;
231 599948811 : copy_warning<tree, const_tree>(to, from);
232 : }
233 :
234 : /* Copy the warning disposition mapping from a statement to an expression. */
235 :
236 : void
237 6590865 : copy_warning (tree to, const gimple *from)
238 : {
239 6590865 : copy_warning<tree, const gimple *>(to, from);
240 6590865 : }
241 :
242 : /* Copy the warning disposition mapping from an expression to a statement. */
243 :
244 : void
245 19399162 : copy_warning (gimple *to, const_tree from)
246 : {
247 19399162 : copy_warning<gimple *, const_tree>(to, from);
248 19399162 : }
249 :
250 : /* Copy the warning disposition mapping from one statement to another. */
251 :
252 : void
253 818 : copy_warning (gimple *to, const gimple *from)
254 : {
255 818 : if (to == from)
256 : return;
257 818 : copy_warning<gimple *, const gimple *>(to, from);
258 : }
259 :
260 : /* Whether the tree might have a warning spec. */
261 :
262 16308988 : bool has_warning_spec (const_tree t)
263 : {
264 16308988 : const location_t loc = get_location (t);
265 16308988 : return !RESERVED_LOCATION_P (loc) && get_no_warning_bit (t);
266 : }
267 :
268 : /* Retrieve warning dispostion bitmap for tree streaming. */
269 :
270 : unsigned
271 403385 : get_warning_spec (const_tree t)
272 : {
273 403385 : const nowarn_spec_t *spec = get_nowarn_spec (t);
274 403385 : return spec ? *spec : 0;
275 : }
276 :
277 : /* Write warning disposition bitmap for streamed-in tree. */
278 :
279 : void
280 418406 : put_warning_spec (tree t, unsigned bits)
281 : {
282 418406 : const location_t loc = get_location (t);
283 418406 : put_warning_spec_at (loc, bits);
284 418406 : }
|