annotate gcc/c-family/c-warn.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Diagnostic routines shared by all languages that are variants of C.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 1992-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of GCC.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
9 version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
14 for more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 #include "config.h"
kono
parents:
diff changeset
21 #include "system.h"
kono
parents:
diff changeset
22 #include "coretypes.h"
kono
parents:
diff changeset
23 #include "target.h"
kono
parents:
diff changeset
24 #include "function.h"
kono
parents:
diff changeset
25 #include "tree.h"
kono
parents:
diff changeset
26 #include "c-common.h"
kono
parents:
diff changeset
27 #include "memmodel.h"
kono
parents:
diff changeset
28 #include "tm_p.h"
kono
parents:
diff changeset
29 #include "diagnostic.h"
kono
parents:
diff changeset
30 #include "intl.h"
kono
parents:
diff changeset
31 #include "stringpool.h"
kono
parents:
diff changeset
32 #include "attribs.h"
kono
parents:
diff changeset
33 #include "asan.h"
kono
parents:
diff changeset
34 #include "gcc-rich-location.h"
kono
parents:
diff changeset
35 #include "gimplify.h"
kono
parents:
diff changeset
36 #include "c-family/c-indentation.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
37 #include "c-family/c-spellcheck.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
38 #include "calls.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
39 #include "stor-layout.h"
111
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 /* Print a warning if a constant expression had overflow in folding.
kono
parents:
diff changeset
42 Invoke this function on every expression that the language
kono
parents:
diff changeset
43 requires to be a constant expression.
kono
parents:
diff changeset
44 Note the ANSI C standard says it is erroneous for a
kono
parents:
diff changeset
45 constant expression to overflow. */
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 void
kono
parents:
diff changeset
48 constant_expression_warning (tree value)
kono
parents:
diff changeset
49 {
kono
parents:
diff changeset
50 if (warn_overflow && pedantic
kono
parents:
diff changeset
51 && (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
kono
parents:
diff changeset
52 || TREE_CODE (value) == FIXED_CST
kono
parents:
diff changeset
53 || TREE_CODE (value) == VECTOR_CST
kono
parents:
diff changeset
54 || TREE_CODE (value) == COMPLEX_CST)
kono
parents:
diff changeset
55 && TREE_OVERFLOW (value))
kono
parents:
diff changeset
56 pedwarn (input_location, OPT_Woverflow, "overflow in constant expression");
kono
parents:
diff changeset
57 }
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 /* The same as above but print an unconditional error. */
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 void
kono
parents:
diff changeset
62 constant_expression_error (tree value)
kono
parents:
diff changeset
63 {
kono
parents:
diff changeset
64 if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
kono
parents:
diff changeset
65 || TREE_CODE (value) == FIXED_CST
kono
parents:
diff changeset
66 || TREE_CODE (value) == VECTOR_CST
kono
parents:
diff changeset
67 || TREE_CODE (value) == COMPLEX_CST)
kono
parents:
diff changeset
68 && TREE_OVERFLOW (value))
kono
parents:
diff changeset
69 error ("overflow in constant expression");
kono
parents:
diff changeset
70 }
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 /* Print a warning if an expression result VALUE had an overflow
kono
parents:
diff changeset
73 in folding and its operands hadn't. EXPR, which may be null, is
kono
parents:
diff changeset
74 the operand of the expression.
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 Invoke this function on every expression that
kono
parents:
diff changeset
77 (1) appears in the source code, and
kono
parents:
diff changeset
78 (2) is a constant expression that overflowed, and
kono
parents:
diff changeset
79 (3) is not already checked by convert_and_check;
kono
parents:
diff changeset
80 however, do not invoke this function on operands of explicit casts
kono
parents:
diff changeset
81 or when the expression is the result of an operator and any operand
kono
parents:
diff changeset
82 already overflowed. */
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 void
kono
parents:
diff changeset
85 overflow_warning (location_t loc, tree value, tree expr)
kono
parents:
diff changeset
86 {
kono
parents:
diff changeset
87 if (c_inhibit_evaluation_warnings != 0)
kono
parents:
diff changeset
88 return;
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 const char *warnfmt = NULL;
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 switch (TREE_CODE (value))
kono
parents:
diff changeset
93 {
kono
parents:
diff changeset
94 case INTEGER_CST:
kono
parents:
diff changeset
95 warnfmt = (expr
kono
parents:
diff changeset
96 ? G_("integer overflow in expression %qE of type %qT "
kono
parents:
diff changeset
97 "results in %qE")
kono
parents:
diff changeset
98 : G_("integer overflow in expression of type %qT "
kono
parents:
diff changeset
99 "results in %qE"));
kono
parents:
diff changeset
100 break;
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 case REAL_CST:
kono
parents:
diff changeset
103 warnfmt = (expr
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
104 ? G_("floating point overflow in expression %qE "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
105 "of type %qT results in %qE")
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
106 : G_("floating point overflow in expression of type %qT "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
107 "results in %qE"));
111
kono
parents:
diff changeset
108 break;
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 case FIXED_CST:
kono
parents:
diff changeset
111 warnfmt = (expr
kono
parents:
diff changeset
112 ? G_("fixed-point overflow in expression %qE of type %qT "
kono
parents:
diff changeset
113 "results in %qE")
kono
parents:
diff changeset
114 : G_("fixed-point overflow in expression of type %qT "
kono
parents:
diff changeset
115 "results in %qE"));
kono
parents:
diff changeset
116 break;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 case VECTOR_CST:
kono
parents:
diff changeset
119 warnfmt = (expr
kono
parents:
diff changeset
120 ? G_("vector overflow in expression %qE of type %qT "
kono
parents:
diff changeset
121 "results in %qE")
kono
parents:
diff changeset
122 : G_("vector overflow in expression of type %qT "
kono
parents:
diff changeset
123 "results in %qE"));
kono
parents:
diff changeset
124 break;
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 case COMPLEX_CST:
kono
parents:
diff changeset
127 if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
kono
parents:
diff changeset
128 warnfmt = (expr
kono
parents:
diff changeset
129 ? G_("complex integer overflow in expression %qE "
kono
parents:
diff changeset
130 "of type %qT results in %qE")
kono
parents:
diff changeset
131 : G_("complex integer overflow in expression of type %qT "
kono
parents:
diff changeset
132 "results in %qE"));
kono
parents:
diff changeset
133 else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST)
kono
parents:
diff changeset
134 warnfmt = (expr
kono
parents:
diff changeset
135 ? G_("complex floating point overflow in expression %qE "
kono
parents:
diff changeset
136 "of type %qT results in %qE")
kono
parents:
diff changeset
137 : G_("complex floating point overflow in expression "
kono
parents:
diff changeset
138 "of type %qT results in %qE"));
kono
parents:
diff changeset
139 else
kono
parents:
diff changeset
140 return;
kono
parents:
diff changeset
141 break;
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 default:
kono
parents:
diff changeset
144 return;
kono
parents:
diff changeset
145 }
kono
parents:
diff changeset
146
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
147 bool warned;
111
kono
parents:
diff changeset
148 if (expr)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
149 warned = warning_at (loc, OPT_Woverflow, warnfmt, expr, TREE_TYPE (expr),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
150 value);
111
kono
parents:
diff changeset
151 else
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
152 warned = warning_at (loc, OPT_Woverflow, warnfmt, TREE_TYPE (value),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
153 value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
154
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
155 if (warned)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
156 TREE_NO_WARNING (value) = 1;
111
kono
parents:
diff changeset
157 }
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 /* Helper function for walk_tree. Unwrap C_MAYBE_CONST_EXPRs in an expression
kono
parents:
diff changeset
160 pointed to by TP. */
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 static tree
kono
parents:
diff changeset
163 unwrap_c_maybe_const (tree *tp, int *walk_subtrees, void *)
kono
parents:
diff changeset
164 {
kono
parents:
diff changeset
165 if (TREE_CODE (*tp) == C_MAYBE_CONST_EXPR)
kono
parents:
diff changeset
166 {
kono
parents:
diff changeset
167 *tp = C_MAYBE_CONST_EXPR_EXPR (*tp);
kono
parents:
diff changeset
168 /* C_MAYBE_CONST_EXPRs don't nest. */
kono
parents:
diff changeset
169 *walk_subtrees = false;
kono
parents:
diff changeset
170 }
kono
parents:
diff changeset
171 return NULL_TREE;
kono
parents:
diff changeset
172 }
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 /* Warn about uses of logical || / && operator in a context where it
kono
parents:
diff changeset
175 is likely that the bitwise equivalent was intended by the
kono
parents:
diff changeset
176 programmer. We have seen an expression in which CODE is a binary
kono
parents:
diff changeset
177 operator used to combine expressions OP_LEFT and OP_RIGHT, which before folding
kono
parents:
diff changeset
178 had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE. */
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 void
kono
parents:
diff changeset
181 warn_logical_operator (location_t location, enum tree_code code, tree type,
kono
parents:
diff changeset
182 enum tree_code code_left, tree op_left,
kono
parents:
diff changeset
183 enum tree_code ARG_UNUSED (code_right), tree op_right)
kono
parents:
diff changeset
184 {
kono
parents:
diff changeset
185 int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR);
kono
parents:
diff changeset
186 int in0_p, in1_p, in_p;
kono
parents:
diff changeset
187 tree low0, low1, low, high0, high1, high, lhs, rhs, tem;
kono
parents:
diff changeset
188 bool strict_overflow_p = false;
kono
parents:
diff changeset
189
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
190 if (!warn_logical_op)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
191 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192
111
kono
parents:
diff changeset
193 if (code != TRUTH_ANDIF_EXPR
kono
parents:
diff changeset
194 && code != TRUTH_AND_EXPR
kono
parents:
diff changeset
195 && code != TRUTH_ORIF_EXPR
kono
parents:
diff changeset
196 && code != TRUTH_OR_EXPR)
kono
parents:
diff changeset
197 return;
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 /* We don't want to warn if either operand comes from a macro
kono
parents:
diff changeset
200 expansion. ??? This doesn't work with e.g. NEGATE_EXPR yet;
kono
parents:
diff changeset
201 see PR61534. */
kono
parents:
diff changeset
202 if (from_macro_expansion_at (EXPR_LOCATION (op_left))
kono
parents:
diff changeset
203 || from_macro_expansion_at (EXPR_LOCATION (op_right)))
kono
parents:
diff changeset
204 return;
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 /* Warn if &&/|| are being used in a context where it is
kono
parents:
diff changeset
207 likely that the bitwise equivalent was intended by the
kono
parents:
diff changeset
208 programmer. That is, an expression such as op && MASK
kono
parents:
diff changeset
209 where op should not be any boolean expression, nor a
kono
parents:
diff changeset
210 constant, and mask seems to be a non-boolean integer constant. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
211 STRIP_ANY_LOCATION_WRAPPER (op_right);
111
kono
parents:
diff changeset
212 if (TREE_CODE (op_right) == CONST_DECL)
kono
parents:
diff changeset
213 /* An enumerator counts as a constant. */
kono
parents:
diff changeset
214 op_right = DECL_INITIAL (op_right);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
215 tree stripped_op_left = tree_strip_any_location_wrapper (op_left);
111
kono
parents:
diff changeset
216 if (!truth_value_p (code_left)
kono
parents:
diff changeset
217 && INTEGRAL_TYPE_P (TREE_TYPE (op_left))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
218 && !CONSTANT_CLASS_P (stripped_op_left)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
219 && TREE_CODE (stripped_op_left) != CONST_DECL
111
kono
parents:
diff changeset
220 && !TREE_NO_WARNING (op_left)
kono
parents:
diff changeset
221 && TREE_CODE (op_right) == INTEGER_CST
kono
parents:
diff changeset
222 && !integer_zerop (op_right)
kono
parents:
diff changeset
223 && !integer_onep (op_right))
kono
parents:
diff changeset
224 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
225 bool warned;
111
kono
parents:
diff changeset
226 if (or_op)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
227 warned
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
228 = warning_at (location, OPT_Wlogical_op,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
229 "logical %<or%> applied to non-boolean constant");
111
kono
parents:
diff changeset
230 else
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
231 warned
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
232 = warning_at (location, OPT_Wlogical_op,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
233 "logical %<and%> applied to non-boolean constant");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
234 if (warned)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
235 TREE_NO_WARNING (op_left) = true;
111
kono
parents:
diff changeset
236 return;
kono
parents:
diff changeset
237 }
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 /* We do not warn for constants because they are typical of macro
kono
parents:
diff changeset
240 expansions that test for features. */
kono
parents:
diff changeset
241 if (CONSTANT_CLASS_P (fold_for_warn (op_left))
kono
parents:
diff changeset
242 || CONSTANT_CLASS_P (fold_for_warn (op_right)))
kono
parents:
diff changeset
243 return;
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 /* This warning only makes sense with logical operands. */
kono
parents:
diff changeset
246 if (!(truth_value_p (TREE_CODE (op_left))
kono
parents:
diff changeset
247 || INTEGRAL_TYPE_P (TREE_TYPE (op_left)))
kono
parents:
diff changeset
248 || !(truth_value_p (TREE_CODE (op_right))
kono
parents:
diff changeset
249 || INTEGRAL_TYPE_P (TREE_TYPE (op_right))))
kono
parents:
diff changeset
250 return;
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 /* The range computations only work with scalars. */
kono
parents:
diff changeset
253 if (VECTOR_TYPE_P (TREE_TYPE (op_left))
kono
parents:
diff changeset
254 || VECTOR_TYPE_P (TREE_TYPE (op_right)))
kono
parents:
diff changeset
255 return;
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 /* We first test whether either side separately is trivially true
kono
parents:
diff changeset
258 (with OR) or trivially false (with AND). If so, do not warn.
kono
parents:
diff changeset
259 This is a common idiom for testing ranges of data types in
kono
parents:
diff changeset
260 portable code. */
kono
parents:
diff changeset
261 op_left = unshare_expr (op_left);
kono
parents:
diff changeset
262 walk_tree_without_duplicates (&op_left, unwrap_c_maybe_const, NULL);
kono
parents:
diff changeset
263 lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
kono
parents:
diff changeset
264 if (!lhs)
kono
parents:
diff changeset
265 return;
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 /* If this is an OR operation, invert both sides; now, the result
kono
parents:
diff changeset
268 should be always false to get a warning. */
kono
parents:
diff changeset
269 if (or_op)
kono
parents:
diff changeset
270 in0_p = !in0_p;
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 tem = build_range_check (UNKNOWN_LOCATION, type, lhs, in0_p, low0, high0);
kono
parents:
diff changeset
273 if (tem && integer_zerop (tem))
kono
parents:
diff changeset
274 return;
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 op_right = unshare_expr (op_right);
kono
parents:
diff changeset
277 walk_tree_without_duplicates (&op_right, unwrap_c_maybe_const, NULL);
kono
parents:
diff changeset
278 rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
kono
parents:
diff changeset
279 if (!rhs)
kono
parents:
diff changeset
280 return;
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 /* If this is an OR operation, invert both sides; now, the result
kono
parents:
diff changeset
283 should be always false to get a warning. */
kono
parents:
diff changeset
284 if (or_op)
kono
parents:
diff changeset
285 in1_p = !in1_p;
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 tem = build_range_check (UNKNOWN_LOCATION, type, rhs, in1_p, low1, high1);
kono
parents:
diff changeset
288 if (tem && integer_zerop (tem))
kono
parents:
diff changeset
289 return;
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 /* If both expressions have the same operand, if we can merge the
kono
parents:
diff changeset
292 ranges, ... */
kono
parents:
diff changeset
293 if (operand_equal_p (lhs, rhs, 0)
kono
parents:
diff changeset
294 && merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
kono
parents:
diff changeset
295 in1_p, low1, high1))
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 tem = build_range_check (UNKNOWN_LOCATION, type, lhs, in_p, low, high);
kono
parents:
diff changeset
298 /* ... and if the range test is always false, then warn. */
kono
parents:
diff changeset
299 if (tem && integer_zerop (tem))
kono
parents:
diff changeset
300 {
kono
parents:
diff changeset
301 if (or_op)
kono
parents:
diff changeset
302 warning_at (location, OPT_Wlogical_op,
kono
parents:
diff changeset
303 "logical %<or%> of collectively exhaustive tests is "
kono
parents:
diff changeset
304 "always true");
kono
parents:
diff changeset
305 else
kono
parents:
diff changeset
306 warning_at (location, OPT_Wlogical_op,
kono
parents:
diff changeset
307 "logical %<and%> of mutually exclusive tests is "
kono
parents:
diff changeset
308 "always false");
kono
parents:
diff changeset
309 }
kono
parents:
diff changeset
310 /* Or warn if the operands have exactly the same range, e.g.
kono
parents:
diff changeset
311 A > 0 && A > 0. */
kono
parents:
diff changeset
312 else if (tree_int_cst_equal (low0, low1)
kono
parents:
diff changeset
313 && tree_int_cst_equal (high0, high1))
kono
parents:
diff changeset
314 {
kono
parents:
diff changeset
315 if (or_op)
kono
parents:
diff changeset
316 warning_at (location, OPT_Wlogical_op,
kono
parents:
diff changeset
317 "logical %<or%> of equal expressions");
kono
parents:
diff changeset
318 else
kono
parents:
diff changeset
319 warning_at (location, OPT_Wlogical_op,
kono
parents:
diff changeset
320 "logical %<and%> of equal expressions");
kono
parents:
diff changeset
321 }
kono
parents:
diff changeset
322 }
kono
parents:
diff changeset
323 }
kono
parents:
diff changeset
324
kono
parents:
diff changeset
325 /* Helper function for warn_tautological_cmp. Look for ARRAY_REFs
kono
parents:
diff changeset
326 with constant indices. */
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 static tree
kono
parents:
diff changeset
329 find_array_ref_with_const_idx_r (tree *expr_p, int *, void *)
kono
parents:
diff changeset
330 {
kono
parents:
diff changeset
331 tree expr = *expr_p;
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 if ((TREE_CODE (expr) == ARRAY_REF
kono
parents:
diff changeset
334 || TREE_CODE (expr) == ARRAY_RANGE_REF)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
335 && (TREE_CODE (fold_for_warn (TREE_OPERAND (expr, 1)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
336 == INTEGER_CST))
111
kono
parents:
diff changeset
337 return integer_type_node;
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 return NULL_TREE;
kono
parents:
diff changeset
340 }
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 /* Subroutine of warn_tautological_cmp. Warn about bitwise comparison
kono
parents:
diff changeset
343 that always evaluate to true or false. LOC is the location of the
kono
parents:
diff changeset
344 ==/!= comparison specified by CODE; LHS and RHS are the usual operands
kono
parents:
diff changeset
345 of this comparison. */
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
348 warn_tautological_bitwise_comparison (const op_location_t &loc, tree_code code,
111
kono
parents:
diff changeset
349 tree lhs, tree rhs)
kono
parents:
diff changeset
350 {
kono
parents:
diff changeset
351 if (code != EQ_EXPR && code != NE_EXPR)
kono
parents:
diff changeset
352 return;
kono
parents:
diff changeset
353
kono
parents:
diff changeset
354 /* Extract the operands from e.g. (x & 8) == 4. */
kono
parents:
diff changeset
355 tree bitop;
kono
parents:
diff changeset
356 tree cst;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
357 tree stripped_lhs = tree_strip_any_location_wrapper (lhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
358 tree stripped_rhs = tree_strip_any_location_wrapper (rhs);
111
kono
parents:
diff changeset
359 if ((TREE_CODE (lhs) == BIT_AND_EXPR
kono
parents:
diff changeset
360 || TREE_CODE (lhs) == BIT_IOR_EXPR)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
361 && TREE_CODE (stripped_rhs) == INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
362 bitop = lhs, cst = stripped_rhs;
111
kono
parents:
diff changeset
363 else if ((TREE_CODE (rhs) == BIT_AND_EXPR
kono
parents:
diff changeset
364 || TREE_CODE (rhs) == BIT_IOR_EXPR)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
365 && TREE_CODE (stripped_lhs) == INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
366 bitop = rhs, cst = stripped_lhs;
111
kono
parents:
diff changeset
367 else
kono
parents:
diff changeset
368 return;
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 tree bitopcst;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
371 tree bitop_op0 = fold_for_warn (TREE_OPERAND (bitop, 0));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
372 if (TREE_CODE (bitop_op0) == INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
373 bitopcst = bitop_op0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
374 else {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
375 tree bitop_op1 = fold_for_warn (TREE_OPERAND (bitop, 1));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
376 if (TREE_CODE (bitop_op1) == INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
377 bitopcst = bitop_op1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
378 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
379 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
380 }
111
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 /* Note that the two operands are from before the usual integer
kono
parents:
diff changeset
383 conversions, so their types might not be the same.
kono
parents:
diff changeset
384 Use the larger of the two precisions and ignore bits outside
kono
parents:
diff changeset
385 of that. */
kono
parents:
diff changeset
386 int prec = MAX (TYPE_PRECISION (TREE_TYPE (cst)),
kono
parents:
diff changeset
387 TYPE_PRECISION (TREE_TYPE (bitopcst)));
kono
parents:
diff changeset
388
kono
parents:
diff changeset
389 wide_int bitopcstw = wi::to_wide (bitopcst, prec);
kono
parents:
diff changeset
390 wide_int cstw = wi::to_wide (cst, prec);
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 wide_int res;
kono
parents:
diff changeset
393 if (TREE_CODE (bitop) == BIT_AND_EXPR)
kono
parents:
diff changeset
394 res = bitopcstw & cstw;
kono
parents:
diff changeset
395 else
kono
parents:
diff changeset
396 res = bitopcstw | cstw;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 /* For BIT_AND only warn if (CST2 & CST1) != CST1, and
kono
parents:
diff changeset
399 for BIT_OR only if (CST2 | CST1) != CST1. */
kono
parents:
diff changeset
400 if (res == cstw)
kono
parents:
diff changeset
401 return;
kono
parents:
diff changeset
402
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
403 binary_op_rich_location richloc (loc, lhs, rhs, false);
111
kono
parents:
diff changeset
404 if (code == EQ_EXPR)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
405 warning_at (&richloc, OPT_Wtautological_compare,
111
kono
parents:
diff changeset
406 "bitwise comparison always evaluates to false");
kono
parents:
diff changeset
407 else
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
408 warning_at (&richloc, OPT_Wtautological_compare,
111
kono
parents:
diff changeset
409 "bitwise comparison always evaluates to true");
kono
parents:
diff changeset
410 }
kono
parents:
diff changeset
411
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
412 /* Given LOC from a macro expansion, return the map for the outermost
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
413 macro in the nest of expansions. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
414
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
415 static const line_map_macro *
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
416 get_outermost_macro_expansion (location_t loc)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
417 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
418 gcc_assert (from_macro_expansion_at (loc));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
419
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
420 const line_map *map = linemap_lookup (line_table, loc);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
421 const line_map_macro *macro_map;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
422 do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
423 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
424 macro_map = linemap_check_macro (map);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
425 loc = linemap_unwind_toward_expansion (line_table, loc, &map);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
426 } while (linemap_macro_expansion_map_p (map));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
427
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
428 return macro_map;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
429 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
430
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
431 /* Given LOC_A and LOC_B from macro expansions, return true if
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
432 they are "spelled the same" i.e. if they are both directly from
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
433 expansion of the same non-function-like macro. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
434
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
435 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
436 spelled_the_same_p (location_t loc_a, location_t loc_b)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
437 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
438 gcc_assert (from_macro_expansion_at (loc_a));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
439 gcc_assert (from_macro_expansion_at (loc_b));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
440
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
441 const line_map_macro *map_a = get_outermost_macro_expansion (loc_a);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
442 const line_map_macro *map_b = get_outermost_macro_expansion (loc_b);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
443
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
444 if (map_a->macro == map_b->macro)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
445 if (!cpp_fun_like_macro_p (map_a->macro))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
446 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
447
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
448 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
449 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
450
111
kono
parents:
diff changeset
451 /* Warn if a self-comparison always evaluates to true or false. LOC
kono
parents:
diff changeset
452 is the location of the comparison with code CODE, LHS and RHS are
kono
parents:
diff changeset
453 operands of the comparison. */
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
456 warn_tautological_cmp (const op_location_t &loc, enum tree_code code,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
457 tree lhs, tree rhs)
111
kono
parents:
diff changeset
458 {
kono
parents:
diff changeset
459 if (TREE_CODE_CLASS (code) != tcc_comparison)
kono
parents:
diff changeset
460 return;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 /* Don't warn for various macro expansions. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
463 if (from_macro_expansion_at (loc))
111
kono
parents:
diff changeset
464 return;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
465 bool lhs_in_macro = from_macro_expansion_at (EXPR_LOCATION (lhs));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
466 bool rhs_in_macro = from_macro_expansion_at (EXPR_LOCATION (rhs));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
467 if (lhs_in_macro || rhs_in_macro)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
468 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
469 /* Don't warn if exactly one is from a macro. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
470 if (!(lhs_in_macro && rhs_in_macro))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
471 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
472
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
473 /* If both are in a macro, only warn if they're spelled the same. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
474 if (!spelled_the_same_p (EXPR_LOCATION (lhs), EXPR_LOCATION (rhs)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
475 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
476 }
111
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 warn_tautological_bitwise_comparison (loc, code, lhs, rhs);
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 /* We do not warn for constants because they are typical of macro
kono
parents:
diff changeset
481 expansions that test for features, sizeof, and similar. */
kono
parents:
diff changeset
482 if (CONSTANT_CLASS_P (fold_for_warn (lhs))
kono
parents:
diff changeset
483 || CONSTANT_CLASS_P (fold_for_warn (rhs)))
kono
parents:
diff changeset
484 return;
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 /* Don't warn for e.g.
kono
parents:
diff changeset
487 HOST_WIDE_INT n;
kono
parents:
diff changeset
488 ...
kono
parents:
diff changeset
489 if (n == (long) n) ...
kono
parents:
diff changeset
490 */
kono
parents:
diff changeset
491 if ((CONVERT_EXPR_P (lhs) || TREE_CODE (lhs) == NON_LVALUE_EXPR)
kono
parents:
diff changeset
492 || (CONVERT_EXPR_P (rhs) || TREE_CODE (rhs) == NON_LVALUE_EXPR))
kono
parents:
diff changeset
493 return;
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 /* Don't warn if either LHS or RHS has an IEEE floating-point type.
kono
parents:
diff changeset
496 It could be a NaN, and NaN never compares equal to anything, even
kono
parents:
diff changeset
497 itself. */
kono
parents:
diff changeset
498 if (FLOAT_TYPE_P (TREE_TYPE (lhs)) || FLOAT_TYPE_P (TREE_TYPE (rhs)))
kono
parents:
diff changeset
499 return;
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 if (operand_equal_p (lhs, rhs, 0))
kono
parents:
diff changeset
502 {
kono
parents:
diff changeset
503 /* Don't warn about array references with constant indices;
kono
parents:
diff changeset
504 these are likely to come from a macro. */
kono
parents:
diff changeset
505 if (walk_tree_without_duplicates (&lhs, find_array_ref_with_const_idx_r,
kono
parents:
diff changeset
506 NULL))
kono
parents:
diff changeset
507 return;
kono
parents:
diff changeset
508 const bool always_true = (code == EQ_EXPR || code == LE_EXPR
kono
parents:
diff changeset
509 || code == GE_EXPR || code == UNLE_EXPR
kono
parents:
diff changeset
510 || code == UNGE_EXPR || code == UNEQ_EXPR);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 binary_op_rich_location richloc (loc, lhs, rhs, false);
111
kono
parents:
diff changeset
512 if (always_true)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
513 warning_at (&richloc, OPT_Wtautological_compare,
111
kono
parents:
diff changeset
514 "self-comparison always evaluates to true");
kono
parents:
diff changeset
515 else
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516 warning_at (&richloc, OPT_Wtautological_compare,
111
kono
parents:
diff changeset
517 "self-comparison always evaluates to false");
kono
parents:
diff changeset
518 }
kono
parents:
diff changeset
519 }
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521 /* Return true iff EXPR only contains boolean operands, or comparisons. */
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 static bool
kono
parents:
diff changeset
524 expr_has_boolean_operands_p (tree expr)
kono
parents:
diff changeset
525 {
kono
parents:
diff changeset
526 STRIP_NOPS (expr);
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 if (CONVERT_EXPR_P (expr))
kono
parents:
diff changeset
529 return bool_promoted_to_int_p (expr);
kono
parents:
diff changeset
530 else if (UNARY_CLASS_P (expr))
kono
parents:
diff changeset
531 return expr_has_boolean_operands_p (TREE_OPERAND (expr, 0));
kono
parents:
diff changeset
532 else if (BINARY_CLASS_P (expr))
kono
parents:
diff changeset
533 return (expr_has_boolean_operands_p (TREE_OPERAND (expr, 0))
kono
parents:
diff changeset
534 && expr_has_boolean_operands_p (TREE_OPERAND (expr, 1)));
kono
parents:
diff changeset
535 else if (COMPARISON_CLASS_P (expr))
kono
parents:
diff changeset
536 return true;
kono
parents:
diff changeset
537 else
kono
parents:
diff changeset
538 return false;
kono
parents:
diff changeset
539 }
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 /* Warn about logical not used on the left hand side operand of a comparison.
kono
parents:
diff changeset
542 This function assumes that the LHS is inside of TRUTH_NOT_EXPR.
kono
parents:
diff changeset
543 Do not warn if RHS is of a boolean type, a logical operator, or
kono
parents:
diff changeset
544 a comparison. */
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 void
kono
parents:
diff changeset
547 warn_logical_not_parentheses (location_t location, enum tree_code code,
kono
parents:
diff changeset
548 tree lhs, tree rhs)
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 if (TREE_CODE_CLASS (code) != tcc_comparison
kono
parents:
diff changeset
551 || TREE_TYPE (rhs) == NULL_TREE
kono
parents:
diff changeset
552 || TREE_CODE (TREE_TYPE (rhs)) == BOOLEAN_TYPE
kono
parents:
diff changeset
553 || truth_value_p (TREE_CODE (rhs)))
kono
parents:
diff changeset
554 return;
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 /* Don't warn for expression like !x == ~(bool1 | bool2). */
kono
parents:
diff changeset
557 if (expr_has_boolean_operands_p (rhs))
kono
parents:
diff changeset
558 return;
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 /* Don't warn for !x == 0 or !y != 0, those are equivalent to
kono
parents:
diff changeset
561 !(x == 0) or !(y != 0). */
kono
parents:
diff changeset
562 if ((code == EQ_EXPR || code == NE_EXPR)
kono
parents:
diff changeset
563 && integer_zerop (rhs))
kono
parents:
diff changeset
564 return;
kono
parents:
diff changeset
565
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
566 auto_diagnostic_group d;
111
kono
parents:
diff changeset
567 if (warning_at (location, OPT_Wlogical_not_parentheses,
kono
parents:
diff changeset
568 "logical not is only applied to the left hand side of "
kono
parents:
diff changeset
569 "comparison")
kono
parents:
diff changeset
570 && EXPR_HAS_LOCATION (lhs))
kono
parents:
diff changeset
571 {
kono
parents:
diff changeset
572 location_t lhs_loc = EXPR_LOCATION (lhs);
kono
parents:
diff changeset
573 rich_location richloc (line_table, lhs_loc);
kono
parents:
diff changeset
574 richloc.add_fixit_insert_before (lhs_loc, "(");
kono
parents:
diff changeset
575 richloc.add_fixit_insert_after (lhs_loc, ")");
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
576 inform (&richloc, "add parentheses around left hand side "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
577 "expression to silence this warning");
111
kono
parents:
diff changeset
578 }
kono
parents:
diff changeset
579 }
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 /* Warn if EXP contains any computations whose results are not used.
kono
parents:
diff changeset
582 Return true if a warning is printed; false otherwise. LOCUS is the
kono
parents:
diff changeset
583 (potential) location of the expression. */
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 bool
kono
parents:
diff changeset
586 warn_if_unused_value (const_tree exp, location_t locus)
kono
parents:
diff changeset
587 {
kono
parents:
diff changeset
588 restart:
kono
parents:
diff changeset
589 if (TREE_USED (exp) || TREE_NO_WARNING (exp))
kono
parents:
diff changeset
590 return false;
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 /* Don't warn about void constructs. This includes casting to void,
kono
parents:
diff changeset
593 void function calls, and statement expressions with a final cast
kono
parents:
diff changeset
594 to void. */
kono
parents:
diff changeset
595 if (VOID_TYPE_P (TREE_TYPE (exp)))
kono
parents:
diff changeset
596 return false;
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 if (EXPR_HAS_LOCATION (exp))
kono
parents:
diff changeset
599 locus = EXPR_LOCATION (exp);
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 switch (TREE_CODE (exp))
kono
parents:
diff changeset
602 {
kono
parents:
diff changeset
603 case PREINCREMENT_EXPR:
kono
parents:
diff changeset
604 case POSTINCREMENT_EXPR:
kono
parents:
diff changeset
605 case PREDECREMENT_EXPR:
kono
parents:
diff changeset
606 case POSTDECREMENT_EXPR:
kono
parents:
diff changeset
607 case MODIFY_EXPR:
kono
parents:
diff changeset
608 case INIT_EXPR:
kono
parents:
diff changeset
609 case TARGET_EXPR:
kono
parents:
diff changeset
610 case CALL_EXPR:
kono
parents:
diff changeset
611 case TRY_CATCH_EXPR:
kono
parents:
diff changeset
612 case EXIT_EXPR:
kono
parents:
diff changeset
613 case VA_ARG_EXPR:
kono
parents:
diff changeset
614 return false;
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 case BIND_EXPR:
kono
parents:
diff changeset
617 /* For a binding, warn if no side effect within it. */
kono
parents:
diff changeset
618 exp = BIND_EXPR_BODY (exp);
kono
parents:
diff changeset
619 goto restart;
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 case SAVE_EXPR:
kono
parents:
diff changeset
622 case NON_LVALUE_EXPR:
kono
parents:
diff changeset
623 case NOP_EXPR:
kono
parents:
diff changeset
624 exp = TREE_OPERAND (exp, 0);
kono
parents:
diff changeset
625 goto restart;
kono
parents:
diff changeset
626
kono
parents:
diff changeset
627 case TRUTH_ORIF_EXPR:
kono
parents:
diff changeset
628 case TRUTH_ANDIF_EXPR:
kono
parents:
diff changeset
629 /* In && or ||, warn if 2nd operand has no side effect. */
kono
parents:
diff changeset
630 exp = TREE_OPERAND (exp, 1);
kono
parents:
diff changeset
631 goto restart;
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 case COMPOUND_EXPR:
kono
parents:
diff changeset
634 if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus))
kono
parents:
diff changeset
635 return true;
kono
parents:
diff changeset
636 /* Let people do `(foo (), 0)' without a warning. */
kono
parents:
diff changeset
637 if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))
kono
parents:
diff changeset
638 return false;
kono
parents:
diff changeset
639 exp = TREE_OPERAND (exp, 1);
kono
parents:
diff changeset
640 goto restart;
kono
parents:
diff changeset
641
kono
parents:
diff changeset
642 case COND_EXPR:
kono
parents:
diff changeset
643 /* If this is an expression with side effects, don't warn; this
kono
parents:
diff changeset
644 case commonly appears in macro expansions. */
kono
parents:
diff changeset
645 if (TREE_SIDE_EFFECTS (exp))
kono
parents:
diff changeset
646 return false;
kono
parents:
diff changeset
647 goto warn;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 case INDIRECT_REF:
kono
parents:
diff changeset
650 /* Don't warn about automatic dereferencing of references, since
kono
parents:
diff changeset
651 the user cannot control it. */
kono
parents:
diff changeset
652 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
kono
parents:
diff changeset
653 {
kono
parents:
diff changeset
654 exp = TREE_OPERAND (exp, 0);
kono
parents:
diff changeset
655 goto restart;
kono
parents:
diff changeset
656 }
kono
parents:
diff changeset
657 /* Fall through. */
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 default:
kono
parents:
diff changeset
660 /* Referencing a volatile value is a side effect, so don't warn. */
kono
parents:
diff changeset
661 if ((DECL_P (exp) || REFERENCE_CLASS_P (exp))
kono
parents:
diff changeset
662 && TREE_THIS_VOLATILE (exp))
kono
parents:
diff changeset
663 return false;
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 /* If this is an expression which has no operands, there is no value
kono
parents:
diff changeset
666 to be unused. There are no such language-independent codes,
kono
parents:
diff changeset
667 but front ends may define such. */
kono
parents:
diff changeset
668 if (EXPRESSION_CLASS_P (exp) && TREE_OPERAND_LENGTH (exp) == 0)
kono
parents:
diff changeset
669 return false;
kono
parents:
diff changeset
670
kono
parents:
diff changeset
671 warn:
kono
parents:
diff changeset
672 return warning_at (locus, OPT_Wunused_value, "value computed is not used");
kono
parents:
diff changeset
673 }
kono
parents:
diff changeset
674 }
kono
parents:
diff changeset
675
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
676 /* Print a warning about casts that might indicate violation of strict
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
677 aliasing rules if -Wstrict-aliasing is used and strict aliasing
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
678 mode is in effect. LOC is the location of the expression being
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
679 cast, EXPR might be from inside it. TYPE is the type we're casting
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
680 to. */
111
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 bool
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
683 strict_aliasing_warning (location_t loc, tree type, tree expr)
111
kono
parents:
diff changeset
684 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
685 if (loc == UNKNOWN_LOCATION)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
686 loc = input_location;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
687
111
kono
parents:
diff changeset
688 /* Strip pointer conversion chains and get to the correct original type. */
kono
parents:
diff changeset
689 STRIP_NOPS (expr);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
690 tree otype = TREE_TYPE (expr);
111
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 if (!(flag_strict_aliasing
kono
parents:
diff changeset
693 && POINTER_TYPE_P (type)
kono
parents:
diff changeset
694 && POINTER_TYPE_P (otype)
kono
parents:
diff changeset
695 && !VOID_TYPE_P (TREE_TYPE (type)))
kono
parents:
diff changeset
696 /* If the type we are casting to is a ref-all pointer
kono
parents:
diff changeset
697 dereferencing it is always valid. */
kono
parents:
diff changeset
698 || TYPE_REF_CAN_ALIAS_ALL (type))
kono
parents:
diff changeset
699 return false;
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR
kono
parents:
diff changeset
702 && (DECL_P (TREE_OPERAND (expr, 0))
kono
parents:
diff changeset
703 || handled_component_p (TREE_OPERAND (expr, 0))))
kono
parents:
diff changeset
704 {
kono
parents:
diff changeset
705 /* Casting the address of an object to non void pointer. Warn
kono
parents:
diff changeset
706 if the cast breaks type based aliasing. */
kono
parents:
diff changeset
707 if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2)
kono
parents:
diff changeset
708 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
709 warning_at (loc, OPT_Wstrict_aliasing,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
710 "type-punning to incomplete type "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
711 "might break strict-aliasing rules");
111
kono
parents:
diff changeset
712 return true;
kono
parents:
diff changeset
713 }
kono
parents:
diff changeset
714 else
kono
parents:
diff changeset
715 {
kono
parents:
diff changeset
716 /* warn_strict_aliasing >= 3. This includes the default (3).
kono
parents:
diff changeset
717 Only warn if the cast is dereferenced immediately. */
kono
parents:
diff changeset
718 alias_set_type set1
kono
parents:
diff changeset
719 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
kono
parents:
diff changeset
720 alias_set_type set2 = get_alias_set (TREE_TYPE (type));
kono
parents:
diff changeset
721
kono
parents:
diff changeset
722 if (set2 != 0
kono
parents:
diff changeset
723 && set1 != set2
kono
parents:
diff changeset
724 && !alias_set_subset_of (set2, set1)
kono
parents:
diff changeset
725 && !alias_sets_conflict_p (set1, set2))
kono
parents:
diff changeset
726 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
727 warning_at (loc, OPT_Wstrict_aliasing,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
728 "dereferencing type-punned "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
729 "pointer will break strict-aliasing rules");
111
kono
parents:
diff changeset
730 return true;
kono
parents:
diff changeset
731 }
kono
parents:
diff changeset
732 else if (warn_strict_aliasing == 2
kono
parents:
diff changeset
733 && !alias_sets_must_conflict_p (set1, set2))
kono
parents:
diff changeset
734 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
735 warning_at (loc, OPT_Wstrict_aliasing,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
736 "dereferencing type-punned "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
737 "pointer might break strict-aliasing rules");
111
kono
parents:
diff changeset
738 return true;
kono
parents:
diff changeset
739 }
kono
parents:
diff changeset
740 }
kono
parents:
diff changeset
741 }
kono
parents:
diff changeset
742 else if ((warn_strict_aliasing == 1) && !VOID_TYPE_P (TREE_TYPE (otype)))
kono
parents:
diff changeset
743 {
kono
parents:
diff changeset
744 /* At this level, warn for any conversions, even if an address is
kono
parents:
diff changeset
745 not taken in the same statement. This will likely produce many
kono
parents:
diff changeset
746 false positives, but could be useful to pinpoint problems that
kono
parents:
diff changeset
747 are not revealed at higher levels. */
kono
parents:
diff changeset
748 alias_set_type set1 = get_alias_set (TREE_TYPE (otype));
kono
parents:
diff changeset
749 alias_set_type set2 = get_alias_set (TREE_TYPE (type));
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
750 if (!COMPLETE_TYPE_P (TREE_TYPE (type))
111
kono
parents:
diff changeset
751 || !alias_sets_must_conflict_p (set1, set2))
kono
parents:
diff changeset
752 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
753 warning_at (loc, OPT_Wstrict_aliasing,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
754 "dereferencing type-punned "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
755 "pointer might break strict-aliasing rules");
111
kono
parents:
diff changeset
756 return true;
kono
parents:
diff changeset
757 }
kono
parents:
diff changeset
758 }
kono
parents:
diff changeset
759
kono
parents:
diff changeset
760 return false;
kono
parents:
diff changeset
761 }
kono
parents:
diff changeset
762
kono
parents:
diff changeset
763 /* Warn about memset (&a, 0, sizeof (&a)); and similar mistakes with
kono
parents:
diff changeset
764 sizeof as last operand of certain builtins. */
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 void
kono
parents:
diff changeset
767 sizeof_pointer_memaccess_warning (location_t *sizeof_arg_loc, tree callee,
kono
parents:
diff changeset
768 vec<tree, va_gc> *params, tree *sizeof_arg,
kono
parents:
diff changeset
769 bool (*comp_types) (tree, tree))
kono
parents:
diff changeset
770 {
kono
parents:
diff changeset
771 tree type, dest = NULL_TREE, src = NULL_TREE, tem;
kono
parents:
diff changeset
772 bool strop = false, cmp = false;
kono
parents:
diff changeset
773 unsigned int idx = ~0;
kono
parents:
diff changeset
774 location_t loc;
kono
parents:
diff changeset
775
kono
parents:
diff changeset
776 if (TREE_CODE (callee) != FUNCTION_DECL
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
777 || !fndecl_built_in_p (callee, BUILT_IN_NORMAL)
111
kono
parents:
diff changeset
778 || vec_safe_length (params) <= 1)
kono
parents:
diff changeset
779 return;
kono
parents:
diff changeset
780
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
781 enum built_in_function fncode = DECL_FUNCTION_CODE (callee);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
782 switch (fncode)
111
kono
parents:
diff changeset
783 {
kono
parents:
diff changeset
784 case BUILT_IN_STRNCMP:
kono
parents:
diff changeset
785 case BUILT_IN_STRNCASECMP:
kono
parents:
diff changeset
786 cmp = true;
kono
parents:
diff changeset
787 /* FALLTHRU */
kono
parents:
diff changeset
788 case BUILT_IN_STRNCPY:
kono
parents:
diff changeset
789 case BUILT_IN_STRNCPY_CHK:
kono
parents:
diff changeset
790 case BUILT_IN_STRNCAT:
kono
parents:
diff changeset
791 case BUILT_IN_STRNCAT_CHK:
kono
parents:
diff changeset
792 case BUILT_IN_STPNCPY:
kono
parents:
diff changeset
793 case BUILT_IN_STPNCPY_CHK:
kono
parents:
diff changeset
794 strop = true;
kono
parents:
diff changeset
795 /* FALLTHRU */
kono
parents:
diff changeset
796 case BUILT_IN_MEMCPY:
kono
parents:
diff changeset
797 case BUILT_IN_MEMCPY_CHK:
kono
parents:
diff changeset
798 case BUILT_IN_MEMMOVE:
kono
parents:
diff changeset
799 case BUILT_IN_MEMMOVE_CHK:
kono
parents:
diff changeset
800 if (params->length () < 3)
kono
parents:
diff changeset
801 return;
kono
parents:
diff changeset
802 src = (*params)[1];
kono
parents:
diff changeset
803 dest = (*params)[0];
kono
parents:
diff changeset
804 idx = 2;
kono
parents:
diff changeset
805 break;
kono
parents:
diff changeset
806 case BUILT_IN_BCOPY:
kono
parents:
diff changeset
807 if (params->length () < 3)
kono
parents:
diff changeset
808 return;
kono
parents:
diff changeset
809 src = (*params)[0];
kono
parents:
diff changeset
810 dest = (*params)[1];
kono
parents:
diff changeset
811 idx = 2;
kono
parents:
diff changeset
812 break;
kono
parents:
diff changeset
813 case BUILT_IN_MEMCMP:
kono
parents:
diff changeset
814 case BUILT_IN_BCMP:
kono
parents:
diff changeset
815 if (params->length () < 3)
kono
parents:
diff changeset
816 return;
kono
parents:
diff changeset
817 src = (*params)[1];
kono
parents:
diff changeset
818 dest = (*params)[0];
kono
parents:
diff changeset
819 idx = 2;
kono
parents:
diff changeset
820 cmp = true;
kono
parents:
diff changeset
821 break;
kono
parents:
diff changeset
822 case BUILT_IN_MEMSET:
kono
parents:
diff changeset
823 case BUILT_IN_MEMSET_CHK:
kono
parents:
diff changeset
824 if (params->length () < 3)
kono
parents:
diff changeset
825 return;
kono
parents:
diff changeset
826 dest = (*params)[0];
kono
parents:
diff changeset
827 idx = 2;
kono
parents:
diff changeset
828 break;
kono
parents:
diff changeset
829 case BUILT_IN_BZERO:
kono
parents:
diff changeset
830 dest = (*params)[0];
kono
parents:
diff changeset
831 idx = 1;
kono
parents:
diff changeset
832 break;
kono
parents:
diff changeset
833 case BUILT_IN_STRNDUP:
kono
parents:
diff changeset
834 src = (*params)[0];
kono
parents:
diff changeset
835 strop = true;
kono
parents:
diff changeset
836 idx = 1;
kono
parents:
diff changeset
837 break;
kono
parents:
diff changeset
838 case BUILT_IN_MEMCHR:
kono
parents:
diff changeset
839 if (params->length () < 3)
kono
parents:
diff changeset
840 return;
kono
parents:
diff changeset
841 src = (*params)[0];
kono
parents:
diff changeset
842 idx = 2;
kono
parents:
diff changeset
843 break;
kono
parents:
diff changeset
844 case BUILT_IN_SNPRINTF:
kono
parents:
diff changeset
845 case BUILT_IN_SNPRINTF_CHK:
kono
parents:
diff changeset
846 case BUILT_IN_VSNPRINTF:
kono
parents:
diff changeset
847 case BUILT_IN_VSNPRINTF_CHK:
kono
parents:
diff changeset
848 dest = (*params)[0];
kono
parents:
diff changeset
849 idx = 1;
kono
parents:
diff changeset
850 strop = true;
kono
parents:
diff changeset
851 break;
kono
parents:
diff changeset
852 default:
kono
parents:
diff changeset
853 break;
kono
parents:
diff changeset
854 }
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 if (idx >= 3)
kono
parents:
diff changeset
857 return;
kono
parents:
diff changeset
858
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
859 /* Use error_operand_p to detect non-error arguments with an error
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
860 type that the C++ front-end constructs. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
861 if (error_operand_p (src)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
862 || error_operand_p (dest)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
863 || !sizeof_arg[idx]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
864 || error_operand_p (sizeof_arg[idx]))
111
kono
parents:
diff changeset
865 return;
kono
parents:
diff changeset
866
kono
parents:
diff changeset
867 type = TYPE_P (sizeof_arg[idx])
kono
parents:
diff changeset
868 ? sizeof_arg[idx] : TREE_TYPE (sizeof_arg[idx]);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
869
111
kono
parents:
diff changeset
870 if (!POINTER_TYPE_P (type))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
871 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
872 /* The argument type may be an array. Diagnose bounded string
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
873 copy functions that specify the bound in terms of the source
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
874 argument rather than the destination unless they are equal
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
875 to one another. Handle constant sizes and also try to handle
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
876 sizeof expressions involving VLAs. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
877 if (strop && !cmp && fncode != BUILT_IN_STRNDUP && src)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
878 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
879 tem = tree_strip_nop_conversions (src);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
880 if (TREE_CODE (tem) == ADDR_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
881 tem = TREE_OPERAND (tem, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
882
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
883 /* Avoid diagnosing sizeof SRC when SRC is declared with
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
884 attribute nonstring. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
885 tree dummy;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
886 if (get_attr_nonstring_decl (tem, &dummy))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
887 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
888
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
889 tree d = tree_strip_nop_conversions (dest);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
890 if (TREE_CODE (d) == ADDR_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
891 d = TREE_OPERAND (d, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
892
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
893 tree dstsz = TYPE_SIZE_UNIT (TREE_TYPE (d));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
894 tree srcsz = TYPE_SIZE_UNIT (TREE_TYPE (tem));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
895
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
896 if ((!dstsz
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
897 || !srcsz
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
898 || !operand_equal_p (dstsz, srcsz, OEP_LEXICOGRAPHIC))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
899 && operand_equal_p (tem, sizeof_arg[idx], OEP_ADDRESS_OF))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
900 warning_at (sizeof_arg_loc[idx], OPT_Wsizeof_pointer_memaccess,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
901 "argument to %<sizeof%> in %qD call is the same "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
902 "expression as the source; did you mean to use "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
903 "the size of the destination?",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
904 callee);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
906
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
907 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
908 }
111
kono
parents:
diff changeset
909
kono
parents:
diff changeset
910 if (dest
kono
parents:
diff changeset
911 && (tem = tree_strip_nop_conversions (dest))
kono
parents:
diff changeset
912 && POINTER_TYPE_P (TREE_TYPE (tem))
kono
parents:
diff changeset
913 && comp_types (TREE_TYPE (TREE_TYPE (tem)), type))
kono
parents:
diff changeset
914 return;
kono
parents:
diff changeset
915
kono
parents:
diff changeset
916 if (src
kono
parents:
diff changeset
917 && (tem = tree_strip_nop_conversions (src))
kono
parents:
diff changeset
918 && POINTER_TYPE_P (TREE_TYPE (tem))
kono
parents:
diff changeset
919 && comp_types (TREE_TYPE (TREE_TYPE (tem)), type))
kono
parents:
diff changeset
920 return;
kono
parents:
diff changeset
921
kono
parents:
diff changeset
922 loc = sizeof_arg_loc[idx];
kono
parents:
diff changeset
923
kono
parents:
diff changeset
924 if (dest && !cmp)
kono
parents:
diff changeset
925 {
kono
parents:
diff changeset
926 if (!TYPE_P (sizeof_arg[idx])
kono
parents:
diff changeset
927 && operand_equal_p (dest, sizeof_arg[idx], 0)
kono
parents:
diff changeset
928 && comp_types (TREE_TYPE (dest), type))
kono
parents:
diff changeset
929 {
kono
parents:
diff changeset
930 if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
kono
parents:
diff changeset
931 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
932 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
933 "expression as the destination; did you mean to "
kono
parents:
diff changeset
934 "remove the addressof?", callee);
kono
parents:
diff changeset
935 else if ((TYPE_PRECISION (TREE_TYPE (type))
kono
parents:
diff changeset
936 == TYPE_PRECISION (char_type_node))
kono
parents:
diff changeset
937 || strop)
kono
parents:
diff changeset
938 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
939 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
940 "expression as the destination; did you mean to "
kono
parents:
diff changeset
941 "provide an explicit length?", callee);
kono
parents:
diff changeset
942 else
kono
parents:
diff changeset
943 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
944 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
945 "expression as the destination; did you mean to "
kono
parents:
diff changeset
946 "dereference it?", callee);
kono
parents:
diff changeset
947 return;
kono
parents:
diff changeset
948 }
kono
parents:
diff changeset
949
kono
parents:
diff changeset
950 if (POINTER_TYPE_P (TREE_TYPE (dest))
kono
parents:
diff changeset
951 && !strop
kono
parents:
diff changeset
952 && comp_types (TREE_TYPE (dest), type)
kono
parents:
diff changeset
953 && !VOID_TYPE_P (TREE_TYPE (type)))
kono
parents:
diff changeset
954 {
kono
parents:
diff changeset
955 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
956 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
957 "pointer type %qT as the destination; expected %qT "
kono
parents:
diff changeset
958 "or an explicit length", callee, TREE_TYPE (dest),
kono
parents:
diff changeset
959 TREE_TYPE (TREE_TYPE (dest)));
kono
parents:
diff changeset
960 return;
kono
parents:
diff changeset
961 }
kono
parents:
diff changeset
962 }
kono
parents:
diff changeset
963
kono
parents:
diff changeset
964 if (src && !cmp)
kono
parents:
diff changeset
965 {
kono
parents:
diff changeset
966 if (!TYPE_P (sizeof_arg[idx])
kono
parents:
diff changeset
967 && operand_equal_p (src, sizeof_arg[idx], 0)
kono
parents:
diff changeset
968 && comp_types (TREE_TYPE (src), type))
kono
parents:
diff changeset
969 {
kono
parents:
diff changeset
970 if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
kono
parents:
diff changeset
971 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
972 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
973 "expression as the source; did you mean to "
kono
parents:
diff changeset
974 "remove the addressof?", callee);
kono
parents:
diff changeset
975 else if ((TYPE_PRECISION (TREE_TYPE (type))
kono
parents:
diff changeset
976 == TYPE_PRECISION (char_type_node))
kono
parents:
diff changeset
977 || strop)
kono
parents:
diff changeset
978 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
979 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
980 "expression as the source; did you mean to "
kono
parents:
diff changeset
981 "provide an explicit length?", callee);
kono
parents:
diff changeset
982 else
kono
parents:
diff changeset
983 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
984 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
985 "expression as the source; did you mean to "
kono
parents:
diff changeset
986 "dereference it?", callee);
kono
parents:
diff changeset
987 return;
kono
parents:
diff changeset
988 }
kono
parents:
diff changeset
989
kono
parents:
diff changeset
990 if (POINTER_TYPE_P (TREE_TYPE (src))
kono
parents:
diff changeset
991 && !strop
kono
parents:
diff changeset
992 && comp_types (TREE_TYPE (src), type)
kono
parents:
diff changeset
993 && !VOID_TYPE_P (TREE_TYPE (type)))
kono
parents:
diff changeset
994 {
kono
parents:
diff changeset
995 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
996 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
997 "pointer type %qT as the source; expected %qT "
kono
parents:
diff changeset
998 "or an explicit length", callee, TREE_TYPE (src),
kono
parents:
diff changeset
999 TREE_TYPE (TREE_TYPE (src)));
kono
parents:
diff changeset
1000 return;
kono
parents:
diff changeset
1001 }
kono
parents:
diff changeset
1002 }
kono
parents:
diff changeset
1003
kono
parents:
diff changeset
1004 if (dest)
kono
parents:
diff changeset
1005 {
kono
parents:
diff changeset
1006 if (!TYPE_P (sizeof_arg[idx])
kono
parents:
diff changeset
1007 && operand_equal_p (dest, sizeof_arg[idx], 0)
kono
parents:
diff changeset
1008 && comp_types (TREE_TYPE (dest), type))
kono
parents:
diff changeset
1009 {
kono
parents:
diff changeset
1010 if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
kono
parents:
diff changeset
1011 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1012 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1013 "expression as the first source; did you mean to "
kono
parents:
diff changeset
1014 "remove the addressof?", callee);
kono
parents:
diff changeset
1015 else if ((TYPE_PRECISION (TREE_TYPE (type))
kono
parents:
diff changeset
1016 == TYPE_PRECISION (char_type_node))
kono
parents:
diff changeset
1017 || strop)
kono
parents:
diff changeset
1018 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1019 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1020 "expression as the first source; did you mean to "
kono
parents:
diff changeset
1021 "provide an explicit length?", callee);
kono
parents:
diff changeset
1022 else
kono
parents:
diff changeset
1023 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1024 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1025 "expression as the first source; did you mean to "
kono
parents:
diff changeset
1026 "dereference it?", callee);
kono
parents:
diff changeset
1027 return;
kono
parents:
diff changeset
1028 }
kono
parents:
diff changeset
1029
kono
parents:
diff changeset
1030 if (POINTER_TYPE_P (TREE_TYPE (dest))
kono
parents:
diff changeset
1031 && !strop
kono
parents:
diff changeset
1032 && comp_types (TREE_TYPE (dest), type)
kono
parents:
diff changeset
1033 && !VOID_TYPE_P (TREE_TYPE (type)))
kono
parents:
diff changeset
1034 {
kono
parents:
diff changeset
1035 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1036 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1037 "pointer type %qT as the first source; expected %qT "
kono
parents:
diff changeset
1038 "or an explicit length", callee, TREE_TYPE (dest),
kono
parents:
diff changeset
1039 TREE_TYPE (TREE_TYPE (dest)));
kono
parents:
diff changeset
1040 return;
kono
parents:
diff changeset
1041 }
kono
parents:
diff changeset
1042 }
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 if (src)
kono
parents:
diff changeset
1045 {
kono
parents:
diff changeset
1046 if (!TYPE_P (sizeof_arg[idx])
kono
parents:
diff changeset
1047 && operand_equal_p (src, sizeof_arg[idx], 0)
kono
parents:
diff changeset
1048 && comp_types (TREE_TYPE (src), type))
kono
parents:
diff changeset
1049 {
kono
parents:
diff changeset
1050 if (TREE_CODE (sizeof_arg[idx]) == ADDR_EXPR && !strop)
kono
parents:
diff changeset
1051 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1052 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1053 "expression as the second source; did you mean to "
kono
parents:
diff changeset
1054 "remove the addressof?", callee);
kono
parents:
diff changeset
1055 else if ((TYPE_PRECISION (TREE_TYPE (type))
kono
parents:
diff changeset
1056 == TYPE_PRECISION (char_type_node))
kono
parents:
diff changeset
1057 || strop)
kono
parents:
diff changeset
1058 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1059 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1060 "expression as the second source; did you mean to "
kono
parents:
diff changeset
1061 "provide an explicit length?", callee);
kono
parents:
diff changeset
1062 else
kono
parents:
diff changeset
1063 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1064 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1065 "expression as the second source; did you mean to "
kono
parents:
diff changeset
1066 "dereference it?", callee);
kono
parents:
diff changeset
1067 return;
kono
parents:
diff changeset
1068 }
kono
parents:
diff changeset
1069
kono
parents:
diff changeset
1070 if (POINTER_TYPE_P (TREE_TYPE (src))
kono
parents:
diff changeset
1071 && !strop
kono
parents:
diff changeset
1072 && comp_types (TREE_TYPE (src), type)
kono
parents:
diff changeset
1073 && !VOID_TYPE_P (TREE_TYPE (type)))
kono
parents:
diff changeset
1074 {
kono
parents:
diff changeset
1075 warning_at (loc, OPT_Wsizeof_pointer_memaccess,
kono
parents:
diff changeset
1076 "argument to %<sizeof%> in %qD call is the same "
kono
parents:
diff changeset
1077 "pointer type %qT as the second source; expected %qT "
kono
parents:
diff changeset
1078 "or an explicit length", callee, TREE_TYPE (src),
kono
parents:
diff changeset
1079 TREE_TYPE (TREE_TYPE (src)));
kono
parents:
diff changeset
1080 return;
kono
parents:
diff changeset
1081 }
kono
parents:
diff changeset
1082 }
kono
parents:
diff changeset
1083
kono
parents:
diff changeset
1084 }
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086 /* Warn for unlikely, improbable, or stupid DECL declarations
kono
parents:
diff changeset
1087 of `main'. */
kono
parents:
diff changeset
1088
kono
parents:
diff changeset
1089 void
kono
parents:
diff changeset
1090 check_main_parameter_types (tree decl)
kono
parents:
diff changeset
1091 {
kono
parents:
diff changeset
1092 function_args_iterator iter;
kono
parents:
diff changeset
1093 tree type;
kono
parents:
diff changeset
1094 int argct = 0;
kono
parents:
diff changeset
1095
kono
parents:
diff changeset
1096 FOREACH_FUNCTION_ARGS (TREE_TYPE (decl), type, iter)
kono
parents:
diff changeset
1097 {
kono
parents:
diff changeset
1098 /* XXX void_type_node belies the abstraction. */
kono
parents:
diff changeset
1099 if (type == void_type_node || type == error_mark_node)
kono
parents:
diff changeset
1100 break;
kono
parents:
diff changeset
1101
kono
parents:
diff changeset
1102 tree t = type;
kono
parents:
diff changeset
1103 if (TYPE_ATOMIC (t))
kono
parents:
diff changeset
1104 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1105 "%<_Atomic%>-qualified parameter type %qT of %q+D",
kono
parents:
diff changeset
1106 type, decl);
kono
parents:
diff changeset
1107 while (POINTER_TYPE_P (t))
kono
parents:
diff changeset
1108 {
kono
parents:
diff changeset
1109 t = TREE_TYPE (t);
kono
parents:
diff changeset
1110 if (TYPE_ATOMIC (t))
kono
parents:
diff changeset
1111 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1112 "%<_Atomic%>-qualified parameter type %qT of %q+D",
kono
parents:
diff changeset
1113 type, decl);
kono
parents:
diff changeset
1114 }
kono
parents:
diff changeset
1115
kono
parents:
diff changeset
1116 ++argct;
kono
parents:
diff changeset
1117 switch (argct)
kono
parents:
diff changeset
1118 {
kono
parents:
diff changeset
1119 case 1:
kono
parents:
diff changeset
1120 if (TYPE_MAIN_VARIANT (type) != integer_type_node)
kono
parents:
diff changeset
1121 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1122 "first argument of %q+D should be %<int%>", decl);
kono
parents:
diff changeset
1123 break;
kono
parents:
diff changeset
1124
kono
parents:
diff changeset
1125 case 2:
kono
parents:
diff changeset
1126 if (TREE_CODE (type) != POINTER_TYPE
kono
parents:
diff changeset
1127 || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
kono
parents:
diff changeset
1128 || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
kono
parents:
diff changeset
1129 != char_type_node))
kono
parents:
diff changeset
1130 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1131 "second argument of %q+D should be %<char **%>", decl);
kono
parents:
diff changeset
1132 break;
kono
parents:
diff changeset
1133
kono
parents:
diff changeset
1134 case 3:
kono
parents:
diff changeset
1135 if (TREE_CODE (type) != POINTER_TYPE
kono
parents:
diff changeset
1136 || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
kono
parents:
diff changeset
1137 || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
kono
parents:
diff changeset
1138 != char_type_node))
kono
parents:
diff changeset
1139 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1140 "third argument of %q+D should probably be "
kono
parents:
diff changeset
1141 "%<char **%>", decl);
kono
parents:
diff changeset
1142 break;
kono
parents:
diff changeset
1143 }
kono
parents:
diff changeset
1144 }
kono
parents:
diff changeset
1145
kono
parents:
diff changeset
1146 /* It is intentional that this message does not mention the third
kono
parents:
diff changeset
1147 argument because it's only mentioned in an appendix of the
kono
parents:
diff changeset
1148 standard. */
kono
parents:
diff changeset
1149 if (argct > 0 && (argct < 2 || argct > 3))
kono
parents:
diff changeset
1150 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1151 "%q+D takes only zero or two arguments", decl);
kono
parents:
diff changeset
1152
kono
parents:
diff changeset
1153 if (stdarg_p (TREE_TYPE (decl)))
kono
parents:
diff changeset
1154 pedwarn (input_location, OPT_Wmain,
kono
parents:
diff changeset
1155 "%q+D declared as variadic function", decl);
kono
parents:
diff changeset
1156 }
kono
parents:
diff changeset
1157
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1158 /* Warns and returns true if the conversion of EXPR to TYPE may alter a value.
111
kono
parents:
diff changeset
1159 This is a helper function for warnings_for_convert_and_check. */
kono
parents:
diff changeset
1160
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1161 static bool
111
kono
parents:
diff changeset
1162 conversion_warning (location_t loc, tree type, tree expr, tree result)
kono
parents:
diff changeset
1163 {
kono
parents:
diff changeset
1164 tree expr_type = TREE_TYPE (expr);
kono
parents:
diff changeset
1165 enum conversion_safety conversion_kind;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1166 int arith_ops = 0;
111
kono
parents:
diff changeset
1167
kono
parents:
diff changeset
1168 if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1169 return false;
111
kono
parents:
diff changeset
1170
kono
parents:
diff changeset
1171 /* This may happen, because for LHS op= RHS we preevaluate
kono
parents:
diff changeset
1172 RHS and create C_MAYBE_CONST_EXPR <SAVE_EXPR <RHS>>, which
kono
parents:
diff changeset
1173 means we could no longer see the code of the EXPR. */
kono
parents:
diff changeset
1174 if (TREE_CODE (expr) == C_MAYBE_CONST_EXPR)
kono
parents:
diff changeset
1175 expr = C_MAYBE_CONST_EXPR_EXPR (expr);
kono
parents:
diff changeset
1176 if (TREE_CODE (expr) == SAVE_EXPR)
kono
parents:
diff changeset
1177 expr = TREE_OPERAND (expr, 0);
kono
parents:
diff changeset
1178
kono
parents:
diff changeset
1179 switch (TREE_CODE (expr))
kono
parents:
diff changeset
1180 {
kono
parents:
diff changeset
1181 case EQ_EXPR:
kono
parents:
diff changeset
1182 case NE_EXPR:
kono
parents:
diff changeset
1183 case LE_EXPR:
kono
parents:
diff changeset
1184 case GE_EXPR:
kono
parents:
diff changeset
1185 case LT_EXPR:
kono
parents:
diff changeset
1186 case GT_EXPR:
kono
parents:
diff changeset
1187 case TRUTH_ANDIF_EXPR:
kono
parents:
diff changeset
1188 case TRUTH_ORIF_EXPR:
kono
parents:
diff changeset
1189 case TRUTH_AND_EXPR:
kono
parents:
diff changeset
1190 case TRUTH_OR_EXPR:
kono
parents:
diff changeset
1191 case TRUTH_XOR_EXPR:
kono
parents:
diff changeset
1192 case TRUTH_NOT_EXPR:
kono
parents:
diff changeset
1193 /* Conversion from boolean to a signed:1 bit-field (which only
kono
parents:
diff changeset
1194 can hold the values 0 and -1) doesn't lose information - but
kono
parents:
diff changeset
1195 it does change the value. */
kono
parents:
diff changeset
1196 if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
kono
parents:
diff changeset
1197 warning_at (loc, OPT_Wconversion,
kono
parents:
diff changeset
1198 "conversion to %qT from boolean expression", type);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1199 return true;
111
kono
parents:
diff changeset
1200
kono
parents:
diff changeset
1201 case REAL_CST:
kono
parents:
diff changeset
1202 case INTEGER_CST:
kono
parents:
diff changeset
1203 case COMPLEX_CST:
kono
parents:
diff changeset
1204 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1205 conversion_kind = unsafe_conversion_p (type, expr, result, true);
111
kono
parents:
diff changeset
1206 int warnopt;
kono
parents:
diff changeset
1207 if (conversion_kind == UNSAFE_REAL)
kono
parents:
diff changeset
1208 warnopt = OPT_Wfloat_conversion;
kono
parents:
diff changeset
1209 else if (conversion_kind)
kono
parents:
diff changeset
1210 warnopt = OPT_Wconversion;
kono
parents:
diff changeset
1211 else
kono
parents:
diff changeset
1212 break;
kono
parents:
diff changeset
1213
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1214 if (conversion_kind == UNSAFE_SIGN)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1215 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1216 bool cstresult
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1217 = (result
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1218 && TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1219 if (TYPE_UNSIGNED (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1220 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1221 if (cstresult)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1222 warning_at (loc, OPT_Wsign_conversion,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1223 "unsigned conversion from %qT to %qT "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1224 "changes value from %qE to %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1225 expr_type, type, expr, result);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1226 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1227 warning_at (loc, OPT_Wsign_conversion,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1228 "unsigned conversion from %qT to %qT "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1229 "changes the value of %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1230 expr_type, type, expr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1231 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1232 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1233 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1234 if (cstresult)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1235 warning_at (loc, OPT_Wsign_conversion,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1236 "signed conversion from %qT to %qT changes "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1237 "value from %qE to %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1238 expr_type, type, expr, result);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1239 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1240 warning_at (loc, OPT_Wsign_conversion,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1241 "signed conversion from %qT to %qT changes "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1242 "the value of %qE",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1243 expr_type, type, expr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1244 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1245 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1246 else if (TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant)
111
kono
parents:
diff changeset
1247 warning_at (loc, warnopt,
kono
parents:
diff changeset
1248 "conversion from %qT to %qT changes value from %qE to %qE",
kono
parents:
diff changeset
1249 expr_type, type, expr, result);
kono
parents:
diff changeset
1250 else
kono
parents:
diff changeset
1251 warning_at (loc, warnopt,
kono
parents:
diff changeset
1252 "conversion from %qT to %qT changes the value of %qE",
kono
parents:
diff changeset
1253 expr_type, type, expr);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1254 return true;
111
kono
parents:
diff changeset
1255 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1256
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1257 case PLUS_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1258 case MINUS_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1259 case MULT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1260 case MAX_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1261 case MIN_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1262 case TRUNC_MOD_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1263 case FLOOR_MOD_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1264 case TRUNC_DIV_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1265 case FLOOR_DIV_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1266 case CEIL_DIV_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1267 case EXACT_DIV_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1268 case RDIV_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1269 arith_ops = 2;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1270 goto default_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1271
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1272 case PREDECREMENT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1273 case PREINCREMENT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1274 case POSTDECREMENT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1275 case POSTINCREMENT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1276 case LSHIFT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1277 case RSHIFT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1278 case FIX_TRUNC_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1279 case NON_LVALUE_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1280 case NEGATE_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1281 case BIT_NOT_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1282 arith_ops = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1283 goto default_;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1284
111
kono
parents:
diff changeset
1285 case COND_EXPR:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1286 {
111
kono
parents:
diff changeset
1287 /* In case of COND_EXPR, we do not care about the type of
kono
parents:
diff changeset
1288 COND_EXPR, only about the conversion of each operand. */
kono
parents:
diff changeset
1289 tree op1 = TREE_OPERAND (expr, 1);
kono
parents:
diff changeset
1290 tree op2 = TREE_OPERAND (expr, 2);
kono
parents:
diff changeset
1291
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1292 return (conversion_warning (loc, type, op1, result)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1293 || conversion_warning (loc, type, op2, result));
111
kono
parents:
diff changeset
1294 }
kono
parents:
diff changeset
1295
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1296 default_:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1297 default:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1298 conversion_kind = unsafe_conversion_p (type, expr, result, true);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1299 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1300 int warnopt;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1301 if (conversion_kind == UNSAFE_REAL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1302 warnopt = OPT_Wfloat_conversion;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1303 else if (conversion_kind == UNSAFE_SIGN)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1304 warnopt = OPT_Wsign_conversion;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1305 else if (conversion_kind)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1306 warnopt = OPT_Wconversion;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1307 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1308 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1309
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1310 if (arith_ops
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1311 && global_dc->option_enabled (warnopt,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1312 global_dc->lang_mask,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1313 global_dc->option_state))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1314 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1315 for (int i = 0; i < arith_ops; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1316 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1317 tree op = TREE_OPERAND (expr, i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1318 /* Avoid -Wsign-conversion for (unsigned)(x + (-1)). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1319 if (TREE_CODE (expr) == PLUS_EXPR && i == 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1320 && INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1321 && TREE_CODE (op) == INTEGER_CST
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1322 && tree_int_cst_sgn (op) < 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1323 op = fold_build1 (NEGATE_EXPR, TREE_TYPE (op), op);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1324 tree opr = convert (type, op);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1325 if (unsafe_conversion_p (type, op, opr, true))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1326 goto op_unsafe;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1327 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1328 /* The operands seem safe, we might still want to warn if
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1329 -Warith-conversion. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1330 warnopt = OPT_Warith_conversion;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1331 op_unsafe:;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1332 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1333
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1334 if (conversion_kind == UNSAFE_SIGN)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1335 warning_at (loc, warnopt, "conversion to %qT from %qT "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1336 "may change the sign of the result",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1337 type, expr_type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1338 else if (conversion_kind == UNSAFE_IMAGINARY)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1339 warning_at (loc, warnopt,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1340 "conversion from %qT to %qT discards imaginary component",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1341 expr_type, type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1342 else
111
kono
parents:
diff changeset
1343 warning_at (loc, warnopt,
kono
parents:
diff changeset
1344 "conversion from %qT to %qT may change value",
kono
parents:
diff changeset
1345 expr_type, type);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1346 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1347 }
111
kono
parents:
diff changeset
1348 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1349 return false;
111
kono
parents:
diff changeset
1350 }
kono
parents:
diff changeset
1351
kono
parents:
diff changeset
1352 /* Produce warnings after a conversion. RESULT is the result of
kono
parents:
diff changeset
1353 converting EXPR to TYPE. This is a helper function for
kono
parents:
diff changeset
1354 convert_and_check and cp_convert_and_check. */
kono
parents:
diff changeset
1355
kono
parents:
diff changeset
1356 void
kono
parents:
diff changeset
1357 warnings_for_convert_and_check (location_t loc, tree type, tree expr,
kono
parents:
diff changeset
1358 tree result)
kono
parents:
diff changeset
1359 {
kono
parents:
diff changeset
1360 loc = expansion_point_location_if_in_system_header (loc);
kono
parents:
diff changeset
1361
kono
parents:
diff changeset
1362 bool cst = TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant;
kono
parents:
diff changeset
1363
kono
parents:
diff changeset
1364 tree exprtype = TREE_TYPE (expr);
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 if (TREE_CODE (expr) == INTEGER_CST
kono
parents:
diff changeset
1367 && (TREE_CODE (type) == INTEGER_TYPE
kono
parents:
diff changeset
1368 || TREE_CODE (type) == ENUMERAL_TYPE)
kono
parents:
diff changeset
1369 && !int_fits_type_p (expr, type))
kono
parents:
diff changeset
1370 {
kono
parents:
diff changeset
1371 /* Do not diagnose overflow in a constant expression merely
kono
parents:
diff changeset
1372 because a conversion overflowed. */
kono
parents:
diff changeset
1373 if (TREE_OVERFLOW (result))
kono
parents:
diff changeset
1374 TREE_OVERFLOW (result) = TREE_OVERFLOW (expr);
kono
parents:
diff changeset
1375
kono
parents:
diff changeset
1376 if (TYPE_UNSIGNED (type))
kono
parents:
diff changeset
1377 {
kono
parents:
diff changeset
1378 /* This detects cases like converting -129 or 256 to
kono
parents:
diff changeset
1379 unsigned char. */
kono
parents:
diff changeset
1380 if (!int_fits_type_p (expr, c_common_signed_type (type)))
kono
parents:
diff changeset
1381 {
kono
parents:
diff changeset
1382 if (cst)
kono
parents:
diff changeset
1383 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1384 (TYPE_UNSIGNED (exprtype)
kono
parents:
diff changeset
1385 ? G_("conversion from %qT to %qT "
kono
parents:
diff changeset
1386 "changes value from %qE to %qE")
kono
parents:
diff changeset
1387 : G_("unsigned conversion from %qT to %qT "
kono
parents:
diff changeset
1388 "changes value from %qE to %qE")),
kono
parents:
diff changeset
1389 exprtype, type, expr, result);
kono
parents:
diff changeset
1390 else
kono
parents:
diff changeset
1391 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1392 (TYPE_UNSIGNED (exprtype)
kono
parents:
diff changeset
1393 ? G_("conversion from %qT to %qT "
kono
parents:
diff changeset
1394 "changes the value of %qE")
kono
parents:
diff changeset
1395 : G_("unsigned conversion from %qT to %qT "
kono
parents:
diff changeset
1396 "changes the value of %qE")),
kono
parents:
diff changeset
1397 exprtype, type, expr);
kono
parents:
diff changeset
1398 }
kono
parents:
diff changeset
1399 else
kono
parents:
diff changeset
1400 conversion_warning (loc, type, expr, result);
kono
parents:
diff changeset
1401 }
kono
parents:
diff changeset
1402 else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
kono
parents:
diff changeset
1403 {
kono
parents:
diff changeset
1404 if (cst)
kono
parents:
diff changeset
1405 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1406 "overflow in conversion from %qT to %qT "
kono
parents:
diff changeset
1407 "changes value from %qE to %qE",
kono
parents:
diff changeset
1408 exprtype, type, expr, result);
kono
parents:
diff changeset
1409 else
kono
parents:
diff changeset
1410 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1411 "overflow in conversion from %qT to %qT "
kono
parents:
diff changeset
1412 "changes the value of %qE",
kono
parents:
diff changeset
1413 exprtype, type, expr);
kono
parents:
diff changeset
1414 }
kono
parents:
diff changeset
1415 /* No warning for converting 0x80000000 to int. */
kono
parents:
diff changeset
1416 else if (pedantic
kono
parents:
diff changeset
1417 && (TREE_CODE (exprtype) != INTEGER_TYPE
kono
parents:
diff changeset
1418 || TYPE_PRECISION (exprtype)
kono
parents:
diff changeset
1419 != TYPE_PRECISION (type)))
kono
parents:
diff changeset
1420 {
kono
parents:
diff changeset
1421 if (cst)
kono
parents:
diff changeset
1422 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1423 "overflow in conversion from %qT to %qT "
kono
parents:
diff changeset
1424 "changes value from %qE to %qE",
kono
parents:
diff changeset
1425 exprtype, type, expr, result);
kono
parents:
diff changeset
1426 else
kono
parents:
diff changeset
1427 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1428 "overflow in conversion from %qT to %qT "
kono
parents:
diff changeset
1429 "changes the value of %qE",
kono
parents:
diff changeset
1430 exprtype, type, expr);
kono
parents:
diff changeset
1431 }
kono
parents:
diff changeset
1432 else
kono
parents:
diff changeset
1433 conversion_warning (loc, type, expr, result);
kono
parents:
diff changeset
1434 }
kono
parents:
diff changeset
1435 else if ((TREE_CODE (result) == INTEGER_CST
kono
parents:
diff changeset
1436 || TREE_CODE (result) == FIXED_CST) && TREE_OVERFLOW (result))
kono
parents:
diff changeset
1437 {
kono
parents:
diff changeset
1438 if (cst)
kono
parents:
diff changeset
1439 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1440 "overflow in conversion from %qT to %qT "
kono
parents:
diff changeset
1441 "changes value from %qE to %qE",
kono
parents:
diff changeset
1442 exprtype, type, expr, result);
kono
parents:
diff changeset
1443 else
kono
parents:
diff changeset
1444 warning_at (loc, OPT_Woverflow,
kono
parents:
diff changeset
1445 "overflow in conversion from %qT to %qT "
kono
parents:
diff changeset
1446 "changes the value of %qE",
kono
parents:
diff changeset
1447 exprtype, type, expr);
kono
parents:
diff changeset
1448 }
kono
parents:
diff changeset
1449 else
kono
parents:
diff changeset
1450 conversion_warning (loc, type, expr, result);
kono
parents:
diff changeset
1451 }
kono
parents:
diff changeset
1452
kono
parents:
diff changeset
1453 /* Subroutines of c_do_switch_warnings, called via splay_tree_foreach.
kono
parents:
diff changeset
1454 Used to verify that case values match up with enumerator values. */
kono
parents:
diff changeset
1455
kono
parents:
diff changeset
1456 static void
kono
parents:
diff changeset
1457 match_case_to_enum_1 (tree key, tree type, tree label)
kono
parents:
diff changeset
1458 {
kono
parents:
diff changeset
1459 /* Avoid warning about enums that have no enumerators. */
kono
parents:
diff changeset
1460 if (TYPE_VALUES (type) == NULL_TREE)
kono
parents:
diff changeset
1461 return;
kono
parents:
diff changeset
1462
kono
parents:
diff changeset
1463 char buf[WIDE_INT_PRINT_BUFFER_SIZE];
kono
parents:
diff changeset
1464
kono
parents:
diff changeset
1465 if (tree_fits_uhwi_p (key))
kono
parents:
diff changeset
1466 print_dec (wi::to_wide (key), buf, UNSIGNED);
kono
parents:
diff changeset
1467 else if (tree_fits_shwi_p (key))
kono
parents:
diff changeset
1468 print_dec (wi::to_wide (key), buf, SIGNED);
kono
parents:
diff changeset
1469 else
kono
parents:
diff changeset
1470 print_hex (wi::to_wide (key), buf);
kono
parents:
diff changeset
1471
kono
parents:
diff changeset
1472 if (TYPE_NAME (type) == NULL_TREE)
kono
parents:
diff changeset
1473 warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
kono
parents:
diff changeset
1474 warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
kono
parents:
diff changeset
1475 "case value %qs not in enumerated type",
kono
parents:
diff changeset
1476 buf);
kono
parents:
diff changeset
1477 else
kono
parents:
diff changeset
1478 warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
kono
parents:
diff changeset
1479 warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
kono
parents:
diff changeset
1480 "case value %qs not in enumerated type %qT",
kono
parents:
diff changeset
1481 buf, type);
kono
parents:
diff changeset
1482 }
kono
parents:
diff changeset
1483
kono
parents:
diff changeset
1484 /* Subroutine of c_do_switch_warnings, called via splay_tree_foreach.
kono
parents:
diff changeset
1485 Used to verify that case values match up with enumerator values. */
kono
parents:
diff changeset
1486
kono
parents:
diff changeset
1487 static int
kono
parents:
diff changeset
1488 match_case_to_enum (splay_tree_node node, void *data)
kono
parents:
diff changeset
1489 {
kono
parents:
diff changeset
1490 tree label = (tree) node->value;
kono
parents:
diff changeset
1491 tree type = (tree) data;
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493 /* Skip default case. */
kono
parents:
diff changeset
1494 if (!CASE_LOW (label))
kono
parents:
diff changeset
1495 return 0;
kono
parents:
diff changeset
1496
kono
parents:
diff changeset
1497 /* If CASE_LOW_SEEN is not set, that means CASE_LOW did not appear
kono
parents:
diff changeset
1498 when we did our enum->case scan. Reset our scratch bit after. */
kono
parents:
diff changeset
1499 if (!CASE_LOW_SEEN (label))
kono
parents:
diff changeset
1500 match_case_to_enum_1 (CASE_LOW (label), type, label);
kono
parents:
diff changeset
1501 else
kono
parents:
diff changeset
1502 CASE_LOW_SEEN (label) = 0;
kono
parents:
diff changeset
1503
kono
parents:
diff changeset
1504 /* If CASE_HIGH is non-null, we have a range. If CASE_HIGH_SEEN is
kono
parents:
diff changeset
1505 not set, that means that CASE_HIGH did not appear when we did our
kono
parents:
diff changeset
1506 enum->case scan. Reset our scratch bit after. */
kono
parents:
diff changeset
1507 if (CASE_HIGH (label))
kono
parents:
diff changeset
1508 {
kono
parents:
diff changeset
1509 if (!CASE_HIGH_SEEN (label))
kono
parents:
diff changeset
1510 match_case_to_enum_1 (CASE_HIGH (label), type, label);
kono
parents:
diff changeset
1511 else
kono
parents:
diff changeset
1512 CASE_HIGH_SEEN (label) = 0;
kono
parents:
diff changeset
1513 }
kono
parents:
diff changeset
1514
kono
parents:
diff changeset
1515 return 0;
kono
parents:
diff changeset
1516 }
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 /* Handle -Wswitch*. Called from the front end after parsing the
kono
parents:
diff changeset
1519 switch construct. */
kono
parents:
diff changeset
1520 /* ??? Should probably be somewhere generic, since other languages
kono
parents:
diff changeset
1521 besides C and C++ would want this. At the moment, however, C/C++
kono
parents:
diff changeset
1522 are the only tree-ssa languages that support enumerations at all,
kono
parents:
diff changeset
1523 so the point is moot. */
kono
parents:
diff changeset
1524
kono
parents:
diff changeset
1525 void
kono
parents:
diff changeset
1526 c_do_switch_warnings (splay_tree cases, location_t switch_location,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1527 tree type, tree cond, bool bool_cond_p)
111
kono
parents:
diff changeset
1528 {
kono
parents:
diff changeset
1529 splay_tree_node default_node;
kono
parents:
diff changeset
1530 splay_tree_node node;
kono
parents:
diff changeset
1531 tree chain;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1532 bool outside_range_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1533
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1534 if (type != error_mark_node
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1535 && type != TREE_TYPE (cond)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1536 && INTEGRAL_TYPE_P (type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1537 && INTEGRAL_TYPE_P (TREE_TYPE (cond))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1538 && (!tree_int_cst_equal (TYPE_MIN_VALUE (type),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1539 TYPE_MIN_VALUE (TREE_TYPE (cond)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1540 || !tree_int_cst_equal (TYPE_MAX_VALUE (type),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1541 TYPE_MAX_VALUE (TREE_TYPE (cond)))))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1542 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1543 tree min_value = TYPE_MIN_VALUE (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1544 tree max_value = TYPE_MAX_VALUE (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1545
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1546 node = splay_tree_predecessor (cases, (splay_tree_key) min_value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1547 if (node && node->key)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1548 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1549 outside_range_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1550 /* There is at least one case smaller than TYPE's minimum value.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1551 NODE itself could be still a range overlapping the valid values,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1552 but any predecessors thereof except the default case will be
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1553 completely outside of range. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1554 if (CASE_HIGH ((tree) node->value)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1555 && tree_int_cst_compare (CASE_HIGH ((tree) node->value),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1556 min_value) >= 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1557 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1558 location_t loc = EXPR_LOCATION ((tree) node->value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1559 warning_at (loc, OPT_Wswitch_outside_range,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1560 "lower value in case label range less than minimum"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1561 " value for type");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1562 CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1563 min_value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1564 node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1565 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1566 /* All the following ones are completely outside of range. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1567 do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1568 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1569 node = splay_tree_predecessor (cases,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1570 (splay_tree_key) min_value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1571 if (node == NULL || !node->key)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1572 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1573 location_t loc = EXPR_LOCATION ((tree) node->value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1574 warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1575 " less than minimum value for type");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1576 splay_tree_remove (cases, node->key);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1577 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1578 while (1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1579 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1580 node = splay_tree_lookup (cases, (splay_tree_key) max_value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1581 if (node == NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1582 node = splay_tree_predecessor (cases, (splay_tree_key) max_value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1583 /* Handle a single node that might partially overlap the range. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1584 if (node
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1585 && node->key
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1586 && CASE_HIGH ((tree) node->value)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1587 && tree_int_cst_compare (CASE_HIGH ((tree) node->value),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1588 max_value) > 0)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1589 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1590 location_t loc = EXPR_LOCATION ((tree) node->value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1591 warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1592 " label range exceeds maximum value for type");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1593 CASE_HIGH ((tree) node->value)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1594 = convert (TREE_TYPE (cond), max_value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1595 outside_range_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1596 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1597 /* And any nodes that are completely outside of the range. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1598 while ((node = splay_tree_successor (cases,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1599 (splay_tree_key) max_value))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1600 != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1601 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1602 location_t loc = EXPR_LOCATION ((tree) node->value);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1603 warning_at (loc, OPT_Wswitch_outside_range,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1604 "case label value exceeds maximum value for type");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1605 splay_tree_remove (cases, node->key);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1606 outside_range_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1607 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1608 }
111
kono
parents:
diff changeset
1609
kono
parents:
diff changeset
1610 if (!warn_switch && !warn_switch_enum && !warn_switch_default
kono
parents:
diff changeset
1611 && !warn_switch_bool)
kono
parents:
diff changeset
1612 return;
kono
parents:
diff changeset
1613
kono
parents:
diff changeset
1614 default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
kono
parents:
diff changeset
1615 if (!default_node)
kono
parents:
diff changeset
1616 warning_at (switch_location, OPT_Wswitch_default,
kono
parents:
diff changeset
1617 "switch missing default case");
kono
parents:
diff changeset
1618
kono
parents:
diff changeset
1619 /* There are certain cases where -Wswitch-bool warnings aren't
kono
parents:
diff changeset
1620 desirable, such as
kono
parents:
diff changeset
1621 switch (boolean)
kono
parents:
diff changeset
1622 {
kono
parents:
diff changeset
1623 case true: ...
kono
parents:
diff changeset
1624 case false: ...
kono
parents:
diff changeset
1625 }
kono
parents:
diff changeset
1626 so be careful here. */
kono
parents:
diff changeset
1627 if (warn_switch_bool && bool_cond_p)
kono
parents:
diff changeset
1628 {
kono
parents:
diff changeset
1629 splay_tree_node min_node;
kono
parents:
diff changeset
1630 /* If there's a default node, it's also the value with the minimal
kono
parents:
diff changeset
1631 key. So look at the penultimate key (if any). */
kono
parents:
diff changeset
1632 if (default_node)
kono
parents:
diff changeset
1633 min_node = splay_tree_successor (cases, (splay_tree_key) NULL);
kono
parents:
diff changeset
1634 else
kono
parents:
diff changeset
1635 min_node = splay_tree_min (cases);
kono
parents:
diff changeset
1636 tree min = min_node ? (tree) min_node->key : NULL_TREE;
kono
parents:
diff changeset
1637
kono
parents:
diff changeset
1638 splay_tree_node max_node = splay_tree_max (cases);
kono
parents:
diff changeset
1639 /* This might be a case range, so look at the value with the
kono
parents:
diff changeset
1640 maximal key and then check CASE_HIGH. */
kono
parents:
diff changeset
1641 tree max = max_node ? (tree) max_node->value : NULL_TREE;
kono
parents:
diff changeset
1642 if (max)
kono
parents:
diff changeset
1643 max = CASE_HIGH (max) ? CASE_HIGH (max) : CASE_LOW (max);
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 /* If there's a case value > 1 or < 0, that is outside bool
kono
parents:
diff changeset
1646 range, warn. */
kono
parents:
diff changeset
1647 if (outside_range_p
kono
parents:
diff changeset
1648 || (max && wi::gts_p (wi::to_wide (max), 1))
kono
parents:
diff changeset
1649 || (min && wi::lts_p (wi::to_wide (min), 0))
kono
parents:
diff changeset
1650 /* And handle the
kono
parents:
diff changeset
1651 switch (boolean)
kono
parents:
diff changeset
1652 {
kono
parents:
diff changeset
1653 case true: ...
kono
parents:
diff changeset
1654 case false: ...
kono
parents:
diff changeset
1655 default: ...
kono
parents:
diff changeset
1656 }
kono
parents:
diff changeset
1657 case, where we want to warn. */
kono
parents:
diff changeset
1658 || (default_node
kono
parents:
diff changeset
1659 && max && wi::to_wide (max) == 1
kono
parents:
diff changeset
1660 && min && wi::to_wide (min) == 0))
kono
parents:
diff changeset
1661 warning_at (switch_location, OPT_Wswitch_bool,
kono
parents:
diff changeset
1662 "switch condition has boolean value");
kono
parents:
diff changeset
1663 }
kono
parents:
diff changeset
1664
kono
parents:
diff changeset
1665 /* From here on, we only care about enumerated types. */
kono
parents:
diff changeset
1666 if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
kono
parents:
diff changeset
1667 return;
kono
parents:
diff changeset
1668
kono
parents:
diff changeset
1669 /* From here on, we only care about -Wswitch and -Wswitch-enum. */
kono
parents:
diff changeset
1670 if (!warn_switch_enum && !warn_switch)
kono
parents:
diff changeset
1671 return;
kono
parents:
diff changeset
1672
kono
parents:
diff changeset
1673 /* Check the cases. Warn about case values which are not members of
kono
parents:
diff changeset
1674 the enumerated type. For -Wswitch-enum, or for -Wswitch when
kono
parents:
diff changeset
1675 there is no default case, check that exactly all enumeration
kono
parents:
diff changeset
1676 literals are covered by the cases. */
kono
parents:
diff changeset
1677
kono
parents:
diff changeset
1678 /* Clearing COND if it is not an integer constant simplifies
kono
parents:
diff changeset
1679 the tests inside the loop below. */
kono
parents:
diff changeset
1680 if (TREE_CODE (cond) != INTEGER_CST)
kono
parents:
diff changeset
1681 cond = NULL_TREE;
kono
parents:
diff changeset
1682
kono
parents:
diff changeset
1683 /* The time complexity here is O(N*lg(N)) worst case, but for the
kono
parents:
diff changeset
1684 common case of monotonically increasing enumerators, it is
kono
parents:
diff changeset
1685 O(N), since the nature of the splay tree will keep the next
kono
parents:
diff changeset
1686 element adjacent to the root at all times. */
kono
parents:
diff changeset
1687
kono
parents:
diff changeset
1688 for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
kono
parents:
diff changeset
1689 {
kono
parents:
diff changeset
1690 tree value = TREE_VALUE (chain);
kono
parents:
diff changeset
1691 if (TREE_CODE (value) == CONST_DECL)
kono
parents:
diff changeset
1692 value = DECL_INITIAL (value);
kono
parents:
diff changeset
1693 node = splay_tree_lookup (cases, (splay_tree_key) value);
kono
parents:
diff changeset
1694 if (node)
kono
parents:
diff changeset
1695 {
kono
parents:
diff changeset
1696 /* Mark the CASE_LOW part of the case entry as seen. */
kono
parents:
diff changeset
1697 tree label = (tree) node->value;
kono
parents:
diff changeset
1698 CASE_LOW_SEEN (label) = 1;
kono
parents:
diff changeset
1699 continue;
kono
parents:
diff changeset
1700 }
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 /* Even though there wasn't an exact match, there might be a
kono
parents:
diff changeset
1703 case range which includes the enumerator's value. */
kono
parents:
diff changeset
1704 node = splay_tree_predecessor (cases, (splay_tree_key) value);
kono
parents:
diff changeset
1705 if (node && CASE_HIGH ((tree) node->value))
kono
parents:
diff changeset
1706 {
kono
parents:
diff changeset
1707 tree label = (tree) node->value;
kono
parents:
diff changeset
1708 int cmp = tree_int_cst_compare (CASE_HIGH (label), value);
kono
parents:
diff changeset
1709 if (cmp >= 0)
kono
parents:
diff changeset
1710 {
kono
parents:
diff changeset
1711 /* If we match the upper bound exactly, mark the CASE_HIGH
kono
parents:
diff changeset
1712 part of the case entry as seen. */
kono
parents:
diff changeset
1713 if (cmp == 0)
kono
parents:
diff changeset
1714 CASE_HIGH_SEEN (label) = 1;
kono
parents:
diff changeset
1715 continue;
kono
parents:
diff changeset
1716 }
kono
parents:
diff changeset
1717 }
kono
parents:
diff changeset
1718
kono
parents:
diff changeset
1719 /* We've now determined that this enumerated literal isn't
kono
parents:
diff changeset
1720 handled by the case labels of the switch statement. */
kono
parents:
diff changeset
1721
kono
parents:
diff changeset
1722 /* If the switch expression is a constant, we only really care
kono
parents:
diff changeset
1723 about whether that constant is handled by the switch. */
kono
parents:
diff changeset
1724 if (cond && tree_int_cst_compare (cond, value))
kono
parents:
diff changeset
1725 continue;
kono
parents:
diff changeset
1726
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1727 /* If the enumerator is defined in a system header and uses a reserved
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1728 name, then we continue to avoid throwing a warning. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1729 location_t loc = DECL_SOURCE_LOCATION
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1730 (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (type)));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1731 if (in_system_header_at (loc)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1732 && name_reserved_for_implementation_p
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1733 (IDENTIFIER_POINTER (TREE_PURPOSE (chain))))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1734 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1735
111
kono
parents:
diff changeset
1736 /* If there is a default_node, the only relevant option is
kono
parents:
diff changeset
1737 Wswitch-enum. Otherwise, if both are enabled then we prefer
kono
parents:
diff changeset
1738 to warn using -Wswitch because -Wswitch is enabled by -Wall
kono
parents:
diff changeset
1739 while -Wswitch-enum is explicit. */
kono
parents:
diff changeset
1740 warning_at (switch_location,
kono
parents:
diff changeset
1741 (default_node || !warn_switch
kono
parents:
diff changeset
1742 ? OPT_Wswitch_enum
kono
parents:
diff changeset
1743 : OPT_Wswitch),
kono
parents:
diff changeset
1744 "enumeration value %qE not handled in switch",
kono
parents:
diff changeset
1745 TREE_PURPOSE (chain));
kono
parents:
diff changeset
1746 }
kono
parents:
diff changeset
1747
kono
parents:
diff changeset
1748 /* Warn if there are case expressions that don't correspond to
kono
parents:
diff changeset
1749 enumerators. This can occur since C and C++ don't enforce
kono
parents:
diff changeset
1750 type-checking of assignments to enumeration variables.
kono
parents:
diff changeset
1751
kono
parents:
diff changeset
1752 The time complexity here is now always O(N) worst case, since
kono
parents:
diff changeset
1753 we should have marked both the lower bound and upper bound of
kono
parents:
diff changeset
1754 every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
kono
parents:
diff changeset
1755 above. This scan also resets those fields. */
kono
parents:
diff changeset
1756
kono
parents:
diff changeset
1757 splay_tree_foreach (cases, match_case_to_enum, type);
kono
parents:
diff changeset
1758 }
kono
parents:
diff changeset
1759
kono
parents:
diff changeset
1760 /* Warn for A ?: C expressions (with B omitted) where A is a boolean
kono
parents:
diff changeset
1761 expression, because B will always be true. */
kono
parents:
diff changeset
1762
kono
parents:
diff changeset
1763 void
kono
parents:
diff changeset
1764 warn_for_omitted_condop (location_t location, tree cond)
kono
parents:
diff changeset
1765 {
kono
parents:
diff changeset
1766 /* In C++ template declarations it can happen that the type is dependent
kono
parents:
diff changeset
1767 and not yet known, thus TREE_TYPE (cond) == NULL_TREE. */
kono
parents:
diff changeset
1768 if (truth_value_p (TREE_CODE (cond))
kono
parents:
diff changeset
1769 || (TREE_TYPE (cond) != NULL_TREE
kono
parents:
diff changeset
1770 && TREE_CODE (TREE_TYPE (cond)) == BOOLEAN_TYPE))
kono
parents:
diff changeset
1771 warning_at (location, OPT_Wparentheses,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1772 "the omitted middle operand in %<?:%> will always be %<true%>, "
111
kono
parents:
diff changeset
1773 "suggest explicit middle operand");
kono
parents:
diff changeset
1774 }
kono
parents:
diff changeset
1775
kono
parents:
diff changeset
1776 /* Give an error for storing into ARG, which is 'const'. USE indicates
kono
parents:
diff changeset
1777 how ARG was being used. */
kono
parents:
diff changeset
1778
kono
parents:
diff changeset
1779 void
kono
parents:
diff changeset
1780 readonly_error (location_t loc, tree arg, enum lvalue_use use)
kono
parents:
diff changeset
1781 {
kono
parents:
diff changeset
1782 gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
kono
parents:
diff changeset
1783 || use == lv_asm);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1784 STRIP_ANY_LOCATION_WRAPPER (arg);
111
kono
parents:
diff changeset
1785 /* Using this macro rather than (for example) arrays of messages
kono
parents:
diff changeset
1786 ensures that all the format strings are checked at compile
kono
parents:
diff changeset
1787 time. */
kono
parents:
diff changeset
1788 #define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \
kono
parents:
diff changeset
1789 : (use == lv_increment ? (I) \
kono
parents:
diff changeset
1790 : (use == lv_decrement ? (D) : (AS))))
kono
parents:
diff changeset
1791 if (TREE_CODE (arg) == COMPONENT_REF)
kono
parents:
diff changeset
1792 {
kono
parents:
diff changeset
1793 if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
kono
parents:
diff changeset
1794 error_at (loc, READONLY_MSG (G_("assignment of member "
kono
parents:
diff changeset
1795 "%qD in read-only object"),
kono
parents:
diff changeset
1796 G_("increment of member "
kono
parents:
diff changeset
1797 "%qD in read-only object"),
kono
parents:
diff changeset
1798 G_("decrement of member "
kono
parents:
diff changeset
1799 "%qD in read-only object"),
kono
parents:
diff changeset
1800 G_("member %qD in read-only object "
kono
parents:
diff changeset
1801 "used as %<asm%> output")),
kono
parents:
diff changeset
1802 TREE_OPERAND (arg, 1));
kono
parents:
diff changeset
1803 else
kono
parents:
diff changeset
1804 error_at (loc, READONLY_MSG (G_("assignment of read-only member %qD"),
kono
parents:
diff changeset
1805 G_("increment of read-only member %qD"),
kono
parents:
diff changeset
1806 G_("decrement of read-only member %qD"),
kono
parents:
diff changeset
1807 G_("read-only member %qD used as %<asm%> output")),
kono
parents:
diff changeset
1808 TREE_OPERAND (arg, 1));
kono
parents:
diff changeset
1809 }
kono
parents:
diff changeset
1810 else if (VAR_P (arg))
kono
parents:
diff changeset
1811 error_at (loc, READONLY_MSG (G_("assignment of read-only variable %qD"),
kono
parents:
diff changeset
1812 G_("increment of read-only variable %qD"),
kono
parents:
diff changeset
1813 G_("decrement of read-only variable %qD"),
kono
parents:
diff changeset
1814 G_("read-only variable %qD used as %<asm%> output")),
kono
parents:
diff changeset
1815 arg);
kono
parents:
diff changeset
1816 else if (TREE_CODE (arg) == PARM_DECL)
kono
parents:
diff changeset
1817 error_at (loc, READONLY_MSG (G_("assignment of read-only parameter %qD"),
kono
parents:
diff changeset
1818 G_("increment of read-only parameter %qD"),
kono
parents:
diff changeset
1819 G_("decrement of read-only parameter %qD"),
kono
parents:
diff changeset
1820 G_("read-only parameter %qD use as %<asm%> output")),
kono
parents:
diff changeset
1821 arg);
kono
parents:
diff changeset
1822 else if (TREE_CODE (arg) == RESULT_DECL)
kono
parents:
diff changeset
1823 {
kono
parents:
diff changeset
1824 gcc_assert (c_dialect_cxx ());
kono
parents:
diff changeset
1825 error_at (loc, READONLY_MSG (G_("assignment of "
kono
parents:
diff changeset
1826 "read-only named return value %qD"),
kono
parents:
diff changeset
1827 G_("increment of "
kono
parents:
diff changeset
1828 "read-only named return value %qD"),
kono
parents:
diff changeset
1829 G_("decrement of "
kono
parents:
diff changeset
1830 "read-only named return value %qD"),
kono
parents:
diff changeset
1831 G_("read-only named return value %qD "
kono
parents:
diff changeset
1832 "used as %<asm%>output")),
kono
parents:
diff changeset
1833 arg);
kono
parents:
diff changeset
1834 }
kono
parents:
diff changeset
1835 else if (TREE_CODE (arg) == FUNCTION_DECL)
kono
parents:
diff changeset
1836 error_at (loc, READONLY_MSG (G_("assignment of function %qD"),
kono
parents:
diff changeset
1837 G_("increment of function %qD"),
kono
parents:
diff changeset
1838 G_("decrement of function %qD"),
kono
parents:
diff changeset
1839 G_("function %qD used as %<asm%> output")),
kono
parents:
diff changeset
1840 arg);
kono
parents:
diff changeset
1841 else
kono
parents:
diff changeset
1842 error_at (loc, READONLY_MSG (G_("assignment of read-only location %qE"),
kono
parents:
diff changeset
1843 G_("increment of read-only location %qE"),
kono
parents:
diff changeset
1844 G_("decrement of read-only location %qE"),
kono
parents:
diff changeset
1845 G_("read-only location %qE used as %<asm%> output")),
kono
parents:
diff changeset
1846 arg);
kono
parents:
diff changeset
1847 }
kono
parents:
diff changeset
1848
kono
parents:
diff changeset
1849 /* Print an error message for an invalid lvalue. USE says
kono
parents:
diff changeset
1850 how the lvalue is being used and so selects the error message. LOC
kono
parents:
diff changeset
1851 is the location for the error. */
kono
parents:
diff changeset
1852
kono
parents:
diff changeset
1853 void
kono
parents:
diff changeset
1854 lvalue_error (location_t loc, enum lvalue_use use)
kono
parents:
diff changeset
1855 {
kono
parents:
diff changeset
1856 switch (use)
kono
parents:
diff changeset
1857 {
kono
parents:
diff changeset
1858 case lv_assign:
kono
parents:
diff changeset
1859 error_at (loc, "lvalue required as left operand of assignment");
kono
parents:
diff changeset
1860 break;
kono
parents:
diff changeset
1861 case lv_increment:
kono
parents:
diff changeset
1862 error_at (loc, "lvalue required as increment operand");
kono
parents:
diff changeset
1863 break;
kono
parents:
diff changeset
1864 case lv_decrement:
kono
parents:
diff changeset
1865 error_at (loc, "lvalue required as decrement operand");
kono
parents:
diff changeset
1866 break;
kono
parents:
diff changeset
1867 case lv_addressof:
kono
parents:
diff changeset
1868 error_at (loc, "lvalue required as unary %<&%> operand");
kono
parents:
diff changeset
1869 break;
kono
parents:
diff changeset
1870 case lv_asm:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1871 error_at (loc, "lvalue required in %<asm%> statement");
111
kono
parents:
diff changeset
1872 break;
kono
parents:
diff changeset
1873 default:
kono
parents:
diff changeset
1874 gcc_unreachable ();
kono
parents:
diff changeset
1875 }
kono
parents:
diff changeset
1876 }
kono
parents:
diff changeset
1877
kono
parents:
diff changeset
1878 /* Print an error message for an invalid indirection of type TYPE.
kono
parents:
diff changeset
1879 ERRSTRING is the name of the operator for the indirection. */
kono
parents:
diff changeset
1880
kono
parents:
diff changeset
1881 void
kono
parents:
diff changeset
1882 invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
kono
parents:
diff changeset
1883 {
kono
parents:
diff changeset
1884 switch (errstring)
kono
parents:
diff changeset
1885 {
kono
parents:
diff changeset
1886 case RO_NULL:
kono
parents:
diff changeset
1887 gcc_assert (c_dialect_cxx ());
kono
parents:
diff changeset
1888 error_at (loc, "invalid type argument (have %qT)", type);
kono
parents:
diff changeset
1889 break;
kono
parents:
diff changeset
1890 case RO_ARRAY_INDEXING:
kono
parents:
diff changeset
1891 error_at (loc,
kono
parents:
diff changeset
1892 "invalid type argument of array indexing (have %qT)",
kono
parents:
diff changeset
1893 type);
kono
parents:
diff changeset
1894 break;
kono
parents:
diff changeset
1895 case RO_UNARY_STAR:
kono
parents:
diff changeset
1896 error_at (loc,
kono
parents:
diff changeset
1897 "invalid type argument of unary %<*%> (have %qT)",
kono
parents:
diff changeset
1898 type);
kono
parents:
diff changeset
1899 break;
kono
parents:
diff changeset
1900 case RO_ARROW:
kono
parents:
diff changeset
1901 error_at (loc,
kono
parents:
diff changeset
1902 "invalid type argument of %<->%> (have %qT)",
kono
parents:
diff changeset
1903 type);
kono
parents:
diff changeset
1904 break;
kono
parents:
diff changeset
1905 case RO_ARROW_STAR:
kono
parents:
diff changeset
1906 error_at (loc,
kono
parents:
diff changeset
1907 "invalid type argument of %<->*%> (have %qT)",
kono
parents:
diff changeset
1908 type);
kono
parents:
diff changeset
1909 break;
kono
parents:
diff changeset
1910 case RO_IMPLICIT_CONVERSION:
kono
parents:
diff changeset
1911 error_at (loc,
kono
parents:
diff changeset
1912 "invalid type argument of implicit conversion (have %qT)",
kono
parents:
diff changeset
1913 type);
kono
parents:
diff changeset
1914 break;
kono
parents:
diff changeset
1915 default:
kono
parents:
diff changeset
1916 gcc_unreachable ();
kono
parents:
diff changeset
1917 }
kono
parents:
diff changeset
1918 }
kono
parents:
diff changeset
1919
kono
parents:
diff changeset
1920 /* Subscripting with type char is likely to lose on a machine where
kono
parents:
diff changeset
1921 chars are signed. So warn on any machine, but optionally. Don't
kono
parents:
diff changeset
1922 warn for unsigned char since that type is safe. Don't warn for
kono
parents:
diff changeset
1923 signed char because anyone who uses that must have done so
kono
parents:
diff changeset
1924 deliberately. Furthermore, we reduce the false positive load by
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1925 warning only for non-constant value of type char.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1926 LOC is the location of the subscripting expression. */
111
kono
parents:
diff changeset
1927
kono
parents:
diff changeset
1928 void
kono
parents:
diff changeset
1929 warn_array_subscript_with_type_char (location_t loc, tree index)
kono
parents:
diff changeset
1930 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1931 if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1932 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1933 /* If INDEX has a location, use it; otherwise use LOC (the location
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1934 of the subscripting expression as a whole). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1935 loc = EXPR_LOC_OR_LOC (index, loc);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1936 STRIP_ANY_LOCATION_WRAPPER (index);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1937 if (TREE_CODE (index) != INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1938 warning_at (loc, OPT_Wchar_subscripts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1939 "array subscript has type %<char%>");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1940 }
111
kono
parents:
diff changeset
1941 }
kono
parents:
diff changeset
1942
kono
parents:
diff changeset
1943 /* Implement -Wparentheses for the unexpected C precedence rules, to
kono
parents:
diff changeset
1944 cover cases like x + y << z which readers are likely to
kono
parents:
diff changeset
1945 misinterpret. We have seen an expression in which CODE is a binary
kono
parents:
diff changeset
1946 operator used to combine expressions ARG_LEFT and ARG_RIGHT, which
kono
parents:
diff changeset
1947 before folding had CODE_LEFT and CODE_RIGHT. CODE_LEFT and
kono
parents:
diff changeset
1948 CODE_RIGHT may be ERROR_MARK, which means that that side of the
kono
parents:
diff changeset
1949 expression was not formed using a binary or unary operator, or it
kono
parents:
diff changeset
1950 was enclosed in parentheses. */
kono
parents:
diff changeset
1951
kono
parents:
diff changeset
1952 void
kono
parents:
diff changeset
1953 warn_about_parentheses (location_t loc, enum tree_code code,
kono
parents:
diff changeset
1954 enum tree_code code_left, tree arg_left,
kono
parents:
diff changeset
1955 enum tree_code code_right, tree arg_right)
kono
parents:
diff changeset
1956 {
kono
parents:
diff changeset
1957 if (!warn_parentheses)
kono
parents:
diff changeset
1958 return;
kono
parents:
diff changeset
1959
kono
parents:
diff changeset
1960 /* This macro tests that the expression ARG with original tree code
kono
parents:
diff changeset
1961 CODE appears to be a boolean expression. or the result of folding a
kono
parents:
diff changeset
1962 boolean expression. */
kono
parents:
diff changeset
1963 #define APPEARS_TO_BE_BOOLEAN_EXPR_P(CODE, ARG) \
kono
parents:
diff changeset
1964 (truth_value_p (TREE_CODE (ARG)) \
kono
parents:
diff changeset
1965 || TREE_CODE (TREE_TYPE (ARG)) == BOOLEAN_TYPE \
kono
parents:
diff changeset
1966 /* Folding may create 0 or 1 integers from other expressions. */ \
kono
parents:
diff changeset
1967 || ((CODE) != INTEGER_CST \
kono
parents:
diff changeset
1968 && (integer_onep (ARG) || integer_zerop (ARG))))
kono
parents:
diff changeset
1969
kono
parents:
diff changeset
1970 switch (code)
kono
parents:
diff changeset
1971 {
kono
parents:
diff changeset
1972 case LSHIFT_EXPR:
kono
parents:
diff changeset
1973 if (code_left == PLUS_EXPR)
kono
parents:
diff changeset
1974 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1975 "suggest parentheses around %<+%> inside %<<<%>");
kono
parents:
diff changeset
1976 else if (code_right == PLUS_EXPR)
kono
parents:
diff changeset
1977 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1978 "suggest parentheses around %<+%> inside %<<<%>");
kono
parents:
diff changeset
1979 else if (code_left == MINUS_EXPR)
kono
parents:
diff changeset
1980 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1981 "suggest parentheses around %<-%> inside %<<<%>");
kono
parents:
diff changeset
1982 else if (code_right == MINUS_EXPR)
kono
parents:
diff changeset
1983 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1984 "suggest parentheses around %<-%> inside %<<<%>");
kono
parents:
diff changeset
1985 return;
kono
parents:
diff changeset
1986
kono
parents:
diff changeset
1987 case RSHIFT_EXPR:
kono
parents:
diff changeset
1988 if (code_left == PLUS_EXPR)
kono
parents:
diff changeset
1989 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1990 "suggest parentheses around %<+%> inside %<>>%>");
kono
parents:
diff changeset
1991 else if (code_right == PLUS_EXPR)
kono
parents:
diff changeset
1992 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1993 "suggest parentheses around %<+%> inside %<>>%>");
kono
parents:
diff changeset
1994 else if (code_left == MINUS_EXPR)
kono
parents:
diff changeset
1995 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1996 "suggest parentheses around %<-%> inside %<>>%>");
kono
parents:
diff changeset
1997 else if (code_right == MINUS_EXPR)
kono
parents:
diff changeset
1998 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
1999 "suggest parentheses around %<-%> inside %<>>%>");
kono
parents:
diff changeset
2000 return;
kono
parents:
diff changeset
2001
kono
parents:
diff changeset
2002 case TRUTH_ORIF_EXPR:
kono
parents:
diff changeset
2003 if (code_left == TRUTH_ANDIF_EXPR)
kono
parents:
diff changeset
2004 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2005 "suggest parentheses around %<&&%> within %<||%>");
kono
parents:
diff changeset
2006 else if (code_right == TRUTH_ANDIF_EXPR)
kono
parents:
diff changeset
2007 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2008 "suggest parentheses around %<&&%> within %<||%>");
kono
parents:
diff changeset
2009 return;
kono
parents:
diff changeset
2010
kono
parents:
diff changeset
2011 case BIT_IOR_EXPR:
kono
parents:
diff changeset
2012 if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR
kono
parents:
diff changeset
2013 || code_left == PLUS_EXPR || code_left == MINUS_EXPR)
kono
parents:
diff changeset
2014 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2015 "suggest parentheses around arithmetic in operand of %<|%>");
kono
parents:
diff changeset
2016 else if (code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
kono
parents:
diff changeset
2017 || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
kono
parents:
diff changeset
2018 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2019 "suggest parentheses around arithmetic in operand of %<|%>");
kono
parents:
diff changeset
2020 /* Check cases like x|y==z */
kono
parents:
diff changeset
2021 else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
kono
parents:
diff changeset
2022 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2023 "suggest parentheses around comparison in operand of %<|%>");
kono
parents:
diff changeset
2024 else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
kono
parents:
diff changeset
2025 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2026 "suggest parentheses around comparison in operand of %<|%>");
kono
parents:
diff changeset
2027 /* Check cases like !x | y */
kono
parents:
diff changeset
2028 else if (code_left == TRUTH_NOT_EXPR
kono
parents:
diff changeset
2029 && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
kono
parents:
diff changeset
2030 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2031 "suggest parentheses around operand of "
kono
parents:
diff changeset
2032 "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
kono
parents:
diff changeset
2033 return;
kono
parents:
diff changeset
2034
kono
parents:
diff changeset
2035 case BIT_XOR_EXPR:
kono
parents:
diff changeset
2036 if (code_left == BIT_AND_EXPR
kono
parents:
diff changeset
2037 || code_left == PLUS_EXPR || code_left == MINUS_EXPR)
kono
parents:
diff changeset
2038 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2039 "suggest parentheses around arithmetic in operand of %<^%>");
kono
parents:
diff changeset
2040 else if (code_right == BIT_AND_EXPR
kono
parents:
diff changeset
2041 || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
kono
parents:
diff changeset
2042 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2043 "suggest parentheses around arithmetic in operand of %<^%>");
kono
parents:
diff changeset
2044 /* Check cases like x^y==z */
kono
parents:
diff changeset
2045 else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
kono
parents:
diff changeset
2046 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2047 "suggest parentheses around comparison in operand of %<^%>");
kono
parents:
diff changeset
2048 else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
kono
parents:
diff changeset
2049 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2050 "suggest parentheses around comparison in operand of %<^%>");
kono
parents:
diff changeset
2051 return;
kono
parents:
diff changeset
2052
kono
parents:
diff changeset
2053 case BIT_AND_EXPR:
kono
parents:
diff changeset
2054 if (code_left == PLUS_EXPR)
kono
parents:
diff changeset
2055 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2056 "suggest parentheses around %<+%> in operand of %<&%>");
kono
parents:
diff changeset
2057 else if (code_right == PLUS_EXPR)
kono
parents:
diff changeset
2058 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2059 "suggest parentheses around %<+%> in operand of %<&%>");
kono
parents:
diff changeset
2060 else if (code_left == MINUS_EXPR)
kono
parents:
diff changeset
2061 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2062 "suggest parentheses around %<-%> in operand of %<&%>");
kono
parents:
diff changeset
2063 else if (code_right == MINUS_EXPR)
kono
parents:
diff changeset
2064 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2065 "suggest parentheses around %<-%> in operand of %<&%>");
kono
parents:
diff changeset
2066 /* Check cases like x&y==z */
kono
parents:
diff changeset
2067 else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
kono
parents:
diff changeset
2068 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2069 "suggest parentheses around comparison in operand of %<&%>");
kono
parents:
diff changeset
2070 else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
kono
parents:
diff changeset
2071 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2072 "suggest parentheses around comparison in operand of %<&%>");
kono
parents:
diff changeset
2073 /* Check cases like !x & y */
kono
parents:
diff changeset
2074 else if (code_left == TRUTH_NOT_EXPR
kono
parents:
diff changeset
2075 && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
kono
parents:
diff changeset
2076 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2077 "suggest parentheses around operand of "
kono
parents:
diff changeset
2078 "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
kono
parents:
diff changeset
2079 return;
kono
parents:
diff changeset
2080
kono
parents:
diff changeset
2081 case EQ_EXPR:
kono
parents:
diff changeset
2082 if (TREE_CODE_CLASS (code_left) == tcc_comparison)
kono
parents:
diff changeset
2083 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2084 "suggest parentheses around comparison in operand of %<==%>");
kono
parents:
diff changeset
2085 else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
kono
parents:
diff changeset
2086 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2087 "suggest parentheses around comparison in operand of %<==%>");
kono
parents:
diff changeset
2088 return;
kono
parents:
diff changeset
2089 case NE_EXPR:
kono
parents:
diff changeset
2090 if (TREE_CODE_CLASS (code_left) == tcc_comparison)
kono
parents:
diff changeset
2091 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2092 "suggest parentheses around comparison in operand of %<!=%>");
kono
parents:
diff changeset
2093 else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
kono
parents:
diff changeset
2094 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2095 "suggest parentheses around comparison in operand of %<!=%>");
kono
parents:
diff changeset
2096 return;
kono
parents:
diff changeset
2097
kono
parents:
diff changeset
2098 default:
kono
parents:
diff changeset
2099 if (TREE_CODE_CLASS (code) == tcc_comparison)
kono
parents:
diff changeset
2100 {
kono
parents:
diff changeset
2101 if (TREE_CODE_CLASS (code_left) == tcc_comparison
kono
parents:
diff changeset
2102 && code_left != NE_EXPR && code_left != EQ_EXPR
kono
parents:
diff changeset
2103 && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
kono
parents:
diff changeset
2104 warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2105 "comparisons like %<X<=Y<=Z%> do not "
kono
parents:
diff changeset
2106 "have their mathematical meaning");
kono
parents:
diff changeset
2107 else if (TREE_CODE_CLASS (code_right) == tcc_comparison
kono
parents:
diff changeset
2108 && code_right != NE_EXPR && code_right != EQ_EXPR
kono
parents:
diff changeset
2109 && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))
kono
parents:
diff changeset
2110 warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
kono
parents:
diff changeset
2111 "comparisons like %<X<=Y<=Z%> do not "
kono
parents:
diff changeset
2112 "have their mathematical meaning");
kono
parents:
diff changeset
2113 }
kono
parents:
diff changeset
2114 return;
kono
parents:
diff changeset
2115 }
kono
parents:
diff changeset
2116 #undef NOT_A_BOOLEAN_EXPR_P
kono
parents:
diff changeset
2117 }
kono
parents:
diff changeset
2118
kono
parents:
diff changeset
2119 /* If LABEL (a LABEL_DECL) has not been used, issue a warning. */
kono
parents:
diff changeset
2120
kono
parents:
diff changeset
2121 void
kono
parents:
diff changeset
2122 warn_for_unused_label (tree label)
kono
parents:
diff changeset
2123 {
kono
parents:
diff changeset
2124 if (!TREE_USED (label))
kono
parents:
diff changeset
2125 {
kono
parents:
diff changeset
2126 if (DECL_INITIAL (label))
kono
parents:
diff changeset
2127 warning (OPT_Wunused_label, "label %q+D defined but not used", label);
kono
parents:
diff changeset
2128 else
kono
parents:
diff changeset
2129 warning (OPT_Wunused_label, "label %q+D declared but not defined", label);
kono
parents:
diff changeset
2130 }
kono
parents:
diff changeset
2131 else if (asan_sanitize_use_after_scope ())
kono
parents:
diff changeset
2132 {
kono
parents:
diff changeset
2133 if (asan_used_labels == NULL)
kono
parents:
diff changeset
2134 asan_used_labels = new hash_set<tree> (16);
kono
parents:
diff changeset
2135
kono
parents:
diff changeset
2136 asan_used_labels->add (label);
kono
parents:
diff changeset
2137 }
kono
parents:
diff changeset
2138 }
kono
parents:
diff changeset
2139
kono
parents:
diff changeset
2140 /* Warn for division by zero according to the value of DIVISOR. LOC
kono
parents:
diff changeset
2141 is the location of the division operator. */
kono
parents:
diff changeset
2142
kono
parents:
diff changeset
2143 void
kono
parents:
diff changeset
2144 warn_for_div_by_zero (location_t loc, tree divisor)
kono
parents:
diff changeset
2145 {
kono
parents:
diff changeset
2146 /* If DIVISOR is zero, and has integral or fixed-point type, issue a warning
kono
parents:
diff changeset
2147 about division by zero. Do not issue a warning if DIVISOR has a
kono
parents:
diff changeset
2148 floating-point type, since we consider 0.0/0.0 a valid way of
kono
parents:
diff changeset
2149 generating a NaN. */
kono
parents:
diff changeset
2150 if (c_inhibit_evaluation_warnings == 0
kono
parents:
diff changeset
2151 && (integer_zerop (divisor) || fixed_zerop (divisor)))
kono
parents:
diff changeset
2152 warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
kono
parents:
diff changeset
2153 }
kono
parents:
diff changeset
2154
kono
parents:
diff changeset
2155 /* Warn for patterns where memset appears to be used incorrectly. The
kono
parents:
diff changeset
2156 warning location should be LOC. ARG0, and ARG2 are the first and
kono
parents:
diff changeset
2157 last arguments to the call, while LITERAL_ZERO_MASK has a 1 bit for
kono
parents:
diff changeset
2158 each argument that was a literal zero. */
kono
parents:
diff changeset
2159
kono
parents:
diff changeset
2160 void
kono
parents:
diff changeset
2161 warn_for_memset (location_t loc, tree arg0, tree arg2,
kono
parents:
diff changeset
2162 int literal_zero_mask)
kono
parents:
diff changeset
2163 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2164 arg0 = fold_for_warn (arg0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2165 arg2 = fold_for_warn (arg2);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2166
111
kono
parents:
diff changeset
2167 if (warn_memset_transposed_args
kono
parents:
diff changeset
2168 && integer_zerop (arg2)
kono
parents:
diff changeset
2169 && (literal_zero_mask & (1 << 2)) != 0
kono
parents:
diff changeset
2170 && (literal_zero_mask & (1 << 1)) == 0)
kono
parents:
diff changeset
2171 warning_at (loc, OPT_Wmemset_transposed_args,
kono
parents:
diff changeset
2172 "%<memset%> used with constant zero length "
kono
parents:
diff changeset
2173 "parameter; this could be due to transposed "
kono
parents:
diff changeset
2174 "parameters");
kono
parents:
diff changeset
2175
kono
parents:
diff changeset
2176 if (warn_memset_elt_size && TREE_CODE (arg2) == INTEGER_CST)
kono
parents:
diff changeset
2177 {
kono
parents:
diff changeset
2178 STRIP_NOPS (arg0);
kono
parents:
diff changeset
2179 if (TREE_CODE (arg0) == ADDR_EXPR)
kono
parents:
diff changeset
2180 arg0 = TREE_OPERAND (arg0, 0);
kono
parents:
diff changeset
2181 tree type = TREE_TYPE (arg0);
kono
parents:
diff changeset
2182 if (type != NULL_TREE && TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
2183 {
kono
parents:
diff changeset
2184 tree elt_type = TREE_TYPE (type);
kono
parents:
diff changeset
2185 tree domain = TYPE_DOMAIN (type);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2186 if (COMPLETE_TYPE_P (elt_type)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2187 && !integer_onep (TYPE_SIZE_UNIT (elt_type))
111
kono
parents:
diff changeset
2188 && domain != NULL_TREE
kono
parents:
diff changeset
2189 && TYPE_MAX_VALUE (domain)
kono
parents:
diff changeset
2190 && TYPE_MIN_VALUE (domain)
kono
parents:
diff changeset
2191 && integer_zerop (TYPE_MIN_VALUE (domain))
kono
parents:
diff changeset
2192 && integer_onep (fold_build2 (MINUS_EXPR, domain,
kono
parents:
diff changeset
2193 arg2,
kono
parents:
diff changeset
2194 TYPE_MAX_VALUE (domain))))
kono
parents:
diff changeset
2195 warning_at (loc, OPT_Wmemset_elt_size,
kono
parents:
diff changeset
2196 "%<memset%> used with length equal to "
kono
parents:
diff changeset
2197 "number of elements without multiplication "
kono
parents:
diff changeset
2198 "by element size");
kono
parents:
diff changeset
2199 }
kono
parents:
diff changeset
2200 }
kono
parents:
diff changeset
2201 }
kono
parents:
diff changeset
2202
kono
parents:
diff changeset
2203 /* Subroutine of build_binary_op. Give warnings for comparisons
kono
parents:
diff changeset
2204 between signed and unsigned quantities that may fail. Do the
kono
parents:
diff changeset
2205 checking based on the original operand trees ORIG_OP0 and ORIG_OP1,
kono
parents:
diff changeset
2206 so that casts will be considered, but default promotions won't
kono
parents:
diff changeset
2207 be.
kono
parents:
diff changeset
2208
kono
parents:
diff changeset
2209 LOCATION is the location of the comparison operator.
kono
parents:
diff changeset
2210
kono
parents:
diff changeset
2211 The arguments of this function map directly to local variables
kono
parents:
diff changeset
2212 of build_binary_op. */
kono
parents:
diff changeset
2213
kono
parents:
diff changeset
2214 void
kono
parents:
diff changeset
2215 warn_for_sign_compare (location_t location,
kono
parents:
diff changeset
2216 tree orig_op0, tree orig_op1,
kono
parents:
diff changeset
2217 tree op0, tree op1,
kono
parents:
diff changeset
2218 tree result_type, enum tree_code resultcode)
kono
parents:
diff changeset
2219 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2220 if (error_operand_p (orig_op0) || error_operand_p (orig_op1))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2221 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2222
111
kono
parents:
diff changeset
2223 int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
kono
parents:
diff changeset
2224 int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
kono
parents:
diff changeset
2225 int unsignedp0, unsignedp1;
kono
parents:
diff changeset
2226
kono
parents:
diff changeset
2227 /* In C++, check for comparison of different enum types. */
kono
parents:
diff changeset
2228 if (c_dialect_cxx()
kono
parents:
diff changeset
2229 && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
kono
parents:
diff changeset
2230 && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
kono
parents:
diff changeset
2231 && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
kono
parents:
diff changeset
2232 != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
kono
parents:
diff changeset
2233 {
kono
parents:
diff changeset
2234 warning_at (location,
kono
parents:
diff changeset
2235 OPT_Wsign_compare, "comparison between types %qT and %qT",
kono
parents:
diff changeset
2236 TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
kono
parents:
diff changeset
2237 }
kono
parents:
diff changeset
2238
kono
parents:
diff changeset
2239 /* Do not warn if the comparison is being done in a signed type,
kono
parents:
diff changeset
2240 since the signed type will only be chosen if it can represent
kono
parents:
diff changeset
2241 all the values of the unsigned type. */
kono
parents:
diff changeset
2242 if (!TYPE_UNSIGNED (result_type))
kono
parents:
diff changeset
2243 /* OK */;
kono
parents:
diff changeset
2244 /* Do not warn if both operands are unsigned. */
kono
parents:
diff changeset
2245 else if (op0_signed == op1_signed)
kono
parents:
diff changeset
2246 /* OK */;
kono
parents:
diff changeset
2247 else
kono
parents:
diff changeset
2248 {
kono
parents:
diff changeset
2249 tree sop, uop, base_type;
kono
parents:
diff changeset
2250 bool ovf;
kono
parents:
diff changeset
2251
kono
parents:
diff changeset
2252 if (op0_signed)
kono
parents:
diff changeset
2253 sop = orig_op0, uop = orig_op1;
kono
parents:
diff changeset
2254 else
kono
parents:
diff changeset
2255 sop = orig_op1, uop = orig_op0;
kono
parents:
diff changeset
2256
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2257 sop = fold_for_warn (sop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2258 uop = fold_for_warn (uop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2259
111
kono
parents:
diff changeset
2260 STRIP_TYPE_NOPS (sop);
kono
parents:
diff changeset
2261 STRIP_TYPE_NOPS (uop);
kono
parents:
diff changeset
2262 base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
kono
parents:
diff changeset
2263 ? TREE_TYPE (result_type) : result_type);
kono
parents:
diff changeset
2264
kono
parents:
diff changeset
2265 /* Do not warn if the signed quantity is an unsuffixed integer
kono
parents:
diff changeset
2266 literal (or some static constant expression involving such
kono
parents:
diff changeset
2267 literals or a conditional expression involving such literals)
kono
parents:
diff changeset
2268 and it is non-negative. */
kono
parents:
diff changeset
2269 if (tree_expr_nonnegative_warnv_p (sop, &ovf))
kono
parents:
diff changeset
2270 /* OK */;
kono
parents:
diff changeset
2271 /* Do not warn if the comparison is an equality operation, the
kono
parents:
diff changeset
2272 unsigned quantity is an integral constant, and it would fit
kono
parents:
diff changeset
2273 in the result if the result were signed. */
kono
parents:
diff changeset
2274 else if (TREE_CODE (uop) == INTEGER_CST
kono
parents:
diff changeset
2275 && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
kono
parents:
diff changeset
2276 && int_fits_type_p (uop, c_common_signed_type (base_type)))
kono
parents:
diff changeset
2277 /* OK */;
kono
parents:
diff changeset
2278 /* In C, do not warn if the unsigned quantity is an enumeration
kono
parents:
diff changeset
2279 constant and its maximum value would fit in the result if the
kono
parents:
diff changeset
2280 result were signed. */
kono
parents:
diff changeset
2281 else if (!c_dialect_cxx() && TREE_CODE (uop) == INTEGER_CST
kono
parents:
diff changeset
2282 && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
kono
parents:
diff changeset
2283 && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
kono
parents:
diff changeset
2284 c_common_signed_type (base_type)))
kono
parents:
diff changeset
2285 /* OK */;
kono
parents:
diff changeset
2286 else
kono
parents:
diff changeset
2287 warning_at (location, OPT_Wsign_compare,
kono
parents:
diff changeset
2288 "comparison of integer expressions of different "
kono
parents:
diff changeset
2289 "signedness: %qT and %qT", TREE_TYPE (orig_op0),
kono
parents:
diff changeset
2290 TREE_TYPE (orig_op1));
kono
parents:
diff changeset
2291 }
kono
parents:
diff changeset
2292
kono
parents:
diff changeset
2293 /* Warn if two unsigned values are being compared in a size larger
kono
parents:
diff changeset
2294 than their original size, and one (and only one) is the result of
kono
parents:
diff changeset
2295 a `~' operator. This comparison will always fail.
kono
parents:
diff changeset
2296
kono
parents:
diff changeset
2297 Also warn if one operand is a constant, and the constant does not
kono
parents:
diff changeset
2298 have all bits set that are set in the ~ operand when it is
kono
parents:
diff changeset
2299 extended. */
kono
parents:
diff changeset
2300
kono
parents:
diff changeset
2301 op0 = c_common_get_narrower (op0, &unsignedp0);
kono
parents:
diff changeset
2302 op1 = c_common_get_narrower (op1, &unsignedp1);
kono
parents:
diff changeset
2303
kono
parents:
diff changeset
2304 if ((TREE_CODE (op0) == BIT_NOT_EXPR)
kono
parents:
diff changeset
2305 ^ (TREE_CODE (op1) == BIT_NOT_EXPR))
kono
parents:
diff changeset
2306 {
kono
parents:
diff changeset
2307 if (TREE_CODE (op0) == BIT_NOT_EXPR)
kono
parents:
diff changeset
2308 op0 = c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
kono
parents:
diff changeset
2309 if (TREE_CODE (op1) == BIT_NOT_EXPR)
kono
parents:
diff changeset
2310 op1 = c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
kono
parents:
diff changeset
2311
kono
parents:
diff changeset
2312 if (tree_fits_shwi_p (op0) || tree_fits_shwi_p (op1))
kono
parents:
diff changeset
2313 {
kono
parents:
diff changeset
2314 tree primop;
kono
parents:
diff changeset
2315 HOST_WIDE_INT constant, mask;
kono
parents:
diff changeset
2316 int unsignedp;
kono
parents:
diff changeset
2317 unsigned int bits;
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 if (tree_fits_shwi_p (op0))
kono
parents:
diff changeset
2320 {
kono
parents:
diff changeset
2321 primop = op1;
kono
parents:
diff changeset
2322 unsignedp = unsignedp1;
kono
parents:
diff changeset
2323 constant = tree_to_shwi (op0);
kono
parents:
diff changeset
2324 }
kono
parents:
diff changeset
2325 else
kono
parents:
diff changeset
2326 {
kono
parents:
diff changeset
2327 primop = op0;
kono
parents:
diff changeset
2328 unsignedp = unsignedp0;
kono
parents:
diff changeset
2329 constant = tree_to_shwi (op1);
kono
parents:
diff changeset
2330 }
kono
parents:
diff changeset
2331
kono
parents:
diff changeset
2332 bits = TYPE_PRECISION (TREE_TYPE (primop));
kono
parents:
diff changeset
2333 if (bits < TYPE_PRECISION (result_type)
kono
parents:
diff changeset
2334 && bits < HOST_BITS_PER_LONG && unsignedp)
kono
parents:
diff changeset
2335 {
kono
parents:
diff changeset
2336 mask = HOST_WIDE_INT_M1U << bits;
kono
parents:
diff changeset
2337 if ((mask & constant) != mask)
kono
parents:
diff changeset
2338 {
kono
parents:
diff changeset
2339 if (constant == 0)
kono
parents:
diff changeset
2340 warning_at (location, OPT_Wsign_compare,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2341 "promoted bitwise complement of an unsigned "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2342 "value is always nonzero");
111
kono
parents:
diff changeset
2343 else
kono
parents:
diff changeset
2344 warning_at (location, OPT_Wsign_compare,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2345 "comparison of promoted bitwise complement "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2346 "of an unsigned value with constant");
111
kono
parents:
diff changeset
2347 }
kono
parents:
diff changeset
2348 }
kono
parents:
diff changeset
2349 }
kono
parents:
diff changeset
2350 else if (unsignedp0 && unsignedp1
kono
parents:
diff changeset
2351 && (TYPE_PRECISION (TREE_TYPE (op0))
kono
parents:
diff changeset
2352 < TYPE_PRECISION (result_type))
kono
parents:
diff changeset
2353 && (TYPE_PRECISION (TREE_TYPE (op1))
kono
parents:
diff changeset
2354 < TYPE_PRECISION (result_type)))
kono
parents:
diff changeset
2355 warning_at (location, OPT_Wsign_compare,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2356 "comparison of promoted bitwise complement "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2357 "of an unsigned value with unsigned");
111
kono
parents:
diff changeset
2358 }
kono
parents:
diff changeset
2359 }
kono
parents:
diff changeset
2360
kono
parents:
diff changeset
2361 /* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common
kono
parents:
diff changeset
2362 type via c_common_type. If -Wdouble-promotion is in use, and the
kono
parents:
diff changeset
2363 conditions for warning have been met, issue a warning. GMSGID is
kono
parents:
diff changeset
2364 the warning message. It must have two %T specifiers for the type
kono
parents:
diff changeset
2365 that was converted (generally "float") and the type to which it was
kono
parents:
diff changeset
2366 converted (generally "double), respectively. LOC is the location
kono
parents:
diff changeset
2367 to which the warning should refer. */
kono
parents:
diff changeset
2368
kono
parents:
diff changeset
2369 void
kono
parents:
diff changeset
2370 do_warn_double_promotion (tree result_type, tree type1, tree type2,
kono
parents:
diff changeset
2371 const char *gmsgid, location_t loc)
kono
parents:
diff changeset
2372 {
kono
parents:
diff changeset
2373 tree source_type;
kono
parents:
diff changeset
2374
kono
parents:
diff changeset
2375 if (!warn_double_promotion)
kono
parents:
diff changeset
2376 return;
kono
parents:
diff changeset
2377 /* If the conversion will not occur at run-time, there is no need to
kono
parents:
diff changeset
2378 warn about it. */
kono
parents:
diff changeset
2379 if (c_inhibit_evaluation_warnings)
kono
parents:
diff changeset
2380 return;
kono
parents:
diff changeset
2381 /* If an invalid conversion has occured, don't warn. */
kono
parents:
diff changeset
2382 if (result_type == error_mark_node)
kono
parents:
diff changeset
2383 return;
kono
parents:
diff changeset
2384 if (TYPE_MAIN_VARIANT (result_type) != double_type_node
kono
parents:
diff changeset
2385 && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node)
kono
parents:
diff changeset
2386 return;
kono
parents:
diff changeset
2387 if (TYPE_MAIN_VARIANT (type1) == float_type_node
kono
parents:
diff changeset
2388 || TYPE_MAIN_VARIANT (type1) == complex_float_type_node)
kono
parents:
diff changeset
2389 source_type = type1;
kono
parents:
diff changeset
2390 else if (TYPE_MAIN_VARIANT (type2) == float_type_node
kono
parents:
diff changeset
2391 || TYPE_MAIN_VARIANT (type2) == complex_float_type_node)
kono
parents:
diff changeset
2392 source_type = type2;
kono
parents:
diff changeset
2393 else
kono
parents:
diff changeset
2394 return;
kono
parents:
diff changeset
2395 warning_at (loc, OPT_Wdouble_promotion, gmsgid, source_type, result_type);
kono
parents:
diff changeset
2396 }
kono
parents:
diff changeset
2397
kono
parents:
diff changeset
2398 /* Possibly warn about unused parameters. */
kono
parents:
diff changeset
2399
kono
parents:
diff changeset
2400 void
kono
parents:
diff changeset
2401 do_warn_unused_parameter (tree fn)
kono
parents:
diff changeset
2402 {
kono
parents:
diff changeset
2403 tree decl;
kono
parents:
diff changeset
2404
kono
parents:
diff changeset
2405 for (decl = DECL_ARGUMENTS (fn);
kono
parents:
diff changeset
2406 decl; decl = DECL_CHAIN (decl))
kono
parents:
diff changeset
2407 if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
kono
parents:
diff changeset
2408 && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
kono
parents:
diff changeset
2409 && !TREE_NO_WARNING (decl))
kono
parents:
diff changeset
2410 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_parameter,
kono
parents:
diff changeset
2411 "unused parameter %qD", decl);
kono
parents:
diff changeset
2412 }
kono
parents:
diff changeset
2413
kono
parents:
diff changeset
2414 /* If DECL is a typedef that is declared in the current function,
kono
parents:
diff changeset
2415 record it for the purpose of -Wunused-local-typedefs. */
kono
parents:
diff changeset
2416
kono
parents:
diff changeset
2417 void
kono
parents:
diff changeset
2418 record_locally_defined_typedef (tree decl)
kono
parents:
diff changeset
2419 {
kono
parents:
diff changeset
2420 struct c_language_function *l;
kono
parents:
diff changeset
2421
kono
parents:
diff changeset
2422 if (!warn_unused_local_typedefs
kono
parents:
diff changeset
2423 || cfun == NULL
kono
parents:
diff changeset
2424 /* if this is not a locally defined typedef then we are not
kono
parents:
diff changeset
2425 interested. */
kono
parents:
diff changeset
2426 || !is_typedef_decl (decl)
kono
parents:
diff changeset
2427 || !decl_function_context (decl))
kono
parents:
diff changeset
2428 return;
kono
parents:
diff changeset
2429
kono
parents:
diff changeset
2430 l = (struct c_language_function *) cfun->language;
kono
parents:
diff changeset
2431 vec_safe_push (l->local_typedefs, decl);
kono
parents:
diff changeset
2432 }
kono
parents:
diff changeset
2433
kono
parents:
diff changeset
2434 /* If T is a TYPE_DECL declared locally, mark it as used. */
kono
parents:
diff changeset
2435
kono
parents:
diff changeset
2436 void
kono
parents:
diff changeset
2437 maybe_record_typedef_use (tree t)
kono
parents:
diff changeset
2438 {
kono
parents:
diff changeset
2439 if (!is_typedef_decl (t))
kono
parents:
diff changeset
2440 return;
kono
parents:
diff changeset
2441
kono
parents:
diff changeset
2442 TREE_USED (t) = true;
kono
parents:
diff changeset
2443 }
kono
parents:
diff changeset
2444
kono
parents:
diff changeset
2445 /* Warn if there are some unused locally defined typedefs in the
kono
parents:
diff changeset
2446 current function. */
kono
parents:
diff changeset
2447
kono
parents:
diff changeset
2448 void
kono
parents:
diff changeset
2449 maybe_warn_unused_local_typedefs (void)
kono
parents:
diff changeset
2450 {
kono
parents:
diff changeset
2451 int i;
kono
parents:
diff changeset
2452 tree decl;
kono
parents:
diff changeset
2453 /* The number of times we have emitted -Wunused-local-typedefs
kono
parents:
diff changeset
2454 warnings. If this is different from errorcount, that means some
kono
parents:
diff changeset
2455 unrelated errors have been issued. In which case, we'll avoid
kono
parents:
diff changeset
2456 emitting "unused-local-typedefs" warnings. */
kono
parents:
diff changeset
2457 static int unused_local_typedefs_warn_count;
kono
parents:
diff changeset
2458 struct c_language_function *l;
kono
parents:
diff changeset
2459
kono
parents:
diff changeset
2460 if (cfun == NULL)
kono
parents:
diff changeset
2461 return;
kono
parents:
diff changeset
2462
kono
parents:
diff changeset
2463 if ((l = (struct c_language_function *) cfun->language) == NULL)
kono
parents:
diff changeset
2464 return;
kono
parents:
diff changeset
2465
kono
parents:
diff changeset
2466 if (warn_unused_local_typedefs
kono
parents:
diff changeset
2467 && errorcount == unused_local_typedefs_warn_count)
kono
parents:
diff changeset
2468 {
kono
parents:
diff changeset
2469 FOR_EACH_VEC_SAFE_ELT (l->local_typedefs, i, decl)
kono
parents:
diff changeset
2470 if (!TREE_USED (decl))
kono
parents:
diff changeset
2471 warning_at (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
2472 OPT_Wunused_local_typedefs,
kono
parents:
diff changeset
2473 "typedef %qD locally defined but not used", decl);
kono
parents:
diff changeset
2474 unused_local_typedefs_warn_count = errorcount;
kono
parents:
diff changeset
2475 }
kono
parents:
diff changeset
2476
kono
parents:
diff changeset
2477 vec_free (l->local_typedefs);
kono
parents:
diff changeset
2478 }
kono
parents:
diff changeset
2479
kono
parents:
diff changeset
2480 /* If we're creating an if-else-if condition chain, first see if we
kono
parents:
diff changeset
2481 already have this COND in the CHAIN. If so, warn and don't add COND
kono
parents:
diff changeset
2482 into the vector, otherwise add the COND there. LOC is the location
kono
parents:
diff changeset
2483 of COND. */
kono
parents:
diff changeset
2484
kono
parents:
diff changeset
2485 void
kono
parents:
diff changeset
2486 warn_duplicated_cond_add_or_warn (location_t loc, tree cond, vec<tree> **chain)
kono
parents:
diff changeset
2487 {
kono
parents:
diff changeset
2488 /* No chain has been created yet. Do nothing. */
kono
parents:
diff changeset
2489 if (*chain == NULL)
kono
parents:
diff changeset
2490 return;
kono
parents:
diff changeset
2491
kono
parents:
diff changeset
2492 if (TREE_SIDE_EFFECTS (cond))
kono
parents:
diff changeset
2493 {
kono
parents:
diff changeset
2494 /* Uh-oh! This condition has a side-effect, thus invalidates
kono
parents:
diff changeset
2495 the whole chain. */
kono
parents:
diff changeset
2496 delete *chain;
kono
parents:
diff changeset
2497 *chain = NULL;
kono
parents:
diff changeset
2498 return;
kono
parents:
diff changeset
2499 }
kono
parents:
diff changeset
2500
kono
parents:
diff changeset
2501 unsigned int ix;
kono
parents:
diff changeset
2502 tree t;
kono
parents:
diff changeset
2503 bool found = false;
kono
parents:
diff changeset
2504 FOR_EACH_VEC_ELT (**chain, ix, t)
kono
parents:
diff changeset
2505 if (operand_equal_p (cond, t, 0))
kono
parents:
diff changeset
2506 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2507 auto_diagnostic_group d;
111
kono
parents:
diff changeset
2508 if (warning_at (loc, OPT_Wduplicated_cond,
kono
parents:
diff changeset
2509 "duplicated %<if%> condition"))
kono
parents:
diff changeset
2510 inform (EXPR_LOCATION (t), "previously used here");
kono
parents:
diff changeset
2511 found = true;
kono
parents:
diff changeset
2512 break;
kono
parents:
diff changeset
2513 }
kono
parents:
diff changeset
2514
kono
parents:
diff changeset
2515 if (!found
kono
parents:
diff changeset
2516 && !CONSTANT_CLASS_P (cond)
kono
parents:
diff changeset
2517 /* Don't infinitely grow the chain. */
kono
parents:
diff changeset
2518 && (*chain)->length () < 512)
kono
parents:
diff changeset
2519 (*chain)->safe_push (cond);
kono
parents:
diff changeset
2520 }
kono
parents:
diff changeset
2521
kono
parents:
diff changeset
2522 /* Check and possibly warn if two declarations have contradictory
kono
parents:
diff changeset
2523 attributes, such as always_inline vs. noinline. */
kono
parents:
diff changeset
2524
kono
parents:
diff changeset
2525 bool
kono
parents:
diff changeset
2526 diagnose_mismatched_attributes (tree olddecl, tree newdecl)
kono
parents:
diff changeset
2527 {
kono
parents:
diff changeset
2528 bool warned = false;
kono
parents:
diff changeset
2529
kono
parents:
diff changeset
2530 tree a1 = lookup_attribute ("optimize", DECL_ATTRIBUTES (olddecl));
kono
parents:
diff changeset
2531 tree a2 = lookup_attribute ("optimize", DECL_ATTRIBUTES (newdecl));
kono
parents:
diff changeset
2532 /* An optimization attribute applied on a declaration after the
kono
parents:
diff changeset
2533 definition is likely not what the user wanted. */
kono
parents:
diff changeset
2534 if (a2 != NULL_TREE
kono
parents:
diff changeset
2535 && DECL_SAVED_TREE (olddecl) != NULL_TREE
kono
parents:
diff changeset
2536 && (a1 == NULL_TREE || !attribute_list_equal (a1, a2)))
kono
parents:
diff changeset
2537 warned |= warning (OPT_Wattributes,
kono
parents:
diff changeset
2538 "optimization attribute on %qD follows "
kono
parents:
diff changeset
2539 "definition but the attribute doesn%'t match",
kono
parents:
diff changeset
2540 newdecl);
kono
parents:
diff changeset
2541
kono
parents:
diff changeset
2542 /* Diagnose inline __attribute__ ((noinline)) which is silly. */
kono
parents:
diff changeset
2543 if (DECL_DECLARED_INLINE_P (newdecl)
kono
parents:
diff changeset
2544 && DECL_UNINLINABLE (olddecl)
kono
parents:
diff changeset
2545 && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
kono
parents:
diff changeset
2546 warned |= warning (OPT_Wattributes, "inline declaration of %qD follows "
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2547 "declaration with attribute %<noinline%>", newdecl);
111
kono
parents:
diff changeset
2548 else if (DECL_DECLARED_INLINE_P (olddecl)
kono
parents:
diff changeset
2549 && DECL_UNINLINABLE (newdecl)
kono
parents:
diff changeset
2550 && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
kono
parents:
diff changeset
2551 warned |= warning (OPT_Wattributes, "declaration of %q+D with attribute "
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2552 "%<noinline%> follows inline declaration", newdecl);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2553
111
kono
parents:
diff changeset
2554 return warned;
kono
parents:
diff changeset
2555 }
kono
parents:
diff changeset
2556
kono
parents:
diff changeset
2557 /* Warn if signed left shift overflows. We don't warn
kono
parents:
diff changeset
2558 about left-shifting 1 into the sign bit in C++14; cf.
kono
parents:
diff changeset
2559 <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3367.html#1457>
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2560 and don't warn for C++2a at all, as signed left shifts never
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2561 overflow.
111
kono
parents:
diff changeset
2562 LOC is a location of the shift; OP0 and OP1 are the operands.
kono
parents:
diff changeset
2563 Return true if an overflow is detected, false otherwise. */
kono
parents:
diff changeset
2564
kono
parents:
diff changeset
2565 bool
kono
parents:
diff changeset
2566 maybe_warn_shift_overflow (location_t loc, tree op0, tree op1)
kono
parents:
diff changeset
2567 {
kono
parents:
diff changeset
2568 if (TREE_CODE (op0) != INTEGER_CST
kono
parents:
diff changeset
2569 || TREE_CODE (op1) != INTEGER_CST)
kono
parents:
diff changeset
2570 return false;
kono
parents:
diff changeset
2571
kono
parents:
diff changeset
2572 tree type0 = TREE_TYPE (op0);
kono
parents:
diff changeset
2573 unsigned int prec0 = TYPE_PRECISION (type0);
kono
parents:
diff changeset
2574
kono
parents:
diff changeset
2575 /* Left-hand operand must be signed. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2576 if (TYPE_UNSIGNED (type0) || cxx_dialect >= cxx2a)
111
kono
parents:
diff changeset
2577 return false;
kono
parents:
diff changeset
2578
kono
parents:
diff changeset
2579 unsigned int min_prec = (wi::min_precision (wi::to_wide (op0), SIGNED)
kono
parents:
diff changeset
2580 + TREE_INT_CST_LOW (op1));
kono
parents:
diff changeset
2581 /* Handle the case of left-shifting 1 into the sign bit.
kono
parents:
diff changeset
2582 * However, shifting 1 _out_ of the sign bit, as in
kono
parents:
diff changeset
2583 * INT_MIN << 1, is considered an overflow.
kono
parents:
diff changeset
2584 */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2585 if (!tree_int_cst_sign_bit (op0) && min_prec == prec0 + 1)
111
kono
parents:
diff changeset
2586 {
kono
parents:
diff changeset
2587 /* Never warn for C++14 onwards. */
kono
parents:
diff changeset
2588 if (cxx_dialect >= cxx14)
kono
parents:
diff changeset
2589 return false;
kono
parents:
diff changeset
2590 /* Otherwise only if -Wshift-overflow=2. But return
kono
parents:
diff changeset
2591 true to signal an overflow for the sake of integer
kono
parents:
diff changeset
2592 constant expressions. */
kono
parents:
diff changeset
2593 if (warn_shift_overflow < 2)
kono
parents:
diff changeset
2594 return true;
kono
parents:
diff changeset
2595 }
kono
parents:
diff changeset
2596
kono
parents:
diff changeset
2597 bool overflowed = min_prec > prec0;
kono
parents:
diff changeset
2598 if (overflowed && c_inhibit_evaluation_warnings == 0)
kono
parents:
diff changeset
2599 warning_at (loc, OPT_Wshift_overflow_,
kono
parents:
diff changeset
2600 "result of %qE requires %u bits to represent, "
kono
parents:
diff changeset
2601 "but %qT only has %u bits",
kono
parents:
diff changeset
2602 build2_loc (loc, LSHIFT_EXPR, type0, op0, op1),
kono
parents:
diff changeset
2603 min_prec, type0, prec0);
kono
parents:
diff changeset
2604
kono
parents:
diff changeset
2605 return overflowed;
kono
parents:
diff changeset
2606 }
kono
parents:
diff changeset
2607
kono
parents:
diff changeset
2608 /* Warn about boolean expression compared with an integer value different
kono
parents:
diff changeset
2609 from true/false. Warns also e.g. about "(i1 == i2) == 2".
kono
parents:
diff changeset
2610 LOC is the location of the comparison, CODE is its code, OP0 and OP1
kono
parents:
diff changeset
2611 are the operands of the comparison. The caller must ensure that
kono
parents:
diff changeset
2612 either operand is a boolean expression. */
kono
parents:
diff changeset
2613
kono
parents:
diff changeset
2614 void
kono
parents:
diff changeset
2615 maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0,
kono
parents:
diff changeset
2616 tree op1)
kono
parents:
diff changeset
2617 {
kono
parents:
diff changeset
2618 if (TREE_CODE_CLASS (code) != tcc_comparison)
kono
parents:
diff changeset
2619 return;
kono
parents:
diff changeset
2620
kono
parents:
diff changeset
2621 tree f, cst;
kono
parents:
diff changeset
2622 if (f = fold_for_warn (op0),
kono
parents:
diff changeset
2623 TREE_CODE (f) == INTEGER_CST)
kono
parents:
diff changeset
2624 cst = op0 = f;
kono
parents:
diff changeset
2625 else if (f = fold_for_warn (op1),
kono
parents:
diff changeset
2626 TREE_CODE (f) == INTEGER_CST)
kono
parents:
diff changeset
2627 cst = op1 = f;
kono
parents:
diff changeset
2628 else
kono
parents:
diff changeset
2629 return;
kono
parents:
diff changeset
2630
kono
parents:
diff changeset
2631 if (!integer_zerop (cst) && !integer_onep (cst))
kono
parents:
diff changeset
2632 {
kono
parents:
diff changeset
2633 int sign = (TREE_CODE (op0) == INTEGER_CST
kono
parents:
diff changeset
2634 ? tree_int_cst_sgn (cst) : -tree_int_cst_sgn (cst));
kono
parents:
diff changeset
2635 if (code == EQ_EXPR
kono
parents:
diff changeset
2636 || ((code == GT_EXPR || code == GE_EXPR) && sign < 0)
kono
parents:
diff changeset
2637 || ((code == LT_EXPR || code == LE_EXPR) && sign > 0))
kono
parents:
diff changeset
2638 warning_at (loc, OPT_Wbool_compare, "comparison of constant %qE "
kono
parents:
diff changeset
2639 "with boolean expression is always false", cst);
kono
parents:
diff changeset
2640 else
kono
parents:
diff changeset
2641 warning_at (loc, OPT_Wbool_compare, "comparison of constant %qE "
kono
parents:
diff changeset
2642 "with boolean expression is always true", cst);
kono
parents:
diff changeset
2643 }
kono
parents:
diff changeset
2644 else if (integer_zerop (cst) || integer_onep (cst))
kono
parents:
diff changeset
2645 {
kono
parents:
diff changeset
2646 /* If the non-constant operand isn't of a boolean type, we
kono
parents:
diff changeset
2647 don't want to warn here. */
kono
parents:
diff changeset
2648 tree noncst = TREE_CODE (op0) == INTEGER_CST ? op1 : op0;
kono
parents:
diff changeset
2649 /* Handle booleans promoted to integers. */
kono
parents:
diff changeset
2650 if (bool_promoted_to_int_p (noncst))
kono
parents:
diff changeset
2651 /* Warn. */;
kono
parents:
diff changeset
2652 else if (TREE_CODE (TREE_TYPE (noncst)) != BOOLEAN_TYPE
kono
parents:
diff changeset
2653 && !truth_value_p (TREE_CODE (noncst)))
kono
parents:
diff changeset
2654 return;
kono
parents:
diff changeset
2655 /* Do some magic to get the right diagnostics. */
kono
parents:
diff changeset
2656 bool flag = TREE_CODE (op0) == INTEGER_CST;
kono
parents:
diff changeset
2657 flag = integer_zerop (cst) ? flag : !flag;
kono
parents:
diff changeset
2658 if ((code == GE_EXPR && !flag) || (code == LE_EXPR && flag))
kono
parents:
diff changeset
2659 warning_at (loc, OPT_Wbool_compare, "comparison of constant %qE "
kono
parents:
diff changeset
2660 "with boolean expression is always true", cst);
kono
parents:
diff changeset
2661 else if ((code == LT_EXPR && !flag) || (code == GT_EXPR && flag))
kono
parents:
diff changeset
2662 warning_at (loc, OPT_Wbool_compare, "comparison of constant %qE "
kono
parents:
diff changeset
2663 "with boolean expression is always false", cst);
kono
parents:
diff changeset
2664 }
kono
parents:
diff changeset
2665 }
kono
parents:
diff changeset
2666
kono
parents:
diff changeset
2667 /* Warn if an argument at position param_pos is passed to a
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2668 restrict-qualified param, and it aliases with another argument.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2669 Return true if a warning has been issued. */
111
kono
parents:
diff changeset
2670
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2671 bool
111
kono
parents:
diff changeset
2672 warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
kono
parents:
diff changeset
2673 {
kono
parents:
diff changeset
2674 tree arg = argarray[param_pos];
kono
parents:
diff changeset
2675 if (TREE_VISITED (arg) || integer_zerop (arg))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2676 return false;
111
kono
parents:
diff changeset
2677
kono
parents:
diff changeset
2678 location_t loc = EXPR_LOC_OR_LOC (arg, input_location);
kono
parents:
diff changeset
2679 gcc_rich_location richloc (loc);
kono
parents:
diff changeset
2680
kono
parents:
diff changeset
2681 unsigned i;
kono
parents:
diff changeset
2682 auto_vec<int, 16> arg_positions;
kono
parents:
diff changeset
2683
kono
parents:
diff changeset
2684 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
2685 {
kono
parents:
diff changeset
2686 if (i == param_pos)
kono
parents:
diff changeset
2687 continue;
kono
parents:
diff changeset
2688
kono
parents:
diff changeset
2689 tree current_arg = argarray[i];
kono
parents:
diff changeset
2690 if (operand_equal_p (arg, current_arg, 0))
kono
parents:
diff changeset
2691 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2692 TREE_VISITED (current_arg) = 1;
111
kono
parents:
diff changeset
2693 arg_positions.safe_push (i + 1);
kono
parents:
diff changeset
2694 }
kono
parents:
diff changeset
2695 }
kono
parents:
diff changeset
2696
kono
parents:
diff changeset
2697 if (arg_positions.is_empty ())
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2698 return false;
111
kono
parents:
diff changeset
2699
kono
parents:
diff changeset
2700 int pos;
kono
parents:
diff changeset
2701 FOR_EACH_VEC_ELT (arg_positions, i, pos)
kono
parents:
diff changeset
2702 {
kono
parents:
diff changeset
2703 arg = argarray[pos - 1];
kono
parents:
diff changeset
2704 if (EXPR_HAS_LOCATION (arg))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2705 richloc.add_range (EXPR_LOCATION (arg));
111
kono
parents:
diff changeset
2706 }
kono
parents:
diff changeset
2707
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2708 return warning_n (&richloc, OPT_Wrestrict, arg_positions.length (),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2709 "passing argument %i to %qs-qualified parameter"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2710 " aliases with argument %Z",
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2711 "passing argument %i to %qs-qualified parameter"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2712 " aliases with arguments %Z",
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2713 param_pos + 1, "restrict", arg_positions.address (),
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2714 arg_positions.length ());
111
kono
parents:
diff changeset
2715 }
kono
parents:
diff changeset
2716
kono
parents:
diff changeset
2717 /* Callback function to determine whether an expression TP or one of its
kono
parents:
diff changeset
2718 subexpressions comes from macro expansion. Used to suppress bogus
kono
parents:
diff changeset
2719 warnings. */
kono
parents:
diff changeset
2720
kono
parents:
diff changeset
2721 static tree
kono
parents:
diff changeset
2722 expr_from_macro_expansion_r (tree *tp, int *, void *)
kono
parents:
diff changeset
2723 {
kono
parents:
diff changeset
2724 if (CAN_HAVE_LOCATION_P (*tp)
kono
parents:
diff changeset
2725 && from_macro_expansion_at (EXPR_LOCATION (*tp)))
kono
parents:
diff changeset
2726 return integer_zero_node;
kono
parents:
diff changeset
2727
kono
parents:
diff changeset
2728 return NULL_TREE;
kono
parents:
diff changeset
2729 }
kono
parents:
diff changeset
2730
kono
parents:
diff changeset
2731 /* Possibly warn when an if-else has identical branches. */
kono
parents:
diff changeset
2732
kono
parents:
diff changeset
2733 static void
kono
parents:
diff changeset
2734 do_warn_duplicated_branches (tree expr)
kono
parents:
diff changeset
2735 {
kono
parents:
diff changeset
2736 tree thenb = COND_EXPR_THEN (expr);
kono
parents:
diff changeset
2737 tree elseb = COND_EXPR_ELSE (expr);
kono
parents:
diff changeset
2738
kono
parents:
diff changeset
2739 /* Don't bother if any of the branches is missing. */
kono
parents:
diff changeset
2740 if (thenb == NULL_TREE || elseb == NULL_TREE)
kono
parents:
diff changeset
2741 return;
kono
parents:
diff changeset
2742
kono
parents:
diff changeset
2743 /* And don't warn for empty statements. */
kono
parents:
diff changeset
2744 if (TREE_CODE (thenb) == NOP_EXPR
kono
parents:
diff changeset
2745 && TREE_TYPE (thenb) == void_type_node
kono
parents:
diff changeset
2746 && TREE_OPERAND (thenb, 0) == size_zero_node)
kono
parents:
diff changeset
2747 return;
kono
parents:
diff changeset
2748
kono
parents:
diff changeset
2749 /* ... or empty branches. */
kono
parents:
diff changeset
2750 if (TREE_CODE (thenb) == STATEMENT_LIST
kono
parents:
diff changeset
2751 && STATEMENT_LIST_HEAD (thenb) == NULL)
kono
parents:
diff changeset
2752 return;
kono
parents:
diff changeset
2753
kono
parents:
diff changeset
2754 /* Compute the hash of the then branch. */
kono
parents:
diff changeset
2755 inchash::hash hstate0 (0);
kono
parents:
diff changeset
2756 inchash::add_expr (thenb, hstate0);
kono
parents:
diff changeset
2757 hashval_t h0 = hstate0.end ();
kono
parents:
diff changeset
2758
kono
parents:
diff changeset
2759 /* Compute the hash of the else branch. */
kono
parents:
diff changeset
2760 inchash::hash hstate1 (0);
kono
parents:
diff changeset
2761 inchash::add_expr (elseb, hstate1);
kono
parents:
diff changeset
2762 hashval_t h1 = hstate1.end ();
kono
parents:
diff changeset
2763
kono
parents:
diff changeset
2764 /* Compare the hashes. */
kono
parents:
diff changeset
2765 if (h0 == h1
kono
parents:
diff changeset
2766 && operand_equal_p (thenb, elseb, OEP_LEXICOGRAPHIC)
kono
parents:
diff changeset
2767 /* Don't warn if any of the branches or their subexpressions comes
kono
parents:
diff changeset
2768 from a macro. */
kono
parents:
diff changeset
2769 && !walk_tree_without_duplicates (&thenb, expr_from_macro_expansion_r,
kono
parents:
diff changeset
2770 NULL)
kono
parents:
diff changeset
2771 && !walk_tree_without_duplicates (&elseb, expr_from_macro_expansion_r,
kono
parents:
diff changeset
2772 NULL))
kono
parents:
diff changeset
2773 warning_at (EXPR_LOCATION (expr), OPT_Wduplicated_branches,
kono
parents:
diff changeset
2774 "this condition has identical branches");
kono
parents:
diff changeset
2775 }
kono
parents:
diff changeset
2776
kono
parents:
diff changeset
2777 /* Callback for c_genericize to implement -Wduplicated-branches. */
kono
parents:
diff changeset
2778
kono
parents:
diff changeset
2779 tree
kono
parents:
diff changeset
2780 do_warn_duplicated_branches_r (tree *tp, int *, void *)
kono
parents:
diff changeset
2781 {
kono
parents:
diff changeset
2782 if (TREE_CODE (*tp) == COND_EXPR)
kono
parents:
diff changeset
2783 do_warn_duplicated_branches (*tp);
kono
parents:
diff changeset
2784 return NULL_TREE;
kono
parents:
diff changeset
2785 }
kono
parents:
diff changeset
2786
kono
parents:
diff changeset
2787 /* Implementation of -Wmultistatement-macros. This warning warns about
kono
parents:
diff changeset
2788 cases when a macro expands to multiple statements not wrapped in
kono
parents:
diff changeset
2789 do {} while (0) or ({ }) and is used as a body of if/else/for/while
kono
parents:
diff changeset
2790 conditionals. For example,
kono
parents:
diff changeset
2791
kono
parents:
diff changeset
2792 #define DOIT x++; y++
kono
parents:
diff changeset
2793
kono
parents:
diff changeset
2794 if (c)
kono
parents:
diff changeset
2795 DOIT;
kono
parents:
diff changeset
2796
kono
parents:
diff changeset
2797 will increment y unconditionally.
kono
parents:
diff changeset
2798
kono
parents:
diff changeset
2799 BODY_LOC is the location of the first token in the body after labels
kono
parents:
diff changeset
2800 have been parsed, NEXT_LOC is the location of the next token after the
kono
parents:
diff changeset
2801 body of the conditional has been parsed, and GUARD_LOC is the location
kono
parents:
diff changeset
2802 of the conditional. */
kono
parents:
diff changeset
2803
kono
parents:
diff changeset
2804 void
kono
parents:
diff changeset
2805 warn_for_multistatement_macros (location_t body_loc, location_t next_loc,
kono
parents:
diff changeset
2806 location_t guard_loc, enum rid keyword)
kono
parents:
diff changeset
2807 {
kono
parents:
diff changeset
2808 if (!warn_multistatement_macros)
kono
parents:
diff changeset
2809 return;
kono
parents:
diff changeset
2810
kono
parents:
diff changeset
2811 /* Ain't got time to waste. We only care about macros here. */
kono
parents:
diff changeset
2812 if (!from_macro_expansion_at (body_loc)
kono
parents:
diff changeset
2813 || !from_macro_expansion_at (next_loc))
kono
parents:
diff changeset
2814 return;
kono
parents:
diff changeset
2815
kono
parents:
diff changeset
2816 /* Let's skip macros defined in system headers. */
kono
parents:
diff changeset
2817 if (in_system_header_at (body_loc)
kono
parents:
diff changeset
2818 || in_system_header_at (next_loc))
kono
parents:
diff changeset
2819 return;
kono
parents:
diff changeset
2820
kono
parents:
diff changeset
2821 /* Find the actual tokens in the macro definition. BODY_LOC and
kono
parents:
diff changeset
2822 NEXT_LOC have to come from the same spelling location, but they
kono
parents:
diff changeset
2823 will resolve to different locations in the context of the macro
kono
parents:
diff changeset
2824 definition. */
kono
parents:
diff changeset
2825 location_t body_loc_exp
kono
parents:
diff changeset
2826 = linemap_resolve_location (line_table, body_loc,
kono
parents:
diff changeset
2827 LRK_MACRO_DEFINITION_LOCATION, NULL);
kono
parents:
diff changeset
2828 location_t next_loc_exp
kono
parents:
diff changeset
2829 = linemap_resolve_location (line_table, next_loc,
kono
parents:
diff changeset
2830 LRK_MACRO_DEFINITION_LOCATION, NULL);
kono
parents:
diff changeset
2831 location_t guard_loc_exp
kono
parents:
diff changeset
2832 = linemap_resolve_location (line_table, guard_loc,
kono
parents:
diff changeset
2833 LRK_MACRO_DEFINITION_LOCATION, NULL);
kono
parents:
diff changeset
2834
kono
parents:
diff changeset
2835 /* These are some funky cases we don't want to warn about. */
kono
parents:
diff changeset
2836 if (body_loc_exp == guard_loc_exp
kono
parents:
diff changeset
2837 || next_loc_exp == guard_loc_exp
kono
parents:
diff changeset
2838 || body_loc_exp == next_loc_exp)
kono
parents:
diff changeset
2839 return;
kono
parents:
diff changeset
2840
kono
parents:
diff changeset
2841 /* Find the macro maps for the macro expansions. */
kono
parents:
diff changeset
2842 const line_map *body_map = linemap_lookup (line_table, body_loc);
kono
parents:
diff changeset
2843 const line_map *next_map = linemap_lookup (line_table, next_loc);
kono
parents:
diff changeset
2844 const line_map *guard_map = linemap_lookup (line_table, guard_loc);
kono
parents:
diff changeset
2845
kono
parents:
diff changeset
2846 /* Now see if the following token (after the body) is coming from the
kono
parents:
diff changeset
2847 same macro expansion. If it is, it might be a problem. */
kono
parents:
diff changeset
2848 if (body_map != next_map)
kono
parents:
diff changeset
2849 return;
kono
parents:
diff changeset
2850
kono
parents:
diff changeset
2851 /* The conditional itself must not come from the same expansion, because
kono
parents:
diff changeset
2852 we don't want to warn about
kono
parents:
diff changeset
2853 #define IF if (x) x++; y++
kono
parents:
diff changeset
2854 and similar. */
kono
parents:
diff changeset
2855 if (guard_map == body_map)
kono
parents:
diff changeset
2856 return;
kono
parents:
diff changeset
2857
kono
parents:
diff changeset
2858 /* Handle the case where NEXT and BODY come from the same expansion while
kono
parents:
diff changeset
2859 GUARD doesn't, yet we shouldn't warn. E.g.
kono
parents:
diff changeset
2860
kono
parents:
diff changeset
2861 #define GUARD if (...)
kono
parents:
diff changeset
2862 #define GUARD2 GUARD
kono
parents:
diff changeset
2863
kono
parents:
diff changeset
2864 and in the definition of another macro:
kono
parents:
diff changeset
2865
kono
parents:
diff changeset
2866 GUARD2
kono
parents:
diff changeset
2867 foo ();
kono
parents:
diff changeset
2868 return 1;
kono
parents:
diff changeset
2869 */
kono
parents:
diff changeset
2870 while (linemap_macro_expansion_map_p (guard_map))
kono
parents:
diff changeset
2871 {
kono
parents:
diff changeset
2872 const line_map_macro *mm = linemap_check_macro (guard_map);
kono
parents:
diff changeset
2873 guard_loc_exp = MACRO_MAP_EXPANSION_POINT_LOCATION (mm);
kono
parents:
diff changeset
2874 guard_map = linemap_lookup (line_table, guard_loc_exp);
kono
parents:
diff changeset
2875 if (guard_map == body_map)
kono
parents:
diff changeset
2876 return;
kono
parents:
diff changeset
2877 }
kono
parents:
diff changeset
2878
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2879 auto_diagnostic_group d;
111
kono
parents:
diff changeset
2880 if (warning_at (body_loc, OPT_Wmultistatement_macros,
kono
parents:
diff changeset
2881 "macro expands to multiple statements"))
kono
parents:
diff changeset
2882 inform (guard_loc, "some parts of macro expansion are not guarded by "
kono
parents:
diff changeset
2883 "this %qs clause", guard_tinfo_to_string (keyword));
kono
parents:
diff changeset
2884 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2885
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2886 /* Return struct or union type if the alignment of data memeber, FIELD,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2887 is less than the alignment of TYPE. Otherwise, return NULL_TREE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2888 If RVALUE is true, only arrays evaluate to pointers. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2889
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2890 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2891 check_alignment_of_packed_member (tree type, tree field, bool rvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2892 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2893 /* Check alignment of the data member. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2894 if (TREE_CODE (field) == FIELD_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2895 && (DECL_PACKED (field) || TYPE_PACKED (TREE_TYPE (field)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2896 /* Ignore FIELDs not laid out yet. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2897 && DECL_FIELD_OFFSET (field)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2898 && (!rvalue || TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2899 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2900 /* Check the expected alignment against the field alignment. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2901 unsigned int type_align = min_align_of_type (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2902 tree context = DECL_CONTEXT (field);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2903 unsigned int record_align = min_align_of_type (context);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2904 if (record_align < type_align)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2905 return context;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2906 tree field_off = byte_position (field);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2907 if (!multiple_of_p (TREE_TYPE (field_off), field_off,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2908 size_int (type_align)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2909 return context;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2910 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2911
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2912 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2913 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2914
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2915 /* Return struct or union type if the right hand value, RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2916 1. Is a pointer value which isn't aligned to a pointer type TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2917 2. Is an address which takes the unaligned address of packed member
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2918 of struct or union when assigning to TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2919 Otherwise, return NULL_TREE. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2920
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2921 static tree
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2922 check_address_or_pointer_of_packed_member (tree type, tree rhs)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2923 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2924 bool rvalue = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2925 bool indirect = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2926
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2927 if (INDIRECT_REF_P (rhs))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2928 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2929 rhs = TREE_OPERAND (rhs, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2930 STRIP_NOPS (rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2931 indirect = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2932 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2933
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2934 if (TREE_CODE (rhs) == ADDR_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2935 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2936 rhs = TREE_OPERAND (rhs, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2937 rvalue = indirect;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2938 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2939
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2940 if (!POINTER_TYPE_P (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2941 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2942
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2943 type = TREE_TYPE (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2944
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2945 if (TREE_CODE (rhs) == PARM_DECL
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2946 || VAR_P (rhs)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2947 || TREE_CODE (rhs) == CALL_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2948 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2949 tree rhstype = TREE_TYPE (rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2950 if (TREE_CODE (rhs) == CALL_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2951 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2952 rhs = CALL_EXPR_FN (rhs); /* Pointer expression. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2953 if (rhs == NULL_TREE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2954 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2955 rhs = TREE_TYPE (rhs); /* Pointer type. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2956 rhs = TREE_TYPE (rhs); /* Function type. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2957 rhstype = TREE_TYPE (rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2958 if (!rhstype || !POINTER_TYPE_P (rhstype))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2959 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2960 rvalue = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2961 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2962 if (rvalue && POINTER_TYPE_P (rhstype))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2963 rhstype = TREE_TYPE (rhstype);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2964 while (TREE_CODE (rhstype) == ARRAY_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2965 rhstype = TREE_TYPE (rhstype);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2966 if (TYPE_PACKED (rhstype))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2967 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2968 unsigned int type_align = min_align_of_type (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2969 unsigned int rhs_align = min_align_of_type (rhstype);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2970 if (rhs_align < type_align)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2971 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2972 auto_diagnostic_group d;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2973 location_t location = EXPR_LOC_OR_LOC (rhs, input_location);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2974 if (warning_at (location, OPT_Waddress_of_packed_member,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2975 "converting a packed %qT pointer (alignment %d) "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2976 "to a %qT pointer (alignment %d) may result in "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2977 "an unaligned pointer value",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2978 rhstype, rhs_align, type, type_align))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2979 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2980 tree decl = TYPE_STUB_DECL (rhstype);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2981 if (decl)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2982 inform (DECL_SOURCE_LOCATION (decl), "defined here");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2983 decl = TYPE_STUB_DECL (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2984 if (decl)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2985 inform (DECL_SOURCE_LOCATION (decl), "defined here");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2986 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2987 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2988 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2989 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2990 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2991
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2992 tree context = NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2993
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2994 /* Check alignment of the object. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2995 while (handled_component_p (rhs))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2996 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2997 if (TREE_CODE (rhs) == COMPONENT_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2998 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2999 tree field = TREE_OPERAND (rhs, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3000 context = check_alignment_of_packed_member (type, field, rvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3001 if (context)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3002 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3003 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3004 if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3005 rvalue = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3006 if (rvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3007 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3008 rhs = TREE_OPERAND (rhs, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3009 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3010
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3011 return context;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3012 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3013
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3014 /* Check and warn if the right hand value, RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3015 1. Is a pointer value which isn't aligned to a pointer type TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3016 2. Is an address which takes the unaligned address of packed member
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3017 of struct or union when assigning to TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3018 */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3019
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3020 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3021 check_and_warn_address_or_pointer_of_packed_member (tree type, tree rhs)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3022 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3023 bool nop_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3024 tree orig_rhs;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3025
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3026 do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3027 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3028 while (TREE_CODE (rhs) == COMPOUND_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3029 rhs = TREE_OPERAND (rhs, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3030 orig_rhs = rhs;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3031 STRIP_NOPS (rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3032 nop_p |= orig_rhs != rhs;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3033 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3034 while (orig_rhs != rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3035
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3036 if (TREE_CODE (rhs) == COND_EXPR)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3037 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3038 /* Check the THEN path. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3039 check_and_warn_address_or_pointer_of_packed_member
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3040 (type, TREE_OPERAND (rhs, 1));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3041
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3042 /* Check the ELSE path. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3043 check_and_warn_address_or_pointer_of_packed_member
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3044 (type, TREE_OPERAND (rhs, 2));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3045 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3046 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3047 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3048 if (nop_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3049 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3050 switch (TREE_CODE (rhs))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3051 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3052 case ADDR_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3053 /* Address is taken. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3054 case PARM_DECL:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3055 case VAR_DECL:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3056 /* Pointer conversion. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3057 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3058 case CALL_EXPR:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3059 /* Function call. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3060 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3061 default:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3062 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3063 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3064 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3065
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3066 tree context
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3067 = check_address_or_pointer_of_packed_member (type, rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3068 if (context)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3069 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3070 location_t loc = EXPR_LOC_OR_LOC (rhs, input_location);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3071 warning_at (loc, OPT_Waddress_of_packed_member,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3072 "taking address of packed member of %qT may result "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3073 "in an unaligned pointer value",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3074 context);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3075 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3076 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3077 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3078
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3079 /* Warn if the right hand value, RHS:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3080 1. Is a pointer value which isn't aligned to a pointer type TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3081 2. Is an address which takes the unaligned address of packed member
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3082 of struct or union when assigning to TYPE.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3083 */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3084
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3085 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3086 warn_for_address_or_pointer_of_packed_member (tree type, tree rhs)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3087 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3088 if (!warn_address_of_packed_member)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3089 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3090
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3091 /* Don't warn if we don't assign RHS to a pointer. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3092 if (!POINTER_TYPE_P (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3093 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3094
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3095 check_and_warn_address_or_pointer_of_packed_member (type, rhs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3096 }