xref: /netbsd-src/external/gpl3/gcc/dist/gcc/diagnostic-spec.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Functions to enable and disable individual warnings on an expression
2    and statement basis.
3    Copyright (C) 2021-2022 Free Software Foundation, Inc.
4    Contributed by Martin Sebor <msebor@redhat.com>
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 "cgraph.h"
29 #include "hash-map.h"
30 #include "diagnostic-spec.h"
31 #include "pretty-print.h"
32 #include "options.h"
33 
34 /* Initialize *THIS from warning option OPT.  */
35 
nowarn_spec_t(opt_code opt)36 nowarn_spec_t::nowarn_spec_t (opt_code opt)
37 {
38   /* Create a very simple mapping based on testing and experience.
39      It should become more refined with time. */
40   switch (opt)
41     {
42     case no_warning:
43       m_bits = 0;
44       break;
45 
46     case all_warnings:
47       m_bits = -1;
48       break;
49 
50       /* Flow-sensitive warnings about pointer problems issued by both
51 	 front ends and the middle end.  */
52     case OPT_Waddress:
53     case OPT_Wnonnull:
54       m_bits = NW_NONNULL;
55       break;
56 
57       /* Flow-sensitive warnings about arithmetic overflow issued by both
58 	 front ends and the middle end.  */
59     case OPT_Woverflow:
60     case OPT_Wshift_count_negative:
61     case OPT_Wshift_count_overflow:
62     case OPT_Wstrict_overflow:
63       m_bits = NW_VFLOW;
64       break;
65 
66       /* Lexical warnings issued by front ends.  */
67     case OPT_Wabi:
68     case OPT_Wlogical_op:
69     case OPT_Wparentheses:
70     case OPT_Wreturn_type:
71     case OPT_Wsizeof_array_div:
72     case OPT_Wstrict_aliasing:
73     case OPT_Wunused:
74     case OPT_Wunused_function:
75     case OPT_Wunused_but_set_variable:
76     case OPT_Wunused_variable:
77     case OPT_Wunused_but_set_parameter:
78       m_bits = NW_LEXICAL;
79       break;
80 
81       /* Access warning group.  */
82     case OPT_Warray_bounds:
83     case OPT_Warray_bounds_:
84     case OPT_Wformat_overflow_:
85     case OPT_Wformat_truncation_:
86     case OPT_Wrestrict:
87     case OPT_Wsizeof_pointer_memaccess:
88     case OPT_Wstrict_aliasing_:
89     case OPT_Wstringop_overflow_:
90     case OPT_Wstringop_overread:
91     case OPT_Wstringop_truncation:
92       m_bits = NW_ACCESS;
93       break;
94 
95       /* Initialization warning group.  */
96     case OPT_Winit_self:
97     case OPT_Wuninitialized:
98     case OPT_Wmaybe_uninitialized:
99 	m_bits = NW_UNINIT;
100       break;
101 
102     case OPT_Wdangling_pointer_:
103     case OPT_Wreturn_local_addr:
104     case OPT_Wuse_after_free_:
105       m_bits = NW_DANGLING;
106       break;
107 
108     default:
109       /* A catchall group for everything else.  */
110       m_bits = NW_OTHER;
111     }
112 }
113 
114 /* A mapping from a 'location_t' to the warning spec set for it.  */
115 
116 GTY(()) nowarn_map_t *nowarn_map;
117 
118 /* Return the no-warning disposition for location LOC and option OPT
119    or for all/any otions by default.  */
120 
121 bool
warning_suppressed_at(location_t loc,opt_code opt)122 warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
123 {
124   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
125 
126   if (!nowarn_map)
127     return false;
128 
129   if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
130     {
131       const nowarn_spec_t optspec (opt);
132       return *pspec & optspec;
133     }
134 
135   return false;
136 }
137 
138  /* Change the supression of warnings for location LOC.
139     OPT controls which warnings are affected.
140     The wildcard OPT of -1 controls all warnings.
141     If SUPP is true (the default), enable the suppression of the warnings.
142     If SUPP is false, disable the suppression of the warnings.  */
143 
144 bool
suppress_warning_at(location_t loc,opt_code opt,bool supp)145 suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
146 		     bool supp /* = true */)
147 {
148   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
149 
150   const nowarn_spec_t optspec (supp ? opt : opt_code ());
151 
152   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
153     {
154       if (supp)
155 	{
156 	  *pspec |= optspec;
157 	  return true;
158 	}
159 
160       *pspec &= optspec;
161       if (*pspec)
162 	return true;
163 
164       nowarn_map->remove (loc);
165       return false;
166     }
167 
168   if (!supp || opt == no_warning)
169     return false;
170 
171   if (!nowarn_map)
172     nowarn_map = nowarn_map_t::create_ggc (32);
173 
174   nowarn_map->put (loc, optspec);
175   return true;
176 }
177 
178 /* Copy the no-warning disposition from one location to another.  */
179 
180 void
copy_warning(location_t to,location_t from)181 copy_warning (location_t to, location_t from)
182 {
183   if (!nowarn_map)
184     return;
185 
186   nowarn_spec_t *from_spec;
187   if (RESERVED_LOCATION_P (from))
188     from_spec = NULL;
189   else
190     from_spec = nowarn_map->get (from);
191   if (RESERVED_LOCATION_P (to))
192     /* We cannot set no-warning dispositions for 'to', so we have no chance but
193        lose those potentially set for 'from'.  */
194     ;
195   else
196     {
197       if (from_spec)
198 	{
199 	  nowarn_spec_t tem = *from_spec;
200 	  nowarn_map->put (to, tem);
201 	}
202       else
203 	nowarn_map->remove (to);
204     }
205 }
206