Skip to content

Commit 69cd03b

Browse files
author
jakub
committed
PR c/66618
PR c/69960 c-family/ * c-common.h (c_fully_fold): Add LVAL argument defaulted to false. c/ * c-parser.c (c_parser_omp_atomic): Pass true as LVAL to c_fully_fold where needed. * c-typeck.c (build_unary_op, build_modify_expr, build_asm_expr, handle_omp_array_sections): Likewise. (digest_init): Don't call decl_constant_value_for_optimization. * c-tree.h (decl_constant_value_for_optimization): Removed. * c-fold.c (c_fold_array_ref): New function. (c_fully_fold_internal): Add LVAL argument, propagate it through recursive calls. For VAR_P call decl_constant_value and unshare if not LVAL and either optimizing or IN_INIT. Remove decl_constant_value_for_optimization calls. If IN_INIT and not LVAL, fold ARRAY_REF with STRING_CST and INTEGER_CST operands. (c_fully_fold): Add LVAL argument, pass it through to c_fully_fold_internal. (decl_constant_value_for_optimization): Removed. cp/ * cp-gimplify.c (c_fully_fold): Add LVAL argument, call cp_fold_maybe_rvalue instead of cp_fold_rvalue and pass it !LVAL. testsuite/ * gcc.dg/pr69960.c: New test. * gcc.dg/pr66618.c: New test. * gcc.dg/pr66618-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254930 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent fadadb9 commit 69cd03b

File tree

13 files changed

+199
-91
lines changed

13 files changed

+199
-91
lines changed

gcc/c-family/ChangeLog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2017-11-19 Jakub Jelinek <[email protected]>
2+
3+
PR c/66618
4+
PR c/69960
5+
* c-common.h (c_fully_fold): Add LVAL argument defaulted to false.
6+
17
2017-11-16 Joseph Myers <[email protected]>
28

39
* c.opt (-std=c17, std=gnu17, -std=iso9899:2017): Refer to 2018

gcc/c-family/c-common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
828828
extern enum conversion_safety unsafe_conversion_p (location_t, tree, tree, tree,
829829
bool);
830830
extern bool decl_with_nonnull_addr_p (const_tree);
831-
extern tree c_fully_fold (tree, bool, bool *);
831+
extern tree c_fully_fold (tree, bool, bool *, bool = false);
832832
extern tree c_wrap_maybe_const (tree, bool);
833833
extern tree c_common_truthvalue_conversion (location_t, tree);
834834
extern void c_apply_type_quals_to_decl (int, tree);

gcc/c/ChangeLog

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,23 @@
1+
2017-11-19 Jakub Jelinek <[email protected]>
2+
3+
PR c/66618
4+
PR c/69960
5+
* c-parser.c (c_parser_omp_atomic): Pass true as LVAL to c_fully_fold
6+
where needed.
7+
* c-typeck.c (build_unary_op, build_modify_expr, build_asm_expr,
8+
handle_omp_array_sections): Likewise.
9+
(digest_init): Don't call decl_constant_value_for_optimization.
10+
* c-tree.h (decl_constant_value_for_optimization): Removed.
11+
* c-fold.c (c_fold_array_ref): New function.
12+
(c_fully_fold_internal): Add LVAL argument, propagate it through
13+
recursive calls. For VAR_P call decl_constant_value and
14+
unshare if not LVAL and either optimizing or IN_INIT. Remove
15+
decl_constant_value_for_optimization calls. If IN_INIT and not LVAL,
16+
fold ARRAY_REF with STRING_CST and INTEGER_CST operands.
17+
(c_fully_fold): Add LVAL argument, pass it through to
18+
c_fully_fold_internal.
19+
(decl_constant_value_for_optimization): Removed.
20+
121
2017-11-15 Joseph Myers <[email protected]>
222

323
PR c/81156

gcc/c/c-fold.c

Lines changed: 100 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

73109
tree
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

107145
static tree
108146
c_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

Comments
 (0)