xref: /dflybsd-src/contrib/gcc-8.0/gcc/c/c-fold.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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