xref: /netbsd-src/external/gpl3/gcc/dist/gcc/warning-control.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Functions to enable and disable individual warnings on an expression
2    and statement basis.
3 
4    Copyright (C) 2021-2022 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 
35 static inline bool
get_no_warning_bit(const_tree expr)36 get_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 
43 static inline bool
get_no_warning_bit(const gimple * stmt)44 get_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 
51 static inline void
set_no_warning_bit(tree expr,bool value)52 set_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 
59 static inline void
set_no_warning_bit(gimple * stmt,bool value)60 set_no_warning_bit (gimple *stmt, bool value)
61 {
62   stmt->no_warning = value;
63 }
64 
65 /* Return EXPR location or 'UNKNOWN_LOCATION'.  */
66 
67 static inline location_t
get_location(const_tree expr)68 get_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 
79 static inline location_t
get_location(const gimple * stmt)80 get_location (const gimple *stmt)
81 {
82   return gimple_location (stmt);
83 }
84 
85 /* Return the no-warning bitmap for decl/expression EXPR.  */
86 
87 static nowarn_spec_t *
get_nowarn_spec(const_tree expr)88 get_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 (loc) : NULL;
99 }
100 
101 /* Return the no-warning bitmap for statement STMT.  */
102 
103 static nowarn_spec_t *
get_nowarn_spec(const gimple * stmt)104 get_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 (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
warning_suppressed_p(const_tree expr,opt_code opt)121 warning_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 
137 bool
warning_suppressed_p(const gimple * stmt,opt_code opt)138 warning_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 
155 void
suppress_warning(tree expr,opt_code opt,bool supp)156 suppress_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, 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
suppress_warning(gimple * stmt,opt_code opt,bool supp)173 suppress_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, supp);
184 }
185 
186 /* Copy the warning disposition mapping between an expression and/or
187    a statement.  */
188 
189 template <class ToType, class FromType>
copy_warning(ToType to,FromType from)190 void copy_warning (ToType to, FromType from)
191 {
192   const location_t to_loc = get_location (to);
193 
194   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 (to_loc, tem);
211 	}
212       else
213 	{
214 	  if (nowarn_map)
215 	    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   set_no_warning_bit (to, supp);
222 }
223 
224 /* Copy the warning disposition mapping from one expression to another.  */
225 
226 void
copy_warning(tree to,const_tree from)227 copy_warning (tree to, const_tree from)
228 {
229   copy_warning<tree, const_tree>(to, from);
230 }
231 
232 /* Copy the warning disposition mapping from a statement to an expression.  */
233 
234 void
copy_warning(tree to,const gimple * from)235 copy_warning (tree to, const gimple *from)
236 {
237   copy_warning<tree, const gimple *>(to, from);
238 }
239 
240 /* Copy the warning disposition mapping from an expression to a statement.  */
241 
242 void
copy_warning(gimple * to,const_tree from)243 copy_warning (gimple *to, const_tree from)
244 {
245   copy_warning<gimple *, const_tree>(to, from);
246 }
247 
248 /* Copy the warning disposition mapping from one statement to another.  */
249 
250 void
copy_warning(gimple * to,const gimple * from)251 copy_warning (gimple *to, const gimple *from)
252 {
253   copy_warning<gimple *, const gimple *>(to, from);
254 }
255