[PATCH] Add LVAL argument to c_fully_fold* and propagate it through (PR c/66618, PR c/69960)
Jakub Jelinek
jakub@redhat.com
Wed Nov 8 16:37:00 GMT 2017
Hi!
Here is an attempt to fix these two PRs. The C++ FE already has an LVAL
bool that it propagates through constexpr.c functions, or in
cp-gimplify.c through calling cp_fold_{maybe_,}rvalue where appropriate.
The C c_fully_fold was instead just calling decl_constant_value_for_optimization
in some spots where we've previously called c_fully_fold{_internal,} on
some rvalue.
decl_constant_value_for_optimization wasn't doing anything when -O0,
so we got different behavior between -O0 and -O1+ on what is accepted
in static initializers. Furthermore, we needed the hack to ignore
vars with ARRAY_TYPE or BLKmode, so that we actually wouldn't fold lvalues
to rvalues.
This patch adds LVAL to c_fully_fold{_internal,} and does what
decl_constant_value_for_optimization did inside of it (without the hacks,
furthermore, and additionally for -O0 when in initializers for consistency),
of course only if LVAL is false. Additionally, I've added folding of
"foo"[2] into 'o'. We have it in gimple-fold.c or so, so that one
isn't performed when not in_init.
Not sure about the COND_EXPR/VEC_COND_EXPR cases, right now I'm passing
false as LVAL for the first operand (condition) and lval as LVAL for the
other two (i.e. if called with lval == true on the whole *_COND_EXPR
decl_constant_value_for_optimization etc. isn't performed on op1/op2, while
without it it is). Can one take address of the whole COND_EXPR, or
have it on LHS of anything in C? If not, perhaps I could just pass false
in all the 3 calls. Though, then likely it would be called with lval == false
anyway.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2017-11-08 Jakub Jelinek <jakub@redhat.com>
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_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/c-family/c-common.h.jj 2017-10-12 20:51:30.000000000 +0200
+++ gcc/c-family/c-common.h 2017-11-08 12:20:59.874481318 +0100
@@ -827,7 +827,7 @@ extern tree c_build_bitfield_integer_typ
extern enum conversion_safety unsafe_conversion_p (location_t, tree, tree, tree,
bool);
extern bool decl_with_nonnull_addr_p (const_tree);
-extern tree c_fully_fold (tree, bool, bool *);
+extern tree c_fully_fold (tree, bool, bool *, bool = false);
extern tree c_wrap_maybe_const (tree, bool);
extern tree c_common_truthvalue_conversion (location_t, tree);
extern void c_apply_type_quals_to_decl (int, tree);
--- gcc/c/c-parser.c.jj 2017-11-08 12:29:02.000000000 +0100
+++ gcc/c/c-parser.c 2017-11-08 13:53:39.756889500 +0100
@@ -14748,7 +14748,7 @@ c_parser_omp_atomic (location_t loc, c_p
case NOP_EXPR: /* atomic write */
v = c_parser_cast_expression (parser, NULL).value;
non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL);
+ v = c_fully_fold (v, false, NULL, true);
if (v == error_mark_node)
goto saw_error;
if (non_lvalue_p)
@@ -14767,7 +14767,7 @@ c_parser_omp_atomic (location_t loc, c_p
{
lhs = c_parser_cast_expression (parser, NULL).value;
non_lvalue_p = !lvalue_p (lhs);
- lhs = c_fully_fold (lhs, false, NULL);
+ lhs = c_fully_fold (lhs, false, NULL, true);
if (lhs == error_mark_node)
goto saw_error;
if (non_lvalue_p)
@@ -14793,7 +14793,7 @@ c_parser_omp_atomic (location_t loc, c_p
{
v = c_parser_cast_expression (parser, NULL).value;
non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL);
+ v = c_fully_fold (v, false, NULL, true);
if (v == error_mark_node)
goto saw_error;
if (non_lvalue_p)
@@ -14814,7 +14814,7 @@ restart:
lhs = expr.value;
expr = default_function_array_conversion (eloc, expr);
unfolded_lhs = expr.value;
- lhs = c_fully_fold (lhs, false, NULL);
+ lhs = c_fully_fold (lhs, false, NULL, true);
orig_lhs = lhs;
switch (TREE_CODE (lhs))
{
@@ -14954,15 +14954,19 @@ restart:
if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
{
opcode = TREE_CODE (rhs1);
- rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
- rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+ true);
+ rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
+ true);
goto stmt_done;
}
if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
{
opcode = TREE_CODE (rhs1);
- rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL);
- rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL);
+ rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
+ true);
+ rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
+ true);
swapped = !commutative_tree_code (opcode);
goto stmt_done;
}
@@ -14981,7 +14985,7 @@ restart:
lhs = NULL_TREE;
expr = default_function_array_read_conversion (eloc, expr);
unfolded_lhs1 = expr.value;
- lhs1 = c_fully_fold (unfolded_lhs1, false, NULL);
+ lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
rhs1 = NULL_TREE;
c_parser_consume_token (parser);
goto restart;
@@ -14990,7 +14994,7 @@ restart:
{
opcode = NOP_EXPR;
expr = default_function_array_read_conversion (eloc, expr);
- rhs = c_fully_fold (expr.value, false, NULL);
+ rhs = c_fully_fold (expr.value, false, NULL, true);
rhs1 = NULL_TREE;
goto stmt_done;
}
@@ -15011,7 +15015,7 @@ restart:
expr = c_parser_expression (parser);
expr = default_function_array_read_conversion (eloc, expr);
rhs = expr.value;
- rhs = c_fully_fold (rhs, false, NULL);
+ rhs = c_fully_fold (rhs, false, NULL, true);
break;
}
stmt_done:
@@ -15021,7 +15025,7 @@ stmt_done:
goto saw_error;
v = c_parser_cast_expression (parser, NULL).value;
non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL);
+ v = c_fully_fold (v, false, NULL, true);
if (v == error_mark_node)
goto saw_error;
if (non_lvalue_p)
@@ -15033,7 +15037,7 @@ stmt_done:
lhs1 = expr.value;
expr = default_function_array_read_conversion (eloc, expr);
unfolded_lhs1 = expr.value;
- lhs1 = c_fully_fold (lhs1, false, NULL);
+ lhs1 = c_fully_fold (lhs1, false, NULL, true);
if (lhs1 == error_mark_node)
goto saw_error;
if (!lvalue_p (unfolded_lhs1))
--- gcc/c/c-typeck.c.jj 2017-11-01 22:49:10.000000000 +0100
+++ gcc/c/c-typeck.c 2017-11-08 13:29:18.882657643 +0100
@@ -4398,7 +4398,7 @@ build_unary_op (location_t location, enu
}
/* Ensure the argument is fully folded inside any SAVE_EXPR. */
- arg = c_fully_fold (arg, false, NULL);
+ arg = c_fully_fold (arg, false, NULL, true);
bool atomic_op;
atomic_op = really_atomic_lvalue (arg);
@@ -5822,7 +5822,7 @@ build_modify_expr (location_t location,
if (modifycode != NOP_EXPR)
{
- lhs = c_fully_fold (lhs, false, NULL);
+ lhs = c_fully_fold (lhs, false, NULL, true);
lhs = stabilize_reference (lhs);
/* Construct the RHS for any non-atomic compound assignemnt. */
@@ -7289,7 +7289,6 @@ digest_init (location_t init_loc, tree t
inside_init = TREE_OPERAND (inside_init, 0);
}
inside_init = c_fully_fold (inside_init, require_constant, &maybe_const);
- inside_init = decl_constant_value_for_optimization (inside_init);
/* Initialization of an array of chars from a string constant
optionally enclosed in braces. */
@@ -9899,7 +9898,7 @@ build_asm_expr (location_t loc, tree str
{
tree output = TREE_VALUE (tail);
- output = c_fully_fold (output, false, NULL);
+ output = c_fully_fold (output, false, NULL, true);
/* ??? Really, this should not be here. Users should be using a
proper lvalue, dammit. But there's a long history of using casts
@@ -9957,7 +9956,7 @@ build_asm_expr (location_t loc, tree str
mark it addressable. */
if (!allows_reg && allows_mem)
{
- input = c_fully_fold (input, false, NULL);
+ input = c_fully_fold (input, false, NULL, true);
/* Strip the nops as we allow this case. FIXME, this really
should be rejected or made deprecated. */
@@ -12723,7 +12722,7 @@ handle_omp_array_sections (tree c, enum
}
if (tem)
first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first);
- first = c_fully_fold (first, false, NULL);
+ first = c_fully_fold (first, false, NULL, true);
OMP_CLAUSE_DECL (c) = first;
}
else
--- gcc/c/c-tree.h.jj 2017-10-04 16:45:26.000000000 +0200
+++ gcc/c/c-tree.h 2017-11-08 11:45:45.651168952 +0100
@@ -770,8 +770,6 @@ set_c_expr_source_range (c_expr *expr,
source_range src_range);
/* In c-fold.c */
-extern tree decl_constant_value_for_optimization (tree);
-
extern vec<tree> incomplete_record_decls;
#if CHECKING_P
--- gcc/c/c-fold.c.jj 2017-05-25 10:36:58.000000000 +0200
+++ gcc/c/c-fold.c 2017-11-08 12:56:12.400811833 +0100
@@ -27,7 +27,8 @@ along with GCC; see the file COPYING3.
#include "intl.h"
#include "gimplify.h"
-static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool);
+static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool,
+ bool);
/* If DISABLE is true, stop issuing warnings. This is used when
parsing code that we know will not be executed. This function may
@@ -68,10 +69,11 @@ c_enable_warnings (bool enable)
folded expression. Function arguments have already been folded
before calling this function, as have the contents of SAVE_EXPR,
TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
- C_MAYBE_CONST_EXPR. */
+ C_MAYBE_CONST_EXPR. LVAL is true if it should be treated as an
+ lvalue. */
tree
-c_fully_fold (tree expr, bool in_init, bool *maybe_const)
+c_fully_fold (tree expr, bool in_init, bool *maybe_const, bool lval)
{
tree ret;
tree eptype = NULL_TREE;
@@ -87,7 +89,7 @@ c_fully_fold (tree expr, bool in_init, b
expr = TREE_OPERAND (expr, 0);
}
ret = c_fully_fold_internal (expr, in_init, maybe_const,
- &maybe_const_itself, false);
+ &maybe_const_itself, false, lval);
if (eptype)
ret = fold_convert_loc (loc, eptype, ret);
*maybe_const &= maybe_const_itself;
@@ -102,11 +104,13 @@ c_fully_fold (tree expr, bool in_init, b
*MAYBE_CONST_ITSELF is carried from only evaluated
subexpressions). FOR_INT_CONST indicates if EXPR is an expression
with integer constant operands, and if any of the operands doesn't
- get folded to an integer constant, don't fold the expression itself. */
+ get folded to an integer constant, don't fold the expression itself.
+ LVAL indicates folding of lvalue, where we can't replace it with
+ an rvalue. */
static tree
c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
- bool *maybe_const_itself, bool for_int_const)
+ bool *maybe_const_itself, bool for_int_const, bool lval)
{
tree ret = expr;
enum tree_code code = TREE_CODE (expr);
@@ -118,14 +122,27 @@ c_fully_fold_internal (tree expr, bool i
bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
bool nowarning = TREE_NO_WARNING (expr);
bool unused_p;
+ bool op0_lval = false;
source_range old_range;
/* Constants, declarations, statements, errors, and anything else not
counted as an expression cannot usefully be folded further at this
point. */
- if (!IS_EXPR_CODE_CLASS (kind)
- || kind == tcc_statement)
- return expr;
+ if (!IS_EXPR_CODE_CLASS (kind) || kind == tcc_statement)
+ {
+ /* Except for variables which we can optimize to its initializer. */
+ if (VAR_P (expr) && !lval && (optimize || in_init))
+ {
+ ret = decl_constant_value (expr);
+ /* Avoid unwanted tree sharing between the initializer and current
+ function's body where the tree can be modified e.g. by the
+ gimplifier. */
+ if (ret != expr && TREE_STATIC (expr))
+ ret = unshare_expr (ret);
+ return ret;
+ }
+ return expr;
+ }
if (IS_EXPR_CODE_CLASS (kind))
old_range = EXPR_LOCATION_RANGE (expr);
@@ -150,7 +167,7 @@ c_fully_fold_internal (tree expr, bool i
{
*maybe_const_itself = false;
inner = c_fully_fold_internal (inner, in_init, maybe_const_operands,
- maybe_const_itself, true);
+ maybe_const_itself, true, lval);
}
if (pre && !in_init)
ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
@@ -201,7 +218,7 @@ c_fully_fold_internal (tree expr, bool i
op1 = TREE_OPERAND (expr, 1);
op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const, lval);
STRIP_TYPE_NOPS (op0);
if (op0 != orig_op0)
ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
@@ -218,12 +235,51 @@ c_fully_fold_internal (tree expr, bool i
op2 = TREE_OPERAND (expr, 2);
op3 = TREE_OPERAND (expr, 3);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const, lval);
STRIP_TYPE_NOPS (op0);
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const, false);
STRIP_TYPE_NOPS (op1);
- op1 = decl_constant_value_for_optimization (op1);
+ /* Fold "foo"[2] in initializers. */
+ if (!lval
+ && in_init
+ && TREE_CODE (op0) == STRING_CST
+ && TREE_CODE (op1) == INTEGER_CST
+ && TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
+ && tree_fits_uhwi_p (op1))
+ {
+ tree ary = op0;
+ tree index = op1;
+ unsigned len = 0;
+ tree elem_type = TREE_TYPE (TREE_TYPE (ary));
+ unsigned elem_nchars = (TYPE_PRECISION (elem_type)
+ / TYPE_PRECISION (char_type_node));
+ len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+
+ tree nelts = array_type_nelts (TREE_TYPE (ary));
+ bool dummy1 = true, dummy2 = true;
+ nelts = c_fully_fold_internal (nelts, in_init, &dummy1, &dummy2,
+ for_int_const, false);
+ unsigned HOST_WIDE_INT i = tree_to_uhwi (index);
+ if (tree_int_cst_le (index, nelts)
+ && i < len
+ && i + elem_nchars <= len)
+ {
+ tree type = TREE_TYPE (expr);
+ if (elem_nchars == 1)
+ ret = build_int_cst (type,
+ TREE_STRING_POINTER (ary)[i]);
+ else
+ {
+ const unsigned char *ptr
+ = ((const unsigned char *)TREE_STRING_POINTER (ary)
+ + i * elem_nchars);
+ ret = native_interpret_expr (type, ptr, elem_nchars);
+ }
+ if (ret)
+ goto out;
+ }
+ }
if (op0 != orig_op0 || op1 != orig_op1)
ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
if (ret != expr)
@@ -232,15 +288,18 @@ c_fully_fold_internal (tree expr, bool i
TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
}
- ret = fold (ret);
+ if (!lval)
+ ret = fold (ret);
goto out;
- case COMPOUND_EXPR:
case MODIFY_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ op0_lval = true;
+ /* FALLTHRU */
+ case COMPOUND_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
@@ -278,21 +337,16 @@ c_fully_fold_internal (tree expr, bool i
orig_op0 = op0 = TREE_OPERAND (expr, 0);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const,
+ op0_lval);
STRIP_TYPE_NOPS (op0);
- if (code != MODIFY_EXPR
- && code != PREDECREMENT_EXPR
- && code != PREINCREMENT_EXPR
- && code != POSTDECREMENT_EXPR
- && code != POSTINCREMENT_EXPR)
- op0 = decl_constant_value_for_optimization (op0);
/* The RHS of a MODIFY_EXPR was fully folded when building that
expression for the sake of conversion warnings. */
if (code != MODIFY_EXPR)
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const,
+ code == COMPOUND_EXPR ? lval : false);
STRIP_TYPE_NOPS (op1);
- op1 = decl_constant_value_for_optimization (op1);
if (for_int_const && (TREE_CODE (op0) != INTEGER_CST
|| TREE_CODE (op1) != INTEGER_CST))
@@ -370,6 +424,13 @@ c_fully_fold_internal (tree expr, bool i
warn_for_div_by_zero (loc, op1);
goto out;
+ case ADDR_EXPR:
+ op0_lval = true;
+ goto unary;
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ op0_lval = lval;
+ /* FALLTHRU */
case INDIRECT_REF:
case FIX_TRUNC_EXPR:
case FLOAT_EXPR:
@@ -380,17 +441,14 @@ c_fully_fold_internal (tree expr, bool i
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
- case ADDR_EXPR:
case CONJ_EXPR:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
+ unary:
/* Unary operations. */
orig_op0 = op0 = TREE_OPERAND (expr, 0);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const,
+ op0_lval);
STRIP_TYPE_NOPS (op0);
- if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
- op0 = decl_constant_value_for_optimization (op0);
if (for_int_const && TREE_CODE (op0) != INTEGER_CST)
goto out;
@@ -440,7 +498,7 @@ c_fully_fold_internal (tree expr, bool i
orig_op0 = op0 = TREE_OPERAND (expr, 0);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self,
- for_int_const);
+ for_int_const, false);
STRIP_TYPE_NOPS (op0);
unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
@@ -448,7 +506,7 @@ c_fully_fold_internal (tree expr, bool i
: truthvalue_true_node));
c_disable_warnings (unused_p);
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self,
- for_int_const);
+ for_int_const, false);
STRIP_TYPE_NOPS (op1);
c_enable_warnings (unused_p);
@@ -486,18 +544,18 @@ c_fully_fold_internal (tree expr, bool i
orig_op1 = op1 = TREE_OPERAND (expr, 1);
orig_op2 = op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self,
- for_int_const);
+ for_int_const, false);
STRIP_TYPE_NOPS (op0);
c_disable_warnings (op0 == truthvalue_false_node);
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self,
- for_int_const);
+ for_int_const, lval);
STRIP_TYPE_NOPS (op1);
c_enable_warnings (op0 == truthvalue_false_node);
c_disable_warnings (op0 == truthvalue_true_node);
op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self,
- for_int_const);
+ for_int_const, lval);
STRIP_TYPE_NOPS (op2);
c_enable_warnings (op0 == truthvalue_true_node);
@@ -540,13 +598,13 @@ c_fully_fold_internal (tree expr, bool i
orig_op1 = op1 = TREE_OPERAND (expr, 1);
orig_op2 = op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const, false);
STRIP_TYPE_NOPS (op0);
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const, lval);
STRIP_TYPE_NOPS (op1);
op2 = c_fully_fold_internal (op2, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const, lval);
STRIP_TYPE_NOPS (op2);
if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
@@ -570,7 +628,8 @@ c_fully_fold_internal (tree expr, bool i
if (!SAVE_EXPR_FOLDED_P (expr))
{
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
- maybe_const_itself, for_int_const);
+ maybe_const_itself, for_int_const,
+ false);
TREE_OPERAND (expr, 0) = op0;
SAVE_EXPR_FOLDED_P (expr) = true;
}
@@ -604,28 +663,3 @@ c_fully_fold_internal (tree expr, bool i
}
return ret;
}
-
-/* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
- return EXP. Otherwise, return either EXP or its known constant
- value (if it has one), but return EXP if EXP has mode BLKmode. ???
- Is the BLKmode test appropriate? */
-
-tree
-decl_constant_value_for_optimization (tree exp)
-{
- tree ret;
-
- if (!optimize
- || !VAR_P (exp)
- || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
- || DECL_MODE (exp) == BLKmode)
- return exp;
-
- ret = decl_constant_value (exp);
- /* Avoid unwanted tree sharing between the initializer and current
- function's body where the tree can be modified e.g. by the
- gimplifier. */
- if (ret != exp && TREE_STATIC (exp))
- ret = unshare_expr (ret);
- return ret;
-}
--- gcc/cp/cp-gimplify.c.jj 2017-11-07 21:50:21.000000000 +0100
+++ gcc/cp/cp-gimplify.c 2017-11-08 12:23:37.427567897 +0100
@@ -2048,11 +2048,9 @@ cp_fully_fold (tree x)
C_MAYBE_CONST_EXPR. */
tree
-c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/)
+c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/, bool lval)
{
- /* c_fully_fold is only used on rvalues, and we need to fold CONST_DECL to
- INTEGER_CST. */
- return cp_fold_rvalue (x);
+ return cp_fold_maybe_rvalue (x, !lval);
}
static GTY((deletable)) hash_map<tree, tree> *fold_cache;
--- gcc/testsuite/gcc.dg/pr69960.c.jj 2017-11-08 10:39:42.743288400 +0100
+++ gcc/testsuite/gcc.dg/pr69960.c 2017-11-08 10:39:23.000000000 +0100
@@ -0,0 +1,12 @@
+/* PR c/69960 */
+/* { dg-do compile { target int32plus } } */
+
+#define TOLOWER(x) (x&~0x20)
+#define Word(s) \
+ s[1] ? s[2] ? s[3] ? \
+ (TOLOWER(s[0]) << 24) + (TOLOWER(s[1]) << 16) + (TOLOWER(s[2]) << 8) + TOLOWER(s[3]) : \
+ (TOLOWER(s[0]) << 16) + (TOLOWER(s[1]) << 8) + TOLOWER(s[2]) : \
+ (TOLOWER(s[0]) << 8) + TOLOWER(s[1]) : \
+ TOLOWER(s[0])
+
+const unsigned int _the = Word("the");
--- gcc/testsuite/gcc.dg/pr66618.c.jj 2017-11-08 11:44:05.512385840 +0100
+++ gcc/testsuite/gcc.dg/pr66618.c 2017-11-08 11:43:52.000000000 +0100
@@ -0,0 +1,11 @@
+/* PR c/66618 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+int
+foo (void)
+{
+ const int a = 0;
+ static int b = a; /* { dg-bogus "initializer element is not constant" } */
+ return b;
+}
Jakub
More information about the Gcc-patches
mailing list