138fd1498Szrj /* Support for fully folding sub-trees of an expression for C compiler.
238fd1498Szrj Copyright (C) 1992-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3. If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>. */
1938fd1498Szrj
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "target.h"
2438fd1498Szrj #include "function.h"
2538fd1498Szrj #include "bitmap.h"
2638fd1498Szrj #include "c-tree.h"
2738fd1498Szrj #include "intl.h"
2838fd1498Szrj #include "gimplify.h"
2938fd1498Szrj
3038fd1498Szrj static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool,
3138fd1498Szrj bool);
3238fd1498Szrj
3338fd1498Szrj /* If DISABLE is true, stop issuing warnings. This is used when
3438fd1498Szrj parsing code that we know will not be executed. This function may
3538fd1498Szrj be called multiple times, and works as a stack. */
3638fd1498Szrj
3738fd1498Szrj static void
c_disable_warnings(bool disable)3838fd1498Szrj c_disable_warnings (bool disable)
3938fd1498Szrj {
4038fd1498Szrj if (disable)
4138fd1498Szrj {
4238fd1498Szrj ++c_inhibit_evaluation_warnings;
4338fd1498Szrj fold_defer_overflow_warnings ();
4438fd1498Szrj }
4538fd1498Szrj }
4638fd1498Szrj
4738fd1498Szrj /* If ENABLE is true, reenable issuing warnings. */
4838fd1498Szrj
4938fd1498Szrj static void
c_enable_warnings(bool enable)5038fd1498Szrj c_enable_warnings (bool enable)
5138fd1498Szrj {
5238fd1498Szrj if (enable)
5338fd1498Szrj {
5438fd1498Szrj --c_inhibit_evaluation_warnings;
5538fd1498Szrj fold_undefer_and_ignore_overflow_warnings ();
5638fd1498Szrj }
5738fd1498Szrj }
5838fd1498Szrj
5938fd1498Szrj /* Try to fold ARRAY_REF ary[index] if possible and not handled by
6038fd1498Szrj normal fold, return NULL_TREE otherwise. */
6138fd1498Szrj
6238fd1498Szrj static tree
c_fold_array_ref(tree type,tree ary,tree index)6338fd1498Szrj c_fold_array_ref (tree type, tree ary, tree index)
6438fd1498Szrj {
6538fd1498Szrj if (TREE_CODE (ary) != STRING_CST
6638fd1498Szrj || TREE_CODE (index) != INTEGER_CST
6738fd1498Szrj || TREE_OVERFLOW (index)
6838fd1498Szrj || TREE_CODE (TREE_TYPE (ary)) != ARRAY_TYPE
6938fd1498Szrj || !tree_fits_uhwi_p (index))
7038fd1498Szrj return NULL_TREE;
7138fd1498Szrj
7238fd1498Szrj tree elem_type = TREE_TYPE (TREE_TYPE (ary));
7338fd1498Szrj unsigned elem_nchars = (TYPE_PRECISION (elem_type)
7438fd1498Szrj / TYPE_PRECISION (char_type_node));
7538fd1498Szrj unsigned len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
7638fd1498Szrj tree nelts = array_type_nelts (TREE_TYPE (ary));
7738fd1498Szrj bool dummy1 = true, dummy2 = true;
7838fd1498Szrj nelts = c_fully_fold_internal (nelts, true, &dummy1, &dummy2, false, false);
7938fd1498Szrj unsigned HOST_WIDE_INT i = tree_to_uhwi (index);
8038fd1498Szrj if (!tree_int_cst_le (index, nelts)
8138fd1498Szrj || i >= len
8238fd1498Szrj || i + elem_nchars > len)
8338fd1498Szrj return NULL_TREE;
8438fd1498Szrj
8538fd1498Szrj if (elem_nchars == 1)
8638fd1498Szrj return build_int_cst (type, TREE_STRING_POINTER (ary)[i]);
8738fd1498Szrj
8838fd1498Szrj const unsigned char *ptr
8938fd1498Szrj = ((const unsigned char *)TREE_STRING_POINTER (ary) + i * elem_nchars);
9038fd1498Szrj return native_interpret_expr (type, ptr, elem_nchars);
9138fd1498Szrj }
9238fd1498Szrj
9338fd1498Szrj /* Fully fold EXPR, an expression that was not folded (beyond integer
9438fd1498Szrj constant expressions and null pointer constants) when being built
9538fd1498Szrj up. If IN_INIT, this is in a static initializer and certain
9638fd1498Szrj changes are made to the folding done. Clear *MAYBE_CONST if
9738fd1498Szrj MAYBE_CONST is not NULL and EXPR is definitely not a constant
9838fd1498Szrj expression because it contains an evaluated operator (in C99) or an
9938fd1498Szrj operator outside of sizeof returning an integer constant (in C90)
10038fd1498Szrj not permitted in constant expressions, or because it contains an
10138fd1498Szrj evaluated arithmetic overflow. (*MAYBE_CONST should typically be
10238fd1498Szrj set to true by callers before calling this function.) Return the
10338fd1498Szrj folded expression. Function arguments have already been folded
10438fd1498Szrj before calling this function, as have the contents of SAVE_EXPR,
10538fd1498Szrj TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
10638fd1498Szrj C_MAYBE_CONST_EXPR. LVAL is true if it should be treated as an
10738fd1498Szrj lvalue. */
10838fd1498Szrj
10938fd1498Szrj tree
c_fully_fold(tree expr,bool in_init,bool * maybe_const,bool lval)11038fd1498Szrj c_fully_fold (tree expr, bool in_init, bool *maybe_const, bool lval)
11138fd1498Szrj {
11238fd1498Szrj tree ret;
11338fd1498Szrj tree eptype = NULL_TREE;
11438fd1498Szrj bool dummy = true;
11538fd1498Szrj bool maybe_const_itself = true;
11638fd1498Szrj location_t loc = EXPR_LOCATION (expr);
11738fd1498Szrj
11838fd1498Szrj if (!maybe_const)
11938fd1498Szrj maybe_const = &dummy;
12038fd1498Szrj if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
12138fd1498Szrj {
12238fd1498Szrj eptype = TREE_TYPE (expr);
12338fd1498Szrj expr = TREE_OPERAND (expr, 0);
12438fd1498Szrj }
12538fd1498Szrj ret = c_fully_fold_internal (expr, in_init, maybe_const,
12638fd1498Szrj &maybe_const_itself, false, lval);
12738fd1498Szrj if (eptype)
12838fd1498Szrj ret = fold_convert_loc (loc, eptype, ret);
12938fd1498Szrj *maybe_const &= maybe_const_itself;
13038fd1498Szrj return ret;
13138fd1498Szrj }
13238fd1498Szrj
13338fd1498Szrj /* Internal helper for c_fully_fold. EXPR and IN_INIT are as for
13438fd1498Szrj c_fully_fold. *MAYBE_CONST_OPERANDS is cleared because of operands
13538fd1498Szrj not permitted, while *MAYBE_CONST_ITSELF is cleared because of
13638fd1498Szrj arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from
13738fd1498Szrj both evaluated and unevaluated subexpressions while
13838fd1498Szrj *MAYBE_CONST_ITSELF is carried from only evaluated
13938fd1498Szrj subexpressions). FOR_INT_CONST indicates if EXPR is an expression
14038fd1498Szrj with integer constant operands, and if any of the operands doesn't
14138fd1498Szrj get folded to an integer constant, don't fold the expression itself.
14238fd1498Szrj LVAL indicates folding of lvalue, where we can't replace it with
14338fd1498Szrj an rvalue. */
14438fd1498Szrj
14538fd1498Szrj static tree
c_fully_fold_internal(tree expr,bool in_init,bool * maybe_const_operands,bool * maybe_const_itself,bool for_int_const,bool lval)14638fd1498Szrj c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
14738fd1498Szrj bool *maybe_const_itself, bool for_int_const, bool lval)
14838fd1498Szrj {
14938fd1498Szrj tree ret = expr;
15038fd1498Szrj enum tree_code code = TREE_CODE (expr);
15138fd1498Szrj enum tree_code_class kind = TREE_CODE_CLASS (code);
15238fd1498Szrj location_t loc = EXPR_LOCATION (expr);
15338fd1498Szrj tree op0, op1, op2, op3;
15438fd1498Szrj tree orig_op0, orig_op1, orig_op2;
15538fd1498Szrj bool op0_const = true, op1_const = true, op2_const = true;
15638fd1498Szrj bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
15738fd1498Szrj bool nowarning = TREE_NO_WARNING (expr);
15838fd1498Szrj bool unused_p;
15938fd1498Szrj bool op0_lval = false;
16038fd1498Szrj source_range old_range;
16138fd1498Szrj
16238fd1498Szrj /* Constants, declarations, statements, errors, and anything else not
16338fd1498Szrj counted as an expression cannot usefully be folded further at this
16438fd1498Szrj point. */
16538fd1498Szrj if (!IS_EXPR_CODE_CLASS (kind) || kind == tcc_statement)
16638fd1498Szrj {
16738fd1498Szrj /* Except for variables which we can optimize to its initializer. */
16838fd1498Szrj if (VAR_P (expr) && !lval && (optimize || in_init))
16938fd1498Szrj {
17038fd1498Szrj if (in_init)
17138fd1498Szrj ret = decl_constant_value_1 (expr, true);
17238fd1498Szrj else
17338fd1498Szrj {
17438fd1498Szrj ret = decl_constant_value (expr);
17538fd1498Szrj if (ret != expr
17638fd1498Szrj && (TYPE_MODE (TREE_TYPE (ret)) == BLKmode
17738fd1498Szrj || TREE_CODE (TREE_TYPE (ret)) == ARRAY_TYPE))
17838fd1498Szrj return expr;
17938fd1498Szrj }
18038fd1498Szrj /* Avoid unwanted tree sharing between the initializer and current
18138fd1498Szrj function's body where the tree can be modified e.g. by the
18238fd1498Szrj gimplifier. */
18338fd1498Szrj if (ret != expr && TREE_STATIC (expr))
18438fd1498Szrj ret = unshare_expr (ret);
18538fd1498Szrj return ret;
18638fd1498Szrj }
18738fd1498Szrj return expr;
18838fd1498Szrj }
18938fd1498Szrj
19038fd1498Szrj if (IS_EXPR_CODE_CLASS (kind))
19138fd1498Szrj old_range = EXPR_LOCATION_RANGE (expr);
19238fd1498Szrj
19338fd1498Szrj /* Operands of variable-length expressions (function calls) have
19438fd1498Szrj already been folded, as have __builtin_* function calls, and such
19538fd1498Szrj expressions cannot occur in constant expressions. */
19638fd1498Szrj if (kind == tcc_vl_exp)
19738fd1498Szrj {
19838fd1498Szrj *maybe_const_operands = false;
19938fd1498Szrj ret = fold (expr);
20038fd1498Szrj goto out;
20138fd1498Szrj }
20238fd1498Szrj
20338fd1498Szrj if (code == C_MAYBE_CONST_EXPR)
20438fd1498Szrj {
20538fd1498Szrj tree pre = C_MAYBE_CONST_EXPR_PRE (expr);
20638fd1498Szrj tree inner = C_MAYBE_CONST_EXPR_EXPR (expr);
20738fd1498Szrj if (C_MAYBE_CONST_EXPR_NON_CONST (expr))
20838fd1498Szrj *maybe_const_operands = false;
20938fd1498Szrj if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr))
21038fd1498Szrj {
21138fd1498Szrj *maybe_const_itself = false;
21238fd1498Szrj inner = c_fully_fold_internal (inner, in_init, maybe_const_operands,
21338fd1498Szrj maybe_const_itself, true, lval);
21438fd1498Szrj }
21538fd1498Szrj if (pre && !in_init)
21638fd1498Szrj ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
21738fd1498Szrj else
21838fd1498Szrj ret = inner;
21938fd1498Szrj goto out;
22038fd1498Szrj }
22138fd1498Szrj
22238fd1498Szrj /* Assignment, increment, decrement, function call and comma
22338fd1498Szrj operators, and statement expressions, cannot occur in constant
22438fd1498Szrj expressions if evaluated / outside of sizeof. (Function calls
22538fd1498Szrj were handled above, though VA_ARG_EXPR is treated like a function
22638fd1498Szrj call here, and statement expressions are handled through
22738fd1498Szrj C_MAYBE_CONST_EXPR to avoid folding inside them.) */
22838fd1498Szrj switch (code)
22938fd1498Szrj {
23038fd1498Szrj case MODIFY_EXPR:
23138fd1498Szrj case PREDECREMENT_EXPR:
23238fd1498Szrj case PREINCREMENT_EXPR:
23338fd1498Szrj case POSTDECREMENT_EXPR:
23438fd1498Szrj case POSTINCREMENT_EXPR:
23538fd1498Szrj case COMPOUND_EXPR:
23638fd1498Szrj *maybe_const_operands = false;
23738fd1498Szrj break;
23838fd1498Szrj
23938fd1498Szrj case VA_ARG_EXPR:
24038fd1498Szrj case TARGET_EXPR:
24138fd1498Szrj case BIND_EXPR:
24238fd1498Szrj case OBJ_TYPE_REF:
24338fd1498Szrj *maybe_const_operands = false;
24438fd1498Szrj ret = fold (expr);
24538fd1498Szrj goto out;
24638fd1498Szrj
24738fd1498Szrj default:
24838fd1498Szrj break;
24938fd1498Szrj }
25038fd1498Szrj
25138fd1498Szrj /* Fold individual tree codes as appropriate. */
25238fd1498Szrj switch (code)
25338fd1498Szrj {
25438fd1498Szrj case COMPOUND_LITERAL_EXPR:
25538fd1498Szrj /* Any non-constancy will have been marked in a containing
25638fd1498Szrj C_MAYBE_CONST_EXPR; there is no more folding to do here. */
25738fd1498Szrj goto out;
25838fd1498Szrj
25938fd1498Szrj case COMPONENT_REF:
26038fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
26138fd1498Szrj op1 = TREE_OPERAND (expr, 1);
26238fd1498Szrj op2 = TREE_OPERAND (expr, 2);
26338fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
26438fd1498Szrj maybe_const_itself, for_int_const, lval);
26538fd1498Szrj STRIP_TYPE_NOPS (op0);
26638fd1498Szrj if (op0 != orig_op0)
26738fd1498Szrj ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
26838fd1498Szrj if (ret != expr)
26938fd1498Szrj {
27038fd1498Szrj TREE_READONLY (ret) = TREE_READONLY (expr);
27138fd1498Szrj TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
27238fd1498Szrj }
27338fd1498Szrj if (!lval)
27438fd1498Szrj ret = fold (ret);
27538fd1498Szrj goto out;
27638fd1498Szrj
27738fd1498Szrj case ARRAY_REF:
27838fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
27938fd1498Szrj orig_op1 = op1 = TREE_OPERAND (expr, 1);
28038fd1498Szrj op2 = TREE_OPERAND (expr, 2);
28138fd1498Szrj op3 = TREE_OPERAND (expr, 3);
28238fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
28338fd1498Szrj maybe_const_itself, for_int_const, lval);
28438fd1498Szrj STRIP_TYPE_NOPS (op0);
28538fd1498Szrj op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
28638fd1498Szrj maybe_const_itself, for_int_const, false);
28738fd1498Szrj STRIP_TYPE_NOPS (op1);
28838fd1498Szrj /* Fold "foo"[2] in initializers. */
28938fd1498Szrj if (!lval && in_init)
29038fd1498Szrj {
29138fd1498Szrj ret = c_fold_array_ref (TREE_TYPE (expr), op0, op1);
29238fd1498Szrj if (ret)
29338fd1498Szrj goto out;
29438fd1498Szrj ret = expr;
29538fd1498Szrj }
29638fd1498Szrj if (op0 != orig_op0 || op1 != orig_op1)
29738fd1498Szrj ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
29838fd1498Szrj if (ret != expr)
29938fd1498Szrj {
30038fd1498Szrj TREE_READONLY (ret) = TREE_READONLY (expr);
30138fd1498Szrj TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
30238fd1498Szrj TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
30338fd1498Szrj }
30438fd1498Szrj if (!lval)
30538fd1498Szrj ret = fold (ret);
30638fd1498Szrj goto out;
30738fd1498Szrj
30838fd1498Szrj case MODIFY_EXPR:
30938fd1498Szrj case PREDECREMENT_EXPR:
31038fd1498Szrj case PREINCREMENT_EXPR:
31138fd1498Szrj case POSTDECREMENT_EXPR:
31238fd1498Szrj case POSTINCREMENT_EXPR:
31338fd1498Szrj op0_lval = true;
31438fd1498Szrj /* FALLTHRU */
31538fd1498Szrj case COMPOUND_EXPR:
31638fd1498Szrj case PLUS_EXPR:
31738fd1498Szrj case MINUS_EXPR:
31838fd1498Szrj case MULT_EXPR:
31938fd1498Szrj case POINTER_PLUS_EXPR:
32038fd1498Szrj case POINTER_DIFF_EXPR:
32138fd1498Szrj case TRUNC_DIV_EXPR:
32238fd1498Szrj case CEIL_DIV_EXPR:
32338fd1498Szrj case FLOOR_DIV_EXPR:
32438fd1498Szrj case TRUNC_MOD_EXPR:
32538fd1498Szrj case RDIV_EXPR:
32638fd1498Szrj case EXACT_DIV_EXPR:
32738fd1498Szrj case LSHIFT_EXPR:
32838fd1498Szrj case RSHIFT_EXPR:
32938fd1498Szrj case BIT_IOR_EXPR:
33038fd1498Szrj case BIT_XOR_EXPR:
33138fd1498Szrj case BIT_AND_EXPR:
33238fd1498Szrj case LT_EXPR:
33338fd1498Szrj case LE_EXPR:
33438fd1498Szrj case GT_EXPR:
33538fd1498Szrj case GE_EXPR:
33638fd1498Szrj case EQ_EXPR:
33738fd1498Szrj case NE_EXPR:
33838fd1498Szrj case COMPLEX_EXPR:
33938fd1498Szrj case TRUTH_AND_EXPR:
34038fd1498Szrj case TRUTH_OR_EXPR:
34138fd1498Szrj case TRUTH_XOR_EXPR:
34238fd1498Szrj case UNORDERED_EXPR:
34338fd1498Szrj case ORDERED_EXPR:
34438fd1498Szrj case UNLT_EXPR:
34538fd1498Szrj case UNLE_EXPR:
34638fd1498Szrj case UNGT_EXPR:
34738fd1498Szrj case UNGE_EXPR:
34838fd1498Szrj case UNEQ_EXPR:
34938fd1498Szrj /* Binary operations evaluating both arguments (increment and
35038fd1498Szrj decrement are binary internally in GCC). */
35138fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
35238fd1498Szrj orig_op1 = op1 = TREE_OPERAND (expr, 1);
35338fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
35438fd1498Szrj maybe_const_itself, for_int_const,
35538fd1498Szrj op0_lval);
35638fd1498Szrj STRIP_TYPE_NOPS (op0);
35738fd1498Szrj /* The RHS of a MODIFY_EXPR was fully folded when building that
35838fd1498Szrj expression for the sake of conversion warnings. */
35938fd1498Szrj if (code != MODIFY_EXPR)
36038fd1498Szrj op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
36138fd1498Szrj maybe_const_itself, for_int_const, false);
36238fd1498Szrj STRIP_TYPE_NOPS (op1);
36338fd1498Szrj
36438fd1498Szrj if (for_int_const && (TREE_CODE (op0) != INTEGER_CST
36538fd1498Szrj || TREE_CODE (op1) != INTEGER_CST))
36638fd1498Szrj goto out;
36738fd1498Szrj
36838fd1498Szrj if (op0 != orig_op0 || op1 != orig_op1 || in_init)
36938fd1498Szrj ret = in_init
37038fd1498Szrj ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
37138fd1498Szrj : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
37238fd1498Szrj else
37338fd1498Szrj ret = fold (expr);
37438fd1498Szrj if (TREE_OVERFLOW_P (ret)
37538fd1498Szrj && !TREE_OVERFLOW_P (op0)
37638fd1498Szrj && !TREE_OVERFLOW_P (op1))
37738fd1498Szrj overflow_warning (EXPR_LOC_OR_LOC (expr, input_location), ret, expr);
37838fd1498Szrj if (code == LSHIFT_EXPR
37938fd1498Szrj && TREE_CODE (orig_op0) != INTEGER_CST
38038fd1498Szrj && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
38138fd1498Szrj && TREE_CODE (op0) == INTEGER_CST
38238fd1498Szrj && c_inhibit_evaluation_warnings == 0
38338fd1498Szrj && tree_int_cst_sgn (op0) < 0)
38438fd1498Szrj warning_at (loc, OPT_Wshift_negative_value,
38538fd1498Szrj "left shift of negative value");
38638fd1498Szrj if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
38738fd1498Szrj && TREE_CODE (orig_op1) != INTEGER_CST
38838fd1498Szrj && TREE_CODE (op1) == INTEGER_CST
38938fd1498Szrj && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
39038fd1498Szrj && c_inhibit_evaluation_warnings == 0)
39138fd1498Szrj {
39238fd1498Szrj if (tree_int_cst_sgn (op1) < 0)
39338fd1498Szrj warning_at (loc, OPT_Wshift_count_negative,
39438fd1498Szrj (code == LSHIFT_EXPR
39538fd1498Szrj ? G_("left shift count is negative")
39638fd1498Szrj : G_("right shift count is negative")));
39738fd1498Szrj else if ((TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
39838fd1498Szrj || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
39938fd1498Szrj && compare_tree_int (op1,
40038fd1498Szrj TYPE_PRECISION (TREE_TYPE (orig_op0)))
40138fd1498Szrj >= 0)
40238fd1498Szrj warning_at (loc, OPT_Wshift_count_overflow,
40338fd1498Szrj (code == LSHIFT_EXPR
40438fd1498Szrj ? G_("left shift count >= width of type")
40538fd1498Szrj : G_("right shift count >= width of type")));
40638fd1498Szrj else if (TREE_CODE (TREE_TYPE (orig_op0)) == VECTOR_TYPE
40738fd1498Szrj && compare_tree_int (op1,
40838fd1498Szrj TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig_op0))))
40938fd1498Szrj >= 0)
41038fd1498Szrj warning_at (loc, OPT_Wshift_count_overflow,
41138fd1498Szrj code == LSHIFT_EXPR
41238fd1498Szrj ? G_("left shift count >= width of vector element")
41338fd1498Szrj : G_("right shift count >= width of vector element"));
41438fd1498Szrj }
41538fd1498Szrj if (code == LSHIFT_EXPR
41638fd1498Szrj /* If either OP0 has been folded to INTEGER_CST... */
41738fd1498Szrj && ((TREE_CODE (orig_op0) != INTEGER_CST
41838fd1498Szrj && TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
41938fd1498Szrj && TREE_CODE (op0) == INTEGER_CST)
42038fd1498Szrj /* ...or if OP1 has been folded to INTEGER_CST... */
42138fd1498Szrj || (TREE_CODE (orig_op1) != INTEGER_CST
42238fd1498Szrj && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
42338fd1498Szrj && TREE_CODE (op1) == INTEGER_CST))
42438fd1498Szrj && c_inhibit_evaluation_warnings == 0)
42538fd1498Szrj /* ...then maybe we can detect an overflow. */
42638fd1498Szrj maybe_warn_shift_overflow (loc, op0, op1);
42738fd1498Szrj if ((code == TRUNC_DIV_EXPR
42838fd1498Szrj || code == CEIL_DIV_EXPR
42938fd1498Szrj || code == FLOOR_DIV_EXPR
43038fd1498Szrj || code == EXACT_DIV_EXPR
43138fd1498Szrj || code == TRUNC_MOD_EXPR)
43238fd1498Szrj && TREE_CODE (orig_op1) != INTEGER_CST
43338fd1498Szrj && TREE_CODE (op1) == INTEGER_CST
43438fd1498Szrj && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
43538fd1498Szrj || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
43638fd1498Szrj && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE)
43738fd1498Szrj warn_for_div_by_zero (loc, op1);
43838fd1498Szrj goto out;
43938fd1498Szrj
44038fd1498Szrj case ADDR_EXPR:
44138fd1498Szrj op0_lval = true;
44238fd1498Szrj goto unary;
44338fd1498Szrj case REALPART_EXPR:
44438fd1498Szrj case IMAGPART_EXPR:
44538fd1498Szrj case VIEW_CONVERT_EXPR:
44638fd1498Szrj op0_lval = lval;
44738fd1498Szrj /* FALLTHRU */
44838fd1498Szrj case INDIRECT_REF:
44938fd1498Szrj case FIX_TRUNC_EXPR:
45038fd1498Szrj case FLOAT_EXPR:
45138fd1498Szrj CASE_CONVERT:
45238fd1498Szrj case ADDR_SPACE_CONVERT_EXPR:
45338fd1498Szrj case NON_LVALUE_EXPR:
45438fd1498Szrj case NEGATE_EXPR:
45538fd1498Szrj case BIT_NOT_EXPR:
45638fd1498Szrj case TRUTH_NOT_EXPR:
45738fd1498Szrj case CONJ_EXPR:
45838fd1498Szrj unary:
45938fd1498Szrj /* Unary operations. */
46038fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
46138fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
46238fd1498Szrj maybe_const_itself, for_int_const,
46338fd1498Szrj op0_lval);
46438fd1498Szrj STRIP_TYPE_NOPS (op0);
46538fd1498Szrj
46638fd1498Szrj if (for_int_const && TREE_CODE (op0) != INTEGER_CST)
46738fd1498Szrj goto out;
46838fd1498Szrj
46938fd1498Szrj /* ??? Cope with user tricks that amount to offsetof. The middle-end is
47038fd1498Szrj not prepared to deal with them if they occur in initializers. */
47138fd1498Szrj if (op0 != orig_op0
47238fd1498Szrj && code == ADDR_EXPR
47338fd1498Szrj && (op1 = get_base_address (op0)) != NULL_TREE
47438fd1498Szrj && INDIRECT_REF_P (op1)
47538fd1498Szrj && TREE_CONSTANT (TREE_OPERAND (op1, 0)))
476*58e805e6Szrj ret = fold_offsetof (op0, TREE_TYPE (expr));
47738fd1498Szrj else if (op0 != orig_op0 || in_init)
47838fd1498Szrj ret = in_init
47938fd1498Szrj ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
48038fd1498Szrj : fold_build1_loc (loc, code, TREE_TYPE (expr), op0);
48138fd1498Szrj else
48238fd1498Szrj ret = fold (expr);
48338fd1498Szrj if (code == INDIRECT_REF
48438fd1498Szrj && ret != expr
48538fd1498Szrj && INDIRECT_REF_P (ret))
48638fd1498Szrj {
48738fd1498Szrj TREE_READONLY (ret) = TREE_READONLY (expr);
48838fd1498Szrj TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
48938fd1498Szrj TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
49038fd1498Szrj }
49138fd1498Szrj switch (code)
49238fd1498Szrj {
49338fd1498Szrj case FIX_TRUNC_EXPR:
49438fd1498Szrj case FLOAT_EXPR:
49538fd1498Szrj CASE_CONVERT:
49638fd1498Szrj /* Don't warn about explicit conversions. We will already
49738fd1498Szrj have warned about suspect implicit conversions. */
49838fd1498Szrj break;
49938fd1498Szrj
50038fd1498Szrj default:
50138fd1498Szrj if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0))
50238fd1498Szrj overflow_warning (EXPR_LOCATION (expr), ret, op0);
50338fd1498Szrj break;
50438fd1498Szrj }
50538fd1498Szrj goto out;
50638fd1498Szrj
50738fd1498Szrj case TRUTH_ANDIF_EXPR:
50838fd1498Szrj case TRUTH_ORIF_EXPR:
50938fd1498Szrj /* Binary operations not necessarily evaluating both
51038fd1498Szrj arguments. */
51138fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
51238fd1498Szrj orig_op1 = op1 = TREE_OPERAND (expr, 1);
51338fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self,
51438fd1498Szrj for_int_const, false);
51538fd1498Szrj STRIP_TYPE_NOPS (op0);
51638fd1498Szrj
51738fd1498Szrj unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
51838fd1498Szrj ? truthvalue_false_node
51938fd1498Szrj : truthvalue_true_node));
52038fd1498Szrj c_disable_warnings (unused_p);
52138fd1498Szrj op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self,
52238fd1498Szrj for_int_const, false);
52338fd1498Szrj STRIP_TYPE_NOPS (op1);
52438fd1498Szrj c_enable_warnings (unused_p);
52538fd1498Szrj
52638fd1498Szrj if (for_int_const
52738fd1498Szrj && (TREE_CODE (op0) != INTEGER_CST
52838fd1498Szrj /* Require OP1 be an INTEGER_CST only if it's evaluated. */
52938fd1498Szrj || (!unused_p && TREE_CODE (op1) != INTEGER_CST)))
53038fd1498Szrj goto out;
53138fd1498Szrj
53238fd1498Szrj if (op0 != orig_op0 || op1 != orig_op1 || in_init)
53338fd1498Szrj ret = in_init
53438fd1498Szrj ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
53538fd1498Szrj : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
53638fd1498Szrj else
53738fd1498Szrj ret = fold (expr);
53838fd1498Szrj *maybe_const_operands &= op0_const;
53938fd1498Szrj *maybe_const_itself &= op0_const_self;
54038fd1498Szrj if (!(flag_isoc99
54138fd1498Szrj && op0_const
54238fd1498Szrj && op0_const_self
54338fd1498Szrj && (code == TRUTH_ANDIF_EXPR
54438fd1498Szrj ? op0 == truthvalue_false_node
54538fd1498Szrj : op0 == truthvalue_true_node)))
54638fd1498Szrj *maybe_const_operands &= op1_const;
54738fd1498Szrj if (!(op0_const
54838fd1498Szrj && op0_const_self
54938fd1498Szrj && (code == TRUTH_ANDIF_EXPR
55038fd1498Szrj ? op0 == truthvalue_false_node
55138fd1498Szrj : op0 == truthvalue_true_node)))
55238fd1498Szrj *maybe_const_itself &= op1_const_self;
55338fd1498Szrj goto out;
55438fd1498Szrj
55538fd1498Szrj case COND_EXPR:
55638fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
55738fd1498Szrj orig_op1 = op1 = TREE_OPERAND (expr, 1);
55838fd1498Szrj orig_op2 = op2 = TREE_OPERAND (expr, 2);
55938fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self,
56038fd1498Szrj for_int_const, false);
56138fd1498Szrj
56238fd1498Szrj STRIP_TYPE_NOPS (op0);
56338fd1498Szrj c_disable_warnings (op0 == truthvalue_false_node);
56438fd1498Szrj op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self,
56538fd1498Szrj for_int_const, false);
56638fd1498Szrj STRIP_TYPE_NOPS (op1);
56738fd1498Szrj c_enable_warnings (op0 == truthvalue_false_node);
56838fd1498Szrj
56938fd1498Szrj c_disable_warnings (op0 == truthvalue_true_node);
57038fd1498Szrj op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self,
57138fd1498Szrj for_int_const, false);
57238fd1498Szrj STRIP_TYPE_NOPS (op2);
57338fd1498Szrj c_enable_warnings (op0 == truthvalue_true_node);
57438fd1498Szrj
57538fd1498Szrj if (for_int_const
57638fd1498Szrj && (TREE_CODE (op0) != INTEGER_CST
57738fd1498Szrj /* Only the evaluated operand must be an INTEGER_CST. */
57838fd1498Szrj || (op0 == truthvalue_true_node
57938fd1498Szrj ? TREE_CODE (op1) != INTEGER_CST
58038fd1498Szrj : TREE_CODE (op2) != INTEGER_CST)))
58138fd1498Szrj goto out;
58238fd1498Szrj
58338fd1498Szrj if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
58438fd1498Szrj ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2);
58538fd1498Szrj else
58638fd1498Szrj ret = fold (expr);
58738fd1498Szrj *maybe_const_operands &= op0_const;
58838fd1498Szrj *maybe_const_itself &= op0_const_self;
58938fd1498Szrj if (!(flag_isoc99
59038fd1498Szrj && op0_const
59138fd1498Szrj && op0_const_self
59238fd1498Szrj && op0 == truthvalue_false_node))
59338fd1498Szrj *maybe_const_operands &= op1_const;
59438fd1498Szrj if (!(op0_const
59538fd1498Szrj && op0_const_self
59638fd1498Szrj && op0 == truthvalue_false_node))
59738fd1498Szrj *maybe_const_itself &= op1_const_self;
59838fd1498Szrj if (!(flag_isoc99
59938fd1498Szrj && op0_const
60038fd1498Szrj && op0_const_self
60138fd1498Szrj && op0 == truthvalue_true_node))
60238fd1498Szrj *maybe_const_operands &= op2_const;
60338fd1498Szrj if (!(op0_const
60438fd1498Szrj && op0_const_self
60538fd1498Szrj && op0 == truthvalue_true_node))
60638fd1498Szrj *maybe_const_itself &= op2_const_self;
60738fd1498Szrj goto out;
60838fd1498Szrj
60938fd1498Szrj case VEC_COND_EXPR:
61038fd1498Szrj orig_op0 = op0 = TREE_OPERAND (expr, 0);
61138fd1498Szrj orig_op1 = op1 = TREE_OPERAND (expr, 1);
61238fd1498Szrj orig_op2 = op2 = TREE_OPERAND (expr, 2);
61338fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
61438fd1498Szrj maybe_const_itself, for_int_const, false);
61538fd1498Szrj STRIP_TYPE_NOPS (op0);
61638fd1498Szrj op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
61738fd1498Szrj maybe_const_itself, for_int_const, false);
61838fd1498Szrj STRIP_TYPE_NOPS (op1);
61938fd1498Szrj op2 = c_fully_fold_internal (op2, in_init, maybe_const_operands,
62038fd1498Szrj maybe_const_itself, for_int_const, false);
62138fd1498Szrj STRIP_TYPE_NOPS (op2);
62238fd1498Szrj
62338fd1498Szrj if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
62438fd1498Szrj ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2);
62538fd1498Szrj else
62638fd1498Szrj ret = fold (expr);
62738fd1498Szrj goto out;
62838fd1498Szrj
62938fd1498Szrj case EXCESS_PRECISION_EXPR:
63038fd1498Szrj /* Each case where an operand with excess precision may be
63138fd1498Szrj encountered must remove the EXCESS_PRECISION_EXPR around
63238fd1498Szrj inner operands and possibly put one around the whole
63338fd1498Szrj expression or possibly convert to the semantic type (which
63438fd1498Szrj c_fully_fold does); we cannot tell at this stage which is
63538fd1498Szrj appropriate in any particular case. */
63638fd1498Szrj gcc_unreachable ();
63738fd1498Szrj
63838fd1498Szrj case SAVE_EXPR:
63938fd1498Szrj /* Make sure to fold the contents of a SAVE_EXPR exactly once. */
64038fd1498Szrj op0 = TREE_OPERAND (expr, 0);
64138fd1498Szrj if (!SAVE_EXPR_FOLDED_P (expr))
64238fd1498Szrj {
64338fd1498Szrj op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
64438fd1498Szrj maybe_const_itself, for_int_const,
64538fd1498Szrj false);
64638fd1498Szrj TREE_OPERAND (expr, 0) = op0;
64738fd1498Szrj SAVE_EXPR_FOLDED_P (expr) = true;
64838fd1498Szrj }
64938fd1498Szrj /* Return the SAVE_EXPR operand if it is invariant. */
65038fd1498Szrj if (tree_invariant_p (op0))
65138fd1498Szrj ret = op0;
65238fd1498Szrj goto out;
65338fd1498Szrj
65438fd1498Szrj default:
65538fd1498Szrj /* Various codes may appear through folding built-in functions
65638fd1498Szrj and their arguments. */
65738fd1498Szrj goto out;
65838fd1498Szrj }
65938fd1498Szrj
66038fd1498Szrj out:
66138fd1498Szrj /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
66238fd1498Szrj have been done by this point, so remove them again. */
66338fd1498Szrj nowarning |= TREE_NO_WARNING (ret);
66438fd1498Szrj STRIP_TYPE_NOPS (ret);
66538fd1498Szrj if (nowarning && !TREE_NO_WARNING (ret))
66638fd1498Szrj {
66738fd1498Szrj if (!CAN_HAVE_LOCATION_P (ret))
66838fd1498Szrj ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
66938fd1498Szrj TREE_NO_WARNING (ret) = 1;
67038fd1498Szrj }
67138fd1498Szrj if (ret != expr)
67238fd1498Szrj {
67338fd1498Szrj protected_set_expr_location (ret, loc);
67438fd1498Szrj if (IS_EXPR_CODE_CLASS (kind))
67538fd1498Szrj set_source_range (ret, old_range.m_start, old_range.m_finish);
67638fd1498Szrj }
67738fd1498Szrj return ret;
67838fd1498Szrj }
67938fd1498Szrj
68038fd1498Szrj /* Fold X for consideration by one of the warning functions when checking
68138fd1498Szrj whether an expression has a constant value. */
68238fd1498Szrj
68338fd1498Szrj tree
fold_for_warn(tree x)68438fd1498Szrj fold_for_warn (tree x)
68538fd1498Szrj {
68638fd1498Szrj /* The C front-end has already folded X appropriately. */
68738fd1498Szrj return x;
68838fd1498Szrj }
689