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:
Jakub Jelinek 2017-11-19 18:17:01 +01:00 committed by Jakub Jelinek
parent 4397fc04e3
commit f9c59f7e95
13 changed files with 199 additions and 91 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View 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" } */

View 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;
}

View 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");