1/* Functions to enable and disable individual warnings on an expression
2 and statement basis.
3
4 Copyright (C) 2021-2023 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 "diagnostic-spec.h"
32
33/* Return the no-warning bit for EXPR. */
34
35static inline bool
36get_no_warning_bit (const_tree expr)
37{
38 return expr->base.nowarning_flag;
39}
40
41/* Return the no-warning bit for statement STMT. */
42
43static inline bool
44get_no_warning_bit (const gimple *stmt)
45{
46 return stmt->no_warning;
47}
48
49/* Set the no-warning bit for EXPR to VALUE. */
50
51static inline void
52set_no_warning_bit (tree expr, bool value)
53{
54 expr->base.nowarning_flag = value;
55}
56
57/* Set the no-warning bit for statement STMT to VALUE. */
58
59static inline void
60set_no_warning_bit (gimple *stmt, bool value)
61{
62 stmt->no_warning = value;
63}
64
65/* Return EXPR location or 'UNKNOWN_LOCATION'. */
66
67static inline location_t
68get_location (const_tree expr)
69{
70 if (DECL_P (expr))
71 return DECL_SOURCE_LOCATION (expr);
72 if (EXPR_P (expr))
73 return EXPR_LOCATION (expr);
74 return UNKNOWN_LOCATION;
75}
76
77/* Return STMT location (may be 'UNKNOWN_LOCATION'). */
78
79static inline location_t
80get_location (const gimple *stmt)
81{
82 return gimple_location (g: stmt);
83}
84
85/* Return the no-warning bitmap for decl/expression EXPR. */
86
87static nowarn_spec_t *
88get_nowarn_spec (const_tree expr)
89{
90 const location_t loc = get_location (expr);
91
92 if (RESERVED_LOCATION_P (loc))
93 return NULL;
94
95 if (!get_no_warning_bit (expr))
96 return NULL;
97
98 return nowarn_map ? nowarn_map->get (k: loc) : NULL;
99}
100
101/* Return the no-warning bitmap for statement STMT. */
102
103static nowarn_spec_t *
104get_nowarn_spec (const gimple *stmt)
105{
106 const location_t loc = get_location (stmt);
107
108 if (RESERVED_LOCATION_P (loc))
109 return NULL;
110
111 if (!get_no_warning_bit (stmt))
112 return NULL;
113
114 return nowarn_map ? nowarn_map->get (k: 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
120bool
121warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
122{
123 const nowarn_spec_t *spec = get_nowarn_spec (expr);
124
125 if (!spec)
126 return get_no_warning_bit (expr);
127
128 const nowarn_spec_t optspec (opt);
129 bool dis = *spec & optspec;
130 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
137bool
138warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
139{
140 const nowarn_spec_t *spec = get_nowarn_spec (stmt);
141
142 if (!spec)
143 /* Fall back on the single no-warning bit. */
144 return get_no_warning_bit (stmt);
145
146 const nowarn_spec_t optspec (opt);
147 bool dis = *spec & optspec;
148 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
155void
156suppress_warning (tree expr, opt_code opt /* = all_warnings */,
157 bool supp /* = true */)
158{
159 if (opt == no_warning)
160 return;
161
162 const location_t loc = get_location (expr);
163
164 if (!RESERVED_LOCATION_P (loc))
165 supp = suppress_warning_at (loc, opt, supp) || supp;
166 set_no_warning_bit (expr, value: 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
172void
173suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
174 bool supp /* = true */)
175{
176 if (opt == no_warning)
177 return;
178
179 const location_t loc = get_location (stmt);
180
181 if (!RESERVED_LOCATION_P (loc))
182 supp = suppress_warning_at (loc, opt, supp) || supp;
183 set_no_warning_bit (stmt, value: supp);
184}
185
186/* Copy the warning disposition mapping between an expression and/or
187 a statement. */
188
189template <class ToType, class FromType>
190void copy_warning (ToType to, FromType from)
191{
192 const location_t to_loc = get_location (to);
193
194 const bool supp = get_no_warning_bit (from);
195
196 nowarn_spec_t *from_spec = get_nowarn_spec (from);
197 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 if (from_spec)
204 {
205 /* If there's an entry in the map the no-warning bit must be set. */
206 gcc_assert (supp);
207
208 gcc_checking_assert (nowarn_map);
209 nowarn_spec_t tem = *from_spec;
210 nowarn_map->put (k: to_loc, v: tem);
211 }
212 else if (supp)
213 {
214 if (nowarn_map)
215 nowarn_map->remove (k: 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 set_no_warning_bit (to, supp);
222}
223
224/* Copy the warning disposition mapping from one expression to another. */
225
226void
227copy_warning (tree to, const_tree from)
228{
229 if (to == from)
230 return;
231 copy_warning<tree, const_tree>(to, from);
232}
233
234/* Copy the warning disposition mapping from a statement to an expression. */
235
236void
237copy_warning (tree to, const gimple *from)
238{
239 copy_warning<tree, const gimple *>(to, from);
240}
241
242/* Copy the warning disposition mapping from an expression to a statement. */
243
244void
245copy_warning (gimple *to, const_tree from)
246{
247 copy_warning<gimple *, const_tree>(to, from);
248}
249
250/* Copy the warning disposition mapping from one statement to another. */
251
252void
253copy_warning (gimple *to, const gimple *from)
254{
255 if (to == from)
256 return;
257 copy_warning<gimple *, const gimple *>(to, from);
258}
259

source code of gcc/warning-control.cc