]>
Commit | Line | Data |
---|---|---|
4250754e | 1 | /* Support for fully folding sub-trees of an expression for C compiler. |
7adcbafe | 2 | Copyright (C) 1992-2022 Free Software Foundation, Inc. |
4250754e JM |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "target.h" | |
24 | #include "function.h" | |
25 | #include "bitmap.h" | |
26 | #include "c-tree.h" | |
27 | #include "intl.h" | |
28 | #include "gimplify.h" | |
29 | ||
f9c59f7e JJ |
30 | static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool, |
31 | bool); | |
4250754e JM |
32 | |
33 | /* If DISABLE is true, stop issuing warnings. This is used when | |
34 | parsing code that we know will not be executed. This function may | |
35 | be called multiple times, and works as a stack. */ | |
36 | ||
37 | static void | |
38 | c_disable_warnings (bool disable) | |
39 | { | |
40 | if (disable) | |
41 | { | |
42 | ++c_inhibit_evaluation_warnings; | |
43 | fold_defer_overflow_warnings (); | |
44 | } | |
45 | } | |
46 | ||
47 | /* If ENABLE is true, reenable issuing warnings. */ | |
48 | ||
49 | static void | |
50 | c_enable_warnings (bool enable) | |
51 | { | |
52 | if (enable) | |
53 | { | |
54 | --c_inhibit_evaluation_warnings; | |
55 | fold_undefer_and_ignore_overflow_warnings (); | |
56 | } | |
57 | } | |
58 | ||
f9c59f7e JJ |
59 | /* Try to fold ARRAY_REF ary[index] if possible and not handled by |
60 | normal fold, return NULL_TREE otherwise. */ | |
61 | ||
62 | static tree | |
63 | c_fold_array_ref (tree type, tree ary, tree index) | |
64 | { | |
65 | if (TREE_CODE (ary) != STRING_CST | |
66 | || TREE_CODE (index) != INTEGER_CST | |
67 | || TREE_OVERFLOW (index) | |
68 | || TREE_CODE (TREE_TYPE (ary)) != ARRAY_TYPE | |
69 | || !tree_fits_uhwi_p (index)) | |
70 | return NULL_TREE; | |
71 | ||
72 | tree elem_type = TREE_TYPE (TREE_TYPE (ary)); | |
73 | unsigned elem_nchars = (TYPE_PRECISION (elem_type) | |
74 | / TYPE_PRECISION (char_type_node)); | |
75 | unsigned len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars; | |
76 | tree nelts = array_type_nelts (TREE_TYPE (ary)); | |
77 | bool dummy1 = true, dummy2 = true; | |
78 | nelts = c_fully_fold_internal (nelts, true, &dummy1, &dummy2, false, false); | |
79 | unsigned HOST_WIDE_INT i = tree_to_uhwi (index); | |
80 | if (!tree_int_cst_le (index, nelts) | |
81 | || i >= len | |
82 | || i + elem_nchars > len) | |
83 | return NULL_TREE; | |
84 | ||
85 | if (elem_nchars == 1) | |
86 | return build_int_cst (type, TREE_STRING_POINTER (ary)[i]); | |
87 | ||
88 | const unsigned char *ptr | |
89 | = ((const unsigned char *)TREE_STRING_POINTER (ary) + i * elem_nchars); | |
90 | return native_interpret_expr (type, ptr, elem_nchars); | |
91 | } | |
92 | ||
4250754e JM |
93 | /* Fully fold EXPR, an expression that was not folded (beyond integer |
94 | constant expressions and null pointer constants) when being built | |
95 | up. If IN_INIT, this is in a static initializer and certain | |
96 | changes are made to the folding done. Clear *MAYBE_CONST if | |
97 | MAYBE_CONST is not NULL and EXPR is definitely not a constant | |
98 | expression because it contains an evaluated operator (in C99) or an | |
99 | operator outside of sizeof returning an integer constant (in C90) | |
100 | not permitted in constant expressions, or because it contains an | |
101 | evaluated arithmetic overflow. (*MAYBE_CONST should typically be | |
102 | set to true by callers before calling this function.) Return the | |
103 | folded expression. Function arguments have already been folded | |
104 | before calling this function, as have the contents of SAVE_EXPR, | |
105 | TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and | |
f9c59f7e JJ |
106 | C_MAYBE_CONST_EXPR. LVAL is true if it should be treated as an |
107 | lvalue. */ | |
4250754e JM |
108 | |
109 | tree | |
f9c59f7e | 110 | c_fully_fold (tree expr, bool in_init, bool *maybe_const, bool lval) |
4250754e JM |
111 | { |
112 | tree ret; | |
113 | tree eptype = NULL_TREE; | |
114 | bool dummy = true; | |
115 | bool maybe_const_itself = true; | |
116 | location_t loc = EXPR_LOCATION (expr); | |
117 | ||
118 | if (!maybe_const) | |
119 | maybe_const = &dummy; | |
120 | if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) | |
121 | { | |
122 | eptype = TREE_TYPE (expr); | |
123 | expr = TREE_OPERAND (expr, 0); | |
124 | } | |
125 | ret = c_fully_fold_internal (expr, in_init, maybe_const, | |
f9c59f7e | 126 | &maybe_const_itself, false, lval); |
4250754e JM |
127 | if (eptype) |
128 | ret = fold_convert_loc (loc, eptype, ret); | |
129 | *maybe_const &= maybe_const_itself; | |
130 | return ret; | |
131 | } | |
132 | ||
133 | /* Internal helper for c_fully_fold. EXPR and IN_INIT are as for | |
134 | c_fully_fold. *MAYBE_CONST_OPERANDS is cleared because of operands | |
135 | not permitted, while *MAYBE_CONST_ITSELF is cleared because of | |
136 | arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from | |
137 | both evaluated and unevaluated subexpressions while | |
138 | *MAYBE_CONST_ITSELF is carried from only evaluated | |
139 | subexpressions). FOR_INT_CONST indicates if EXPR is an expression | |
140 | with integer constant operands, and if any of the operands doesn't | |
f9c59f7e JJ |
141 | get folded to an integer constant, don't fold the expression itself. |
142 | LVAL indicates folding of lvalue, where we can't replace it with | |
143 | an rvalue. */ | |
4250754e JM |
144 | |
145 | static tree | |
146 | c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, | |
f9c59f7e | 147 | bool *maybe_const_itself, bool for_int_const, bool lval) |
4250754e JM |
148 | { |
149 | tree ret = expr; | |
150 | enum tree_code code = TREE_CODE (expr); | |
151 | enum tree_code_class kind = TREE_CODE_CLASS (code); | |
152 | location_t loc = EXPR_LOCATION (expr); | |
153 | tree op0, op1, op2, op3; | |
154 | tree orig_op0, orig_op1, orig_op2; | |
155 | bool op0_const = true, op1_const = true, op2_const = true; | |
156 | bool op0_const_self = true, op1_const_self = true, op2_const_self = true; | |
1ebd2b2c | 157 | bool nowarning = warning_suppressed_p (expr, OPT_Woverflow); |
4250754e | 158 | bool unused_p; |
f9c59f7e | 159 | bool op0_lval = false; |
4250754e JM |
160 | source_range old_range; |
161 | ||
b2fa0a8b MP |
162 | /* Constants, declarations, statements, errors, and anything else not |
163 | counted as an expression cannot usefully be folded further at this | |
164 | point. */ | |
f9c59f7e JJ |
165 | if (!IS_EXPR_CODE_CLASS (kind) || kind == tcc_statement) |
166 | { | |
167 | /* Except for variables which we can optimize to its initializer. */ | |
168 | if (VAR_P (expr) && !lval && (optimize || in_init)) | |
169 | { | |
cc6534d4 | 170 | if (in_init) |
b4923738 | 171 | ret = decl_constant_value_1 (expr, true); |
cc6534d4 | 172 | else |
b4923738 JJ |
173 | { |
174 | ret = decl_constant_value (expr); | |
175 | if (ret != expr | |
176 | && (TYPE_MODE (TREE_TYPE (ret)) == BLKmode | |
177 | || TREE_CODE (TREE_TYPE (ret)) == ARRAY_TYPE)) | |
178 | return expr; | |
179 | } | |
f9c59f7e JJ |
180 | /* Avoid unwanted tree sharing between the initializer and current |
181 | function's body where the tree can be modified e.g. by the | |
182 | gimplifier. */ | |
183 | if (ret != expr && TREE_STATIC (expr)) | |
184 | ret = unshare_expr (ret); | |
185 | return ret; | |
186 | } | |
187 | return expr; | |
188 | } | |
4250754e JM |
189 | |
190 | if (IS_EXPR_CODE_CLASS (kind)) | |
191 | old_range = EXPR_LOCATION_RANGE (expr); | |
192 | ||
193 | /* Operands of variable-length expressions (function calls) have | |
194 | already been folded, as have __builtin_* function calls, and such | |
195 | expressions cannot occur in constant expressions. */ | |
196 | if (kind == tcc_vl_exp) | |
197 | { | |
198 | *maybe_const_operands = false; | |
199 | ret = fold (expr); | |
200 | goto out; | |
201 | } | |
202 | ||
203 | if (code == C_MAYBE_CONST_EXPR) | |
204 | { | |
205 | tree pre = C_MAYBE_CONST_EXPR_PRE (expr); | |
206 | tree inner = C_MAYBE_CONST_EXPR_EXPR (expr); | |
207 | if (C_MAYBE_CONST_EXPR_NON_CONST (expr)) | |
208 | *maybe_const_operands = false; | |
209 | if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr)) | |
210 | { | |
211 | *maybe_const_itself = false; | |
212 | inner = c_fully_fold_internal (inner, in_init, maybe_const_operands, | |
f9c59f7e | 213 | maybe_const_itself, true, lval); |
4250754e JM |
214 | } |
215 | if (pre && !in_init) | |
216 | ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner); | |
217 | else | |
218 | ret = inner; | |
219 | goto out; | |
220 | } | |
221 | ||
222 | /* Assignment, increment, decrement, function call and comma | |
223 | operators, and statement expressions, cannot occur in constant | |
224 | expressions if evaluated / outside of sizeof. (Function calls | |
225 | were handled above, though VA_ARG_EXPR is treated like a function | |
226 | call here, and statement expressions are handled through | |
227 | C_MAYBE_CONST_EXPR to avoid folding inside them.) */ | |
228 | switch (code) | |
229 | { | |
230 | case MODIFY_EXPR: | |
231 | case PREDECREMENT_EXPR: | |
232 | case PREINCREMENT_EXPR: | |
233 | case POSTDECREMENT_EXPR: | |
234 | case POSTINCREMENT_EXPR: | |
235 | case COMPOUND_EXPR: | |
236 | *maybe_const_operands = false; | |
237 | break; | |
238 | ||
239 | case VA_ARG_EXPR: | |
240 | case TARGET_EXPR: | |
241 | case BIND_EXPR: | |
242 | case OBJ_TYPE_REF: | |
243 | *maybe_const_operands = false; | |
244 | ret = fold (expr); | |
245 | goto out; | |
246 | ||
247 | default: | |
248 | break; | |
249 | } | |
250 | ||
251 | /* Fold individual tree codes as appropriate. */ | |
252 | switch (code) | |
253 | { | |
254 | case COMPOUND_LITERAL_EXPR: | |
255 | /* Any non-constancy will have been marked in a containing | |
256 | C_MAYBE_CONST_EXPR; there is no more folding to do here. */ | |
257 | goto out; | |
258 | ||
259 | case COMPONENT_REF: | |
260 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
261 | op1 = TREE_OPERAND (expr, 1); | |
262 | op2 = TREE_OPERAND (expr, 2); | |
263 | op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, | |
f9c59f7e | 264 | maybe_const_itself, for_int_const, lval); |
4250754e JM |
265 | STRIP_TYPE_NOPS (op0); |
266 | if (op0 != orig_op0) | |
267 | ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2); | |
268 | if (ret != expr) | |
269 | { | |
270 | TREE_READONLY (ret) = TREE_READONLY (expr); | |
271 | TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); | |
272 | } | |
b4923738 JJ |
273 | if (!lval) |
274 | ret = fold (ret); | |
4250754e JM |
275 | goto out; |
276 | ||
277 | case ARRAY_REF: | |
278 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
279 | orig_op1 = op1 = TREE_OPERAND (expr, 1); | |
280 | op2 = TREE_OPERAND (expr, 2); | |
281 | op3 = TREE_OPERAND (expr, 3); | |
282 | op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, | |
f9c59f7e | 283 | maybe_const_itself, for_int_const, lval); |
4250754e JM |
284 | STRIP_TYPE_NOPS (op0); |
285 | op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, | |
f9c59f7e | 286 | maybe_const_itself, for_int_const, false); |
4250754e | 287 | STRIP_TYPE_NOPS (op1); |
f9c59f7e JJ |
288 | /* Fold "foo"[2] in initializers. */ |
289 | if (!lval && in_init) | |
290 | { | |
291 | ret = c_fold_array_ref (TREE_TYPE (expr), op0, op1); | |
292 | if (ret) | |
293 | goto out; | |
294 | ret = expr; | |
295 | } | |
4250754e JM |
296 | if (op0 != orig_op0 || op1 != orig_op1) |
297 | ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3); | |
298 | if (ret != expr) | |
299 | { | |
300 | TREE_READONLY (ret) = TREE_READONLY (expr); | |
301 | TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr); | |
302 | TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); | |
303 | } | |
f9c59f7e JJ |
304 | if (!lval) |
305 | ret = fold (ret); | |
4250754e JM |
306 | goto out; |
307 | ||
4250754e JM |
308 | case MODIFY_EXPR: |
309 | case PREDECREMENT_EXPR: | |
310 | case PREINCREMENT_EXPR: | |
311 | case POSTDECREMENT_EXPR: | |
312 | case POSTINCREMENT_EXPR: | |
f9c59f7e JJ |
313 | op0_lval = true; |
314 | /* FALLTHRU */ | |
315 | case COMPOUND_EXPR: | |
4250754e JM |
316 | case PLUS_EXPR: |
317 | case MINUS_EXPR: | |
318 | case MULT_EXPR: | |
319 | case POINTER_PLUS_EXPR: | |
1af4ebf5 | 320 | case POINTER_DIFF_EXPR: |
4250754e JM |
321 | case TRUNC_DIV_EXPR: |
322 | case CEIL_DIV_EXPR: | |
323 | case FLOOR_DIV_EXPR: | |
324 | case TRUNC_MOD_EXPR: | |
325 | case RDIV_EXPR: | |
326 | case EXACT_DIV_EXPR: | |
327 | case LSHIFT_EXPR: | |
328 | case RSHIFT_EXPR: | |
329 | case BIT_IOR_EXPR: | |
330 | case BIT_XOR_EXPR: | |
331 | case BIT_AND_EXPR: | |
332 | case LT_EXPR: | |
333 | case LE_EXPR: | |
334 | case GT_EXPR: | |
335 | case GE_EXPR: | |
336 | case EQ_EXPR: | |
337 | case NE_EXPR: | |
338 | case COMPLEX_EXPR: | |
339 | case TRUTH_AND_EXPR: | |
340 | case TRUTH_OR_EXPR: | |
341 | case TRUTH_XOR_EXPR: | |
342 | case UNORDERED_EXPR: | |
343 | case ORDERED_EXPR: | |
344 | case UNLT_EXPR: | |
345 | case UNLE_EXPR: | |
346 | case UNGT_EXPR: | |
347 | case UNGE_EXPR: | |
348 | case UNEQ_EXPR: | |
c015ff8c | 349 | case MEM_REF: |
4250754e JM |
350 | /* Binary operations evaluating both arguments (increment and |
351 | decrement are binary internally in GCC). */ | |
352 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
353 | orig_op1 = op1 = TREE_OPERAND (expr, 1); | |
354 | op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, | |
f9c59f7e JJ |
355 | maybe_const_itself, for_int_const, |
356 | op0_lval); | |
4250754e | 357 | STRIP_TYPE_NOPS (op0); |
4250754e JM |
358 | /* The RHS of a MODIFY_EXPR was fully folded when building that |
359 | expression for the sake of conversion warnings. */ | |
360 | if (code != MODIFY_EXPR) | |
361 | op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, | |
f9c59f7e | 362 | maybe_const_itself, for_int_const, false); |
4250754e | 363 | STRIP_TYPE_NOPS (op1); |
4250754e JM |
364 | |
365 | if (for_int_const && (TREE_CODE (op0) != INTEGER_CST | |
366 | || TREE_CODE (op1) != INTEGER_CST)) | |
367 | goto out; | |
368 | ||
369 | if (op0 != orig_op0 || op1 != orig_op1 || in_init) | |
370 | ret = in_init | |
371 | ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) | |
372 | : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1); | |
373 | else | |
374 | ret = fold (expr); | |
375 | if (TREE_OVERFLOW_P (ret) | |
376 | && !TREE_OVERFLOW_P (op0) | |
4a88caf2 | 377 | && !(BINARY_CLASS_P (op0) && TREE_OVERFLOW_P (TREE_OPERAND (op0, 1))) |
4250754e | 378 | && !TREE_OVERFLOW_P (op1)) |
3cd211af | 379 | overflow_warning (EXPR_LOC_OR_LOC (expr, input_location), ret, expr); |
4250754e JM |
380 | if (code == LSHIFT_EXPR |
381 | && TREE_CODE (orig_op0) != INTEGER_CST | |
382 | && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE | |
383 | && TREE_CODE (op0) == INTEGER_CST | |
384 | && c_inhibit_evaluation_warnings == 0 | |
385 | && tree_int_cst_sgn (op0) < 0) | |
386 | warning_at (loc, OPT_Wshift_negative_value, | |
387 | "left shift of negative value"); | |
388 | if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR) | |
389 | && TREE_CODE (orig_op1) != INTEGER_CST | |
390 | && TREE_CODE (op1) == INTEGER_CST | |
4250754e JM |
391 | && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE |
392 | && c_inhibit_evaluation_warnings == 0) | |
393 | { | |
394 | if (tree_int_cst_sgn (op1) < 0) | |
395 | warning_at (loc, OPT_Wshift_count_negative, | |
396 | (code == LSHIFT_EXPR | |
397 | ? G_("left shift count is negative") | |
398 | : G_("right shift count is negative"))); | |
76e2c821 JB |
399 | else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE |
400 | || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) | |
401 | && compare_tree_int (op1, | |
402 | TYPE_PRECISION (TREE_TYPE (orig_op0))) | |
403 | >= 0) | |
4250754e JM |
404 | warning_at (loc, OPT_Wshift_count_overflow, |
405 | (code == LSHIFT_EXPR | |
406 | ? G_("left shift count >= width of type") | |
407 | : G_("right shift count >= width of type"))); | |
76e2c821 JB |
408 | else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE |
409 | && compare_tree_int (op1, | |
410 | TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0)))) | |
411 | >= 0) | |
412 | warning_at (loc, OPT_Wshift_count_overflow, | |
413 | code == LSHIFT_EXPR | |
414 | ? G_("left shift count >= width of vector element") | |
415 | : G_("right shift count >= width of vector element")); | |
4250754e JM |
416 | } |
417 | if (code == LSHIFT_EXPR | |
418 | /* If either OP0 has been folded to INTEGER_CST... */ | |
419 | && ((TREE_CODE (orig_op0) != INTEGER_CST | |
420 | && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE | |
421 | && TREE_CODE (op0) == INTEGER_CST) | |
422 | /* ...or if OP1 has been folded to INTEGER_CST... */ | |
423 | || (TREE_CODE (orig_op1) != INTEGER_CST | |
424 | && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE | |
425 | && TREE_CODE (op1) == INTEGER_CST)) | |
426 | && c_inhibit_evaluation_warnings == 0) | |
427 | /* ...then maybe we can detect an overflow. */ | |
428 | maybe_warn_shift_overflow (loc, op0, op1); | |
429 | if ((code == TRUNC_DIV_EXPR | |
430 | || code == CEIL_DIV_EXPR | |
431 | || code == FLOOR_DIV_EXPR | |
432 | || code == EXACT_DIV_EXPR | |
433 | || code == TRUNC_MOD_EXPR) | |
434 | && TREE_CODE (orig_op1) != INTEGER_CST | |
435 | && TREE_CODE (op1) == INTEGER_CST | |
436 | && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE | |
437 | || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) | |
438 | && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE) | |
439 | warn_for_div_by_zero (loc, op1); | |
c015ff8c JJ |
440 | if (code == MEM_REF |
441 | && ret != expr | |
442 | && TREE_CODE (ret) == MEM_REF) | |
443 | { | |
444 | TREE_READONLY (ret) = TREE_READONLY (expr); | |
445 | TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr); | |
446 | TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); | |
447 | } | |
4250754e JM |
448 | goto out; |
449 | ||
f9c59f7e JJ |
450 | case ADDR_EXPR: |
451 | op0_lval = true; | |
452 | goto unary; | |
453 | case REALPART_EXPR: | |
454 | case IMAGPART_EXPR: | |
b7280579 | 455 | case VIEW_CONVERT_EXPR: |
f9c59f7e JJ |
456 | op0_lval = lval; |
457 | /* FALLTHRU */ | |
4250754e JM |
458 | case INDIRECT_REF: |
459 | case FIX_TRUNC_EXPR: | |
460 | case FLOAT_EXPR: | |
461 | CASE_CONVERT: | |
462 | case ADDR_SPACE_CONVERT_EXPR: | |
4250754e JM |
463 | case NON_LVALUE_EXPR: |
464 | case NEGATE_EXPR: | |
465 | case BIT_NOT_EXPR: | |
466 | case TRUTH_NOT_EXPR: | |
4250754e | 467 | case CONJ_EXPR: |
f9c59f7e | 468 | unary: |
4250754e JM |
469 | /* Unary operations. */ |
470 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
471 | op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, | |
f9c59f7e JJ |
472 | maybe_const_itself, for_int_const, |
473 | op0_lval); | |
4250754e | 474 | STRIP_TYPE_NOPS (op0); |
4250754e JM |
475 | |
476 | if (for_int_const && TREE_CODE (op0) != INTEGER_CST) | |
477 | goto out; | |
478 | ||
479 | /* ??? Cope with user tricks that amount to offsetof. The middle-end is | |
480 | not prepared to deal with them if they occur in initializers. */ | |
481 | if (op0 != orig_op0 | |
482 | && code == ADDR_EXPR | |
483 | && (op1 = get_base_address (op0)) != NULL_TREE | |
484 | && INDIRECT_REF_P (op1) | |
485 | && TREE_CONSTANT (TREE_OPERAND (op1, 0))) | |
79e7b1fe | 486 | ret = fold_offsetof (op0, TREE_TYPE (expr)); |
4250754e JM |
487 | else if (op0 != orig_op0 || in_init) |
488 | ret = in_init | |
489 | ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0) | |
490 | : fold_build1_loc (loc, code, TREE_TYPE (expr), op0); | |
491 | else | |
492 | ret = fold (expr); | |
493 | if (code == INDIRECT_REF | |
494 | && ret != expr | |
495 | && INDIRECT_REF_P (ret)) | |
496 | { | |
497 | TREE_READONLY (ret) = TREE_READONLY (expr); | |
498 | TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr); | |
499 | TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); | |
500 | } | |
501 | switch (code) | |
502 | { | |
503 | case FIX_TRUNC_EXPR: | |
504 | case FLOAT_EXPR: | |
505 | CASE_CONVERT: | |
506 | /* Don't warn about explicit conversions. We will already | |
507 | have warned about suspect implicit conversions. */ | |
508 | break; | |
509 | ||
510 | default: | |
511 | if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0)) | |
3cd211af | 512 | overflow_warning (EXPR_LOCATION (expr), ret, op0); |
4250754e JM |
513 | break; |
514 | } | |
515 | goto out; | |
516 | ||
517 | case TRUTH_ANDIF_EXPR: | |
518 | case TRUTH_ORIF_EXPR: | |
519 | /* Binary operations not necessarily evaluating both | |
520 | arguments. */ | |
521 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
522 | orig_op1 = op1 = TREE_OPERAND (expr, 1); | |
523 | op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self, | |
f9c59f7e | 524 | for_int_const, false); |
4250754e JM |
525 | STRIP_TYPE_NOPS (op0); |
526 | ||
527 | unused_p = (op0 == (code == TRUTH_ANDIF_EXPR | |
528 | ? truthvalue_false_node | |
529 | : truthvalue_true_node)); | |
530 | c_disable_warnings (unused_p); | |
531 | op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self, | |
f9c59f7e | 532 | for_int_const, false); |
4250754e JM |
533 | STRIP_TYPE_NOPS (op1); |
534 | c_enable_warnings (unused_p); | |
535 | ||
536 | if (for_int_const | |
537 | && (TREE_CODE (op0) != INTEGER_CST | |
538 | /* Require OP1 be an INTEGER_CST only if it's evaluated. */ | |
539 | || (!unused_p && TREE_CODE (op1) != INTEGER_CST))) | |
540 | goto out; | |
541 | ||
542 | if (op0 != orig_op0 || op1 != orig_op1 || in_init) | |
543 | ret = in_init | |
544 | ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) | |
545 | : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1); | |
546 | else | |
547 | ret = fold (expr); | |
548 | *maybe_const_operands &= op0_const; | |
549 | *maybe_const_itself &= op0_const_self; | |
550 | if (!(flag_isoc99 | |
551 | && op0_const | |
552 | && op0_const_self | |
553 | && (code == TRUTH_ANDIF_EXPR | |
554 | ? op0 == truthvalue_false_node | |
555 | : op0 == truthvalue_true_node))) | |
556 | *maybe_const_operands &= op1_const; | |
557 | if (!(op0_const | |
558 | && op0_const_self | |
559 | && (code == TRUTH_ANDIF_EXPR | |
560 | ? op0 == truthvalue_false_node | |
561 | : op0 == truthvalue_true_node))) | |
562 | *maybe_const_itself &= op1_const_self; | |
563 | goto out; | |
564 | ||
565 | case COND_EXPR: | |
566 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
567 | orig_op1 = op1 = TREE_OPERAND (expr, 1); | |
568 | orig_op2 = op2 = TREE_OPERAND (expr, 2); | |
569 | op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self, | |
f9c59f7e | 570 | for_int_const, false); |
4250754e JM |
571 | |
572 | STRIP_TYPE_NOPS (op0); | |
573 | c_disable_warnings (op0 == truthvalue_false_node); | |
574 | op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self, | |
f9c59f7e | 575 | for_int_const, false); |
4250754e JM |
576 | STRIP_TYPE_NOPS (op1); |
577 | c_enable_warnings (op0 == truthvalue_false_node); | |
578 | ||
579 | c_disable_warnings (op0 == truthvalue_true_node); | |
580 | op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self, | |
f9c59f7e | 581 | for_int_const, false); |
4250754e JM |
582 | STRIP_TYPE_NOPS (op2); |
583 | c_enable_warnings (op0 == truthvalue_true_node); | |
584 | ||
585 | if (for_int_const | |
586 | && (TREE_CODE (op0) != INTEGER_CST | |
587 | /* Only the evaluated operand must be an INTEGER_CST. */ | |
588 | || (op0 == truthvalue_true_node | |
589 | ? TREE_CODE (op1) != INTEGER_CST | |
590 | : TREE_CODE (op2) != INTEGER_CST))) | |
591 | goto out; | |
592 | ||
593 | if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2) | |
594 | ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2); | |
595 | else | |
596 | ret = fold (expr); | |
597 | *maybe_const_operands &= op0_const; | |
598 | *maybe_const_itself &= op0_const_self; | |
599 | if (!(flag_isoc99 | |
600 | && op0_const | |
601 | && op0_const_self | |
602 | && op0 == truthvalue_false_node)) | |
603 | *maybe_const_operands &= op1_const; | |
604 | if (!(op0_const | |
605 | && op0_const_self | |
606 | && op0 == truthvalue_false_node)) | |
607 | *maybe_const_itself &= op1_const_self; | |
608 | if (!(flag_isoc99 | |
609 | && op0_const | |
610 | && op0_const_self | |
611 | && op0 == truthvalue_true_node)) | |
612 | *maybe_const_operands &= op2_const; | |
613 | if (!(op0_const | |
614 | && op0_const_self | |
615 | && op0 == truthvalue_true_node)) | |
616 | *maybe_const_itself &= op2_const_self; | |
617 | goto out; | |
618 | ||
f13355da MP |
619 | case VEC_COND_EXPR: |
620 | orig_op0 = op0 = TREE_OPERAND (expr, 0); | |
621 | orig_op1 = op1 = TREE_OPERAND (expr, 1); | |
622 | orig_op2 = op2 = TREE_OPERAND (expr, 2); | |
623 | op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, | |
f9c59f7e | 624 | maybe_const_itself, for_int_const, false); |
f13355da MP |
625 | STRIP_TYPE_NOPS (op0); |
626 | op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, | |
f9c59f7e | 627 | maybe_const_itself, for_int_const, false); |
f13355da MP |
628 | STRIP_TYPE_NOPS (op1); |
629 | op2 = c_fully_fold_internal (op2, in_init, maybe_const_operands, | |
f9c59f7e | 630 | maybe_const_itself, for_int_const, false); |
f13355da MP |
631 | STRIP_TYPE_NOPS (op2); |
632 | ||
633 | if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2) | |
634 | ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2); | |
635 | else | |
636 | ret = fold (expr); | |
637 | goto out; | |
638 | ||
4250754e JM |
639 | case EXCESS_PRECISION_EXPR: |
640 | /* Each case where an operand with excess precision may be | |
641 | encountered must remove the EXCESS_PRECISION_EXPR around | |
642 | inner operands and possibly put one around the whole | |
643 | expression or possibly convert to the semantic type (which | |
644 | c_fully_fold does); we cannot tell at this stage which is | |
645 | appropriate in any particular case. */ | |
646 | gcc_unreachable (); | |
647 | ||
b2fa0a8b MP |
648 | case SAVE_EXPR: |
649 | /* Make sure to fold the contents of a SAVE_EXPR exactly once. */ | |
d11c168a | 650 | op0 = TREE_OPERAND (expr, 0); |
b2fa0a8b MP |
651 | if (!SAVE_EXPR_FOLDED_P (expr)) |
652 | { | |
b2fa0a8b | 653 | op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, |
f9c59f7e JJ |
654 | maybe_const_itself, for_int_const, |
655 | false); | |
d11c168a JJ |
656 | TREE_OPERAND (expr, 0) = op0; |
657 | SAVE_EXPR_FOLDED_P (expr) = true; | |
b2fa0a8b | 658 | } |
d11c168a JJ |
659 | /* Return the SAVE_EXPR operand if it is invariant. */ |
660 | if (tree_invariant_p (op0)) | |
661 | ret = op0; | |
b2fa0a8b MP |
662 | goto out; |
663 | ||
4250754e JM |
664 | default: |
665 | /* Various codes may appear through folding built-in functions | |
666 | and their arguments. */ | |
667 | goto out; | |
668 | } | |
669 | ||
670 | out: | |
671 | /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks | |
672 | have been done by this point, so remove them again. */ | |
1ebd2b2c | 673 | nowarning |= warning_suppressed_p (ret, OPT_Woverflow); |
4250754e | 674 | STRIP_TYPE_NOPS (ret); |
1ebd2b2c | 675 | if (nowarning && !warning_suppressed_p (ret, OPT_Woverflow)) |
4250754e JM |
676 | { |
677 | if (!CAN_HAVE_LOCATION_P (ret)) | |
678 | ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret); | |
1ebd2b2c | 679 | suppress_warning (ret, OPT_Woverflow); |
4250754e JM |
680 | } |
681 | if (ret != expr) | |
682 | { | |
683 | protected_set_expr_location (ret, loc); | |
684 | if (IS_EXPR_CODE_CLASS (kind)) | |
685 | set_source_range (ret, old_range.m_start, old_range.m_finish); | |
686 | } | |
687 | return ret; | |
688 | } | |
bb9869d5 DM |
689 | |
690 | /* Fold X for consideration by one of the warning functions when checking | |
691 | whether an expression has a constant value. */ | |
692 | ||
693 | tree | |
694 | fold_for_warn (tree x) | |
695 | { | |
696 | /* The C front-end has already folded X appropriately. */ | |
697 | return x; | |
698 | } |