analyzer: fix feasibility false +ve on jumps through function ptrs [PR107582]
[platform/upstream/gcc.git] / gcc / diagnostic-spec.cc
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
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     case OPT_Wpessimizing_move:
109     case OPT_Wredundant_move:
110       m_bits = NW_REDUNDANT;
111       break;
112
113     default:
114       /* A catchall group for everything else.  */
115       m_bits = NW_OTHER;
116     }
117 }
118
119 /* A mapping from a 'location_t' to the warning spec set for it.  */
120
121 GTY(()) nowarn_map_t *nowarn_map;
122
123 /* Return the no-warning disposition for location LOC and option OPT
124    or for all/any otions by default.  */
125
126 bool
127 warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
128 {
129   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
130
131   if (!nowarn_map)
132     return false;
133
134   if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
135     {
136       const nowarn_spec_t optspec (opt);
137       return *pspec & optspec;
138     }
139
140   return false;
141 }
142
143  /* Change the supression of warnings for location LOC.
144     OPT controls which warnings are affected.
145     The wildcard OPT of -1 controls all warnings.
146     If SUPP is true (the default), enable the suppression of the warnings.
147     If SUPP is false, disable the suppression of the warnings.  */
148
149 bool
150 suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
151                      bool supp /* = true */)
152 {
153   gcc_checking_assert (!RESERVED_LOCATION_P (loc));
154
155   const nowarn_spec_t optspec (supp ? opt : opt_code ());
156
157   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
158     {
159       if (supp)
160         {
161           *pspec |= optspec;
162           return true;
163         }
164
165       *pspec &= optspec;
166       if (*pspec)
167         return true;
168
169       nowarn_map->remove (loc);
170       return false;
171     }
172
173   if (!supp || opt == no_warning)
174     return false;
175
176   if (!nowarn_map)
177     nowarn_map = nowarn_map_t::create_ggc (32);
178
179   nowarn_map->put (loc, optspec);
180   return true;
181 }
182
183 /* Copy the no-warning disposition from one location to another.  */
184
185 void
186 copy_warning (location_t to, location_t from)
187 {
188   if (!nowarn_map)
189     return;
190
191   nowarn_spec_t *from_spec;
192   if (RESERVED_LOCATION_P (from))
193     from_spec = NULL;
194   else
195     from_spec = nowarn_map->get (from);
196   if (RESERVED_LOCATION_P (to))
197     /* We cannot set no-warning dispositions for 'to', so we have no chance but
198        lose those potentially set for 'from'.  */
199     ;
200   else
201     {
202       if (from_spec)
203         {
204           nowarn_spec_t tem = *from_spec;
205           nowarn_map->put (to, tem);
206         }
207       else
208         nowarn_map->remove (to);
209     }
210 }