re PR c/66618 (Failure to diagnose non-constant initializer for static object with -O1)
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. From-SVN: r254930
This commit is contained in:
parent
4397fc04e3
commit
f9c59f7e95
@ -1,3 +1,9 @@
|
||||
2017-11-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/66618
|
||||
PR c/69960
|
||||
* c-common.h (c_fully_fold): Add LVAL argument defaulted to false.
|
||||
|
||||
2017-11-16 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* c.opt (-std=c17, std=gnu17, -std=iso9899:2017): Refer to 2018
|
||||
|
@ -828,7 +828,7 @@ extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
|
||||
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);
|
||||
|
@ -1,3 +1,23 @@
|
||||
2017-11-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/66618
|
||||
PR c/69960
|
||||
* 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.
|
||||
|
||||
2017-11-15 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR c/81156
|
||||
|
165
gcc/c/c-fold.c
165
gcc/c/c-fold.c
@ -27,7 +27,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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
|
||||
@ -55,6 +56,40 @@ c_enable_warnings (bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to fold ARRAY_REF ary[index] if possible and not handled by
|
||||
normal fold, return NULL_TREE otherwise. */
|
||||
|
||||
static tree
|
||||
c_fold_array_ref (tree type, tree ary, tree index)
|
||||
{
|
||||
if (TREE_CODE (ary) != STRING_CST
|
||||
|| TREE_CODE (index) != INTEGER_CST
|
||||
|| TREE_OVERFLOW (index)
|
||||
|| TREE_CODE (TREE_TYPE (ary)) != ARRAY_TYPE
|
||||
|| !tree_fits_uhwi_p (index))
|
||||
return NULL_TREE;
|
||||
|
||||
tree elem_type = TREE_TYPE (TREE_TYPE (ary));
|
||||
unsigned elem_nchars = (TYPE_PRECISION (elem_type)
|
||||
/ TYPE_PRECISION (char_type_node));
|
||||
unsigned 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, true, &dummy1, &dummy2, false, false);
|
||||
unsigned HOST_WIDE_INT i = tree_to_uhwi (index);
|
||||
if (!tree_int_cst_le (index, nelts)
|
||||
|| i >= len
|
||||
|| i + elem_nchars > len)
|
||||
return NULL_TREE;
|
||||
|
||||
if (elem_nchars == 1)
|
||||
return build_int_cst (type, TREE_STRING_POINTER (ary)[i]);
|
||||
|
||||
const unsigned char *ptr
|
||||
= ((const unsigned char *)TREE_STRING_POINTER (ary) + i * elem_nchars);
|
||||
return native_interpret_expr (type, ptr, elem_nchars);
|
||||
}
|
||||
|
||||
/* Fully fold EXPR, an expression that was not folded (beyond integer
|
||||
constant expressions and null pointer constants) when being built
|
||||
up. If IN_INIT, this is in a static initializer and certain
|
||||
@ -68,10 +103,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 +123,7 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const)
|
||||
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 +138,13 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const)
|
||||
*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 +156,27 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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 +201,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
{
|
||||
*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 +252,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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 +269,19 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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)
|
||||
{
|
||||
ret = c_fold_array_ref (TREE_TYPE (expr), op0, op1);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = expr;
|
||||
}
|
||||
if (op0 != orig_op0 || op1 != orig_op1)
|
||||
ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
|
||||
if (ret != expr)
|
||||
@ -232,15 +290,18 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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 +339,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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, 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 +425,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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 +442,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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 +499,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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 +507,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
: 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 +545,18 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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, false);
|
||||
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, false);
|
||||
STRIP_TYPE_NOPS (op2);
|
||||
c_enable_warnings (op0 == truthvalue_true_node);
|
||||
|
||||
@ -540,13 +599,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
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, false);
|
||||
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, false);
|
||||
STRIP_TYPE_NOPS (op2);
|
||||
|
||||
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,
|
||||
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 +664,3 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -15312,7 +15312,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
|
||||
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)
|
||||
@ -15331,7 +15331,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
|
||||
{
|
||||
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)
|
||||
@ -15357,7 +15357,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
|
||||
{
|
||||
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)
|
||||
@ -15378,7 +15378,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))
|
||||
{
|
||||
@ -15518,15 +15518,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;
|
||||
}
|
||||
@ -15545,7 +15549,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;
|
||||
@ -15554,7 +15558,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;
|
||||
}
|
||||
@ -15575,7 +15579,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:
|
||||
@ -15585,7 +15589,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)
|
||||
@ -15597,7 +15601,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))
|
||||
|
@ -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
|
||||
|
@ -4398,7 +4398,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
|
||||
}
|
||||
|
||||
/* 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, tree lhs, tree lhs_origtype,
|
||||
|
||||
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 type, tree init, tree origtype,
|
||||
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 string, tree outputs, tree inputs,
|
||||
{
|
||||
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 string, tree outputs, tree inputs,
|
||||
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 c_omp_region_type ort)
|
||||
}
|
||||
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
|
||||
|
@ -1,3 +1,10 @@
|
||||
2017-11-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/66618
|
||||
PR c/69960
|
||||
* cp-gimplify.c (c_fully_fold): Add LVAL argument, call
|
||||
cp_fold_maybe_rvalue instead of cp_fold_rvalue and pass it !LVAL.
|
||||
|
||||
2017-11-16 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/79092 - non-type args of different types are different
|
||||
|
@ -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;
|
||||
|
@ -1,3 +1,11 @@
|
||||
2017-11-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/66618
|
||||
PR c/69960
|
||||
* gcc.dg/pr69960.c: New test.
|
||||
* gcc.dg/pr66618.c: New test.
|
||||
* gcc.dg/pr66618-2.c: New test.
|
||||
|
||||
2017-11-18 Janne Blomqvist <jb@gcc.gnu.org>
|
||||
|
||||
PR fortran/44292
|
||||
|
10
gcc/testsuite/gcc.dg/pr66618-2.c
Normal file
10
gcc/testsuite/gcc.dg/pr66618-2.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* PR c/66618 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-pedantic-errors" } */
|
||||
|
||||
int a = "foo"[2];
|
||||
int b = 1["bar"];
|
||||
int c = "baz"[__INT_MAX__ * -2]; /* { dg-error "initializer element is not constant" } */
|
||||
int d = "str"[3]; /* { dg-warning "integer overflow in expression of type" "" { target *-*-* } .-1 } */
|
||||
int e = "str"[4]; /* { dg-error "initializer element is not constant" } */
|
||||
int f = "str"[-1]; /* { dg-error "initializer element is not constant" } */
|
11
gcc/testsuite/gcc.dg/pr66618.c
Normal file
11
gcc/testsuite/gcc.dg/pr66618.c
Normal file
@ -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;
|
||||
}
|
12
gcc/testsuite/gcc.dg/pr69960.c
Normal file
12
gcc/testsuite/gcc.dg/pr69960.c
Normal file
@ -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");
|
Loading…
Reference in New Issue
Block a user