@@ -27,7 +27,8 @@ along with GCC; see the file COPYING3. If not see
2727#include "intl.h"
2828#include "gimplify.h"
2929
30- static tree c_fully_fold_internal (tree expr , bool , bool * , bool * , bool );
30+ static tree c_fully_fold_internal (tree expr , bool , bool * , bool * , bool ,
31+ bool );
3132
3233/* If DISABLE is true, stop issuing warnings. This is used when
3334 parsing code that we know will not be executed. This function may
@@ -55,6 +56,40 @@ c_enable_warnings (bool enable)
5556 }
5657}
5758
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+
5893/* Fully fold EXPR, an expression that was not folded (beyond integer
5994 constant expressions and null pointer constants) when being built
6095 up. If IN_INIT, this is in a static initializer and certain
@@ -68,10 +103,11 @@ c_enable_warnings (bool enable)
68103 folded expression. Function arguments have already been folded
69104 before calling this function, as have the contents of SAVE_EXPR,
70105 TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
71- C_MAYBE_CONST_EXPR. */
106+ C_MAYBE_CONST_EXPR. LVAL is true if it should be treated as an
107+ lvalue. */
72108
73109tree
74- c_fully_fold (tree expr , bool in_init , bool * maybe_const )
110+ c_fully_fold (tree expr , bool in_init , bool * maybe_const , bool lval )
75111{
76112 tree ret ;
77113 tree eptype = NULL_TREE ;
@@ -87,7 +123,7 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const)
87123 expr = TREE_OPERAND (expr , 0 );
88124 }
89125 ret = c_fully_fold_internal (expr , in_init , maybe_const ,
90- & maybe_const_itself , false);
126+ & maybe_const_itself , false, lval );
91127 if (eptype )
92128 ret = fold_convert_loc (loc , eptype , ret );
93129 * maybe_const &= maybe_const_itself ;
@@ -102,11 +138,13 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const)
102138 *MAYBE_CONST_ITSELF is carried from only evaluated
103139 subexpressions). FOR_INT_CONST indicates if EXPR is an expression
104140 with integer constant operands, and if any of the operands doesn't
105- get folded to an integer constant, don't fold the expression itself. */
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. */
106144
107145static tree
108146c_fully_fold_internal (tree expr , bool in_init , bool * maybe_const_operands ,
109- bool * maybe_const_itself , bool for_int_const )
147+ bool * maybe_const_itself , bool for_int_const , bool lval )
110148{
111149 tree ret = expr ;
112150 enum tree_code code = TREE_CODE (expr );
@@ -118,14 +156,27 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
118156 bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
119157 bool nowarning = TREE_NO_WARNING (expr );
120158 bool unused_p ;
159+ bool op0_lval = false;
121160 source_range old_range ;
122161
123162 /* Constants, declarations, statements, errors, and anything else not
124163 counted as an expression cannot usefully be folded further at this
125164 point. */
126- if (!IS_EXPR_CODE_CLASS (kind )
127- || kind == tcc_statement )
128- return expr ;
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+ {
170+ ret = decl_constant_value (expr );
171+ /* Avoid unwanted tree sharing between the initializer and current
172+ function's body where the tree can be modified e.g. by the
173+ gimplifier. */
174+ if (ret != expr && TREE_STATIC (expr ))
175+ ret = unshare_expr (ret );
176+ return ret ;
177+ }
178+ return expr ;
179+ }
129180
130181 if (IS_EXPR_CODE_CLASS (kind ))
131182 old_range = EXPR_LOCATION_RANGE (expr );
@@ -150,7 +201,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
150201 {
151202 * maybe_const_itself = false;
152203 inner = c_fully_fold_internal (inner , in_init , maybe_const_operands ,
153- maybe_const_itself , true);
204+ maybe_const_itself , true, lval );
154205 }
155206 if (pre && !in_init )
156207 ret = build2 (COMPOUND_EXPR , TREE_TYPE (expr ), pre , inner );
@@ -201,7 +252,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
201252 op1 = TREE_OPERAND (expr , 1 );
202253 op2 = TREE_OPERAND (expr , 2 );
203254 op0 = c_fully_fold_internal (op0 , in_init , maybe_const_operands ,
204- maybe_const_itself , for_int_const );
255+ maybe_const_itself , for_int_const , lval );
205256 STRIP_TYPE_NOPS (op0 );
206257 if (op0 != orig_op0 )
207258 ret = build3 (COMPONENT_REF , TREE_TYPE (expr ), op0 , op1 , op2 );
@@ -218,12 +269,19 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
218269 op2 = TREE_OPERAND (expr , 2 );
219270 op3 = TREE_OPERAND (expr , 3 );
220271 op0 = c_fully_fold_internal (op0 , in_init , maybe_const_operands ,
221- maybe_const_itself , for_int_const );
272+ maybe_const_itself , for_int_const , lval );
222273 STRIP_TYPE_NOPS (op0 );
223274 op1 = c_fully_fold_internal (op1 , in_init , maybe_const_operands ,
224- maybe_const_itself , for_int_const );
275+ maybe_const_itself , for_int_const , false );
225276 STRIP_TYPE_NOPS (op1 );
226- op1 = decl_constant_value_for_optimization (op1 );
277+ /* Fold "foo"[2] in initializers. */
278+ if (!lval && in_init )
279+ {
280+ ret = c_fold_array_ref (TREE_TYPE (expr ), op0 , op1 );
281+ if (ret )
282+ goto out ;
283+ ret = expr ;
284+ }
227285 if (op0 != orig_op0 || op1 != orig_op1 )
228286 ret = build4 (ARRAY_REF , TREE_TYPE (expr ), op0 , op1 , op2 , op3 );
229287 if (ret != expr )
@@ -232,15 +290,18 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
232290 TREE_SIDE_EFFECTS (ret ) = TREE_SIDE_EFFECTS (expr );
233291 TREE_THIS_VOLATILE (ret ) = TREE_THIS_VOLATILE (expr );
234292 }
235- ret = fold (ret );
293+ if (!lval )
294+ ret = fold (ret );
236295 goto out ;
237296
238- case COMPOUND_EXPR :
239297 case MODIFY_EXPR :
240298 case PREDECREMENT_EXPR :
241299 case PREINCREMENT_EXPR :
242300 case POSTDECREMENT_EXPR :
243301 case POSTINCREMENT_EXPR :
302+ op0_lval = true;
303+ /* FALLTHRU */
304+ case COMPOUND_EXPR :
244305 case PLUS_EXPR :
245306 case MINUS_EXPR :
246307 case MULT_EXPR :
@@ -278,21 +339,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
278339 orig_op0 = op0 = TREE_OPERAND (expr , 0 );
279340 orig_op1 = op1 = TREE_OPERAND (expr , 1 );
280341 op0 = c_fully_fold_internal (op0 , in_init , maybe_const_operands ,
281- maybe_const_itself , for_int_const );
342+ maybe_const_itself , for_int_const ,
343+ op0_lval );
282344 STRIP_TYPE_NOPS (op0 );
283- if (code != MODIFY_EXPR
284- && code != PREDECREMENT_EXPR
285- && code != PREINCREMENT_EXPR
286- && code != POSTDECREMENT_EXPR
287- && code != POSTINCREMENT_EXPR )
288- op0 = decl_constant_value_for_optimization (op0 );
289345 /* The RHS of a MODIFY_EXPR was fully folded when building that
290346 expression for the sake of conversion warnings. */
291347 if (code != MODIFY_EXPR )
292348 op1 = c_fully_fold_internal (op1 , in_init , maybe_const_operands ,
293- maybe_const_itself , for_int_const );
349+ maybe_const_itself , for_int_const , false );
294350 STRIP_TYPE_NOPS (op1 );
295- op1 = decl_constant_value_for_optimization (op1 );
296351
297352 if (for_int_const && (TREE_CODE (op0 ) != INTEGER_CST
298353 || TREE_CODE (op1 ) != INTEGER_CST ))
@@ -370,6 +425,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
370425 warn_for_div_by_zero (loc , op1 );
371426 goto out ;
372427
428+ case ADDR_EXPR :
429+ op0_lval = true;
430+ goto unary ;
431+ case REALPART_EXPR :
432+ case IMAGPART_EXPR :
433+ op0_lval = lval ;
434+ /* FALLTHRU */
373435 case INDIRECT_REF :
374436 case FIX_TRUNC_EXPR :
375437 case FLOAT_EXPR :
@@ -380,17 +442,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
380442 case NEGATE_EXPR :
381443 case BIT_NOT_EXPR :
382444 case TRUTH_NOT_EXPR :
383- case ADDR_EXPR :
384445 case CONJ_EXPR :
385- case REALPART_EXPR :
386- case IMAGPART_EXPR :
446+ unary :
387447 /* Unary operations. */
388448 orig_op0 = op0 = TREE_OPERAND (expr , 0 );
389449 op0 = c_fully_fold_internal (op0 , in_init , maybe_const_operands ,
390- maybe_const_itself , for_int_const );
450+ maybe_const_itself , for_int_const ,
451+ op0_lval );
391452 STRIP_TYPE_NOPS (op0 );
392- if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR )
393- op0 = decl_constant_value_for_optimization (op0 );
394453
395454 if (for_int_const && TREE_CODE (op0 ) != INTEGER_CST )
396455 goto out ;
@@ -440,15 +499,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
440499 orig_op0 = op0 = TREE_OPERAND (expr , 0 );
441500 orig_op1 = op1 = TREE_OPERAND (expr , 1 );
442501 op0 = c_fully_fold_internal (op0 , in_init , & op0_const , & op0_const_self ,
443- for_int_const );
502+ for_int_const , false );
444503 STRIP_TYPE_NOPS (op0 );
445504
446505 unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
447506 ? truthvalue_false_node
448507 : truthvalue_true_node ));
449508 c_disable_warnings (unused_p );
450509 op1 = c_fully_fold_internal (op1 , in_init , & op1_const , & op1_const_self ,
451- for_int_const );
510+ for_int_const , false );
452511 STRIP_TYPE_NOPS (op1 );
453512 c_enable_warnings (unused_p );
454513
@@ -486,18 +545,18 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
486545 orig_op1 = op1 = TREE_OPERAND (expr , 1 );
487546 orig_op2 = op2 = TREE_OPERAND (expr , 2 );
488547 op0 = c_fully_fold_internal (op0 , in_init , & op0_const , & op0_const_self ,
489- for_int_const );
548+ for_int_const , false );
490549
491550 STRIP_TYPE_NOPS (op0 );
492551 c_disable_warnings (op0 == truthvalue_false_node );
493552 op1 = c_fully_fold_internal (op1 , in_init , & op1_const , & op1_const_self ,
494- for_int_const );
553+ for_int_const , false );
495554 STRIP_TYPE_NOPS (op1 );
496555 c_enable_warnings (op0 == truthvalue_false_node );
497556
498557 c_disable_warnings (op0 == truthvalue_true_node );
499558 op2 = c_fully_fold_internal (op2 , in_init , & op2_const , & op2_const_self ,
500- for_int_const );
559+ for_int_const , false );
501560 STRIP_TYPE_NOPS (op2 );
502561 c_enable_warnings (op0 == truthvalue_true_node );
503562
@@ -540,13 +599,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
540599 orig_op1 = op1 = TREE_OPERAND (expr , 1 );
541600 orig_op2 = op2 = TREE_OPERAND (expr , 2 );
542601 op0 = c_fully_fold_internal (op0 , in_init , maybe_const_operands ,
543- maybe_const_itself , for_int_const );
602+ maybe_const_itself , for_int_const , false );
544603 STRIP_TYPE_NOPS (op0 );
545604 op1 = c_fully_fold_internal (op1 , in_init , maybe_const_operands ,
546- maybe_const_itself , for_int_const );
605+ maybe_const_itself , for_int_const , false );
547606 STRIP_TYPE_NOPS (op1 );
548607 op2 = c_fully_fold_internal (op2 , in_init , maybe_const_operands ,
549- maybe_const_itself , for_int_const );
608+ maybe_const_itself , for_int_const , false );
550609 STRIP_TYPE_NOPS (op2 );
551610
552611 if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2 )
@@ -570,7 +629,8 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
570629 if (!SAVE_EXPR_FOLDED_P (expr ))
571630 {
572631 op0 = c_fully_fold_internal (op0 , in_init , maybe_const_operands ,
573- maybe_const_itself , for_int_const );
632+ maybe_const_itself , for_int_const ,
633+ false);
574634 TREE_OPERAND (expr , 0 ) = op0 ;
575635 SAVE_EXPR_FOLDED_P (expr ) = true;
576636 }
@@ -604,28 +664,3 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
604664 }
605665 return ret ;
606666}
607-
608- /* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
609- return EXP. Otherwise, return either EXP or its known constant
610- value (if it has one), but return EXP if EXP has mode BLKmode. ???
611- Is the BLKmode test appropriate? */
612-
613- tree
614- decl_constant_value_for_optimization (tree exp )
615- {
616- tree ret ;
617-
618- if (!optimize
619- || !VAR_P (exp )
620- || TREE_CODE (TREE_TYPE (exp )) == ARRAY_TYPE
621- || DECL_MODE (exp ) == BLKmode )
622- return exp ;
623-
624- ret = decl_constant_value (exp );
625- /* Avoid unwanted tree sharing between the initializer and current
626- function's body where the tree can be modified e.g. by the
627- gimplifier. */
628- if (ret != exp && TREE_STATIC (exp ))
629- ret = unshare_expr (ret );
630- return ret ;
631- }
0 commit comments