Commit b4923738 by Jakub Jelinek Committed by Jakub Jelinek

re PR c/83801 ([avr] String constant in __flash not put into .progmem)

	PR c/83801
	* c-tree.h (decl_constant_value_1): Add a bool argument.
	* c-typeck.c (decl_constant_value_1): Add IN_INIT argument, allow
	returning a CONSTRUCTOR if it is true.  Use error_operand_p.
	(decl_constant_value): Adjust caller.
	* c-fold.c (c_fully_fold_internal): If in_init, pass true to
	decl_constant_value_1 as IN_INIT.  Otherwise, punt if
	decl_constant_value returns initializer that has BLKmode or
	array type.
	(c_fully_fold_internal) <case COMPONENT_REF>: Fold if !lval.

	* gcc.dg/pr83801.c: New test.

From-SVN: r256608
parent 567a6e1c
2018-01-13 Jakub Jelinek <jakub@redhat.com>
PR c/83801
* c-tree.h (decl_constant_value_1): Add a bool argument.
* c-typeck.c (decl_constant_value_1): Add IN_INIT argument, allow
returning a CONSTRUCTOR if it is true. Use error_operand_p.
(decl_constant_value): Adjust caller.
* c-fold.c (c_fully_fold_internal): If in_init, pass true to
decl_constant_value_1 as IN_INIT. Otherwise, punt if
decl_constant_value returns initializer that has BLKmode or
array type.
(c_fully_fold_internal) <case COMPONENT_REF>: Fold if !lval.
2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com> David Sherwood <david.sherwood@arm.com>
......
...@@ -168,9 +168,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, ...@@ -168,9 +168,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
if (VAR_P (expr) && !lval && (optimize || in_init)) if (VAR_P (expr) && !lval && (optimize || in_init))
{ {
if (in_init) if (in_init)
ret = decl_constant_value_1 (expr); ret = decl_constant_value_1 (expr, true);
else else
ret = decl_constant_value (expr); {
ret = decl_constant_value (expr);
if (ret != expr
&& (TYPE_MODE (TREE_TYPE (ret)) == BLKmode
|| TREE_CODE (TREE_TYPE (ret)) == ARRAY_TYPE))
return expr;
}
/* Avoid unwanted tree sharing between the initializer and current /* Avoid unwanted tree sharing between the initializer and current
function's body where the tree can be modified e.g. by the function's body where the tree can be modified e.g. by the
gimplifier. */ gimplifier. */
...@@ -264,6 +270,8 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, ...@@ -264,6 +270,8 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
TREE_READONLY (ret) = TREE_READONLY (expr); TREE_READONLY (ret) = TREE_READONLY (expr);
TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
} }
if (!lval)
ret = fold (ret);
goto out; goto out;
case ARRAY_REF: case ARRAY_REF:
......
...@@ -640,7 +640,7 @@ extern struct c_expr default_function_array_read_conversion (location_t, ...@@ -640,7 +640,7 @@ extern struct c_expr default_function_array_read_conversion (location_t,
struct c_expr); struct c_expr);
extern struct c_expr convert_lvalue_to_rvalue (location_t, struct c_expr, extern struct c_expr convert_lvalue_to_rvalue (location_t, struct c_expr,
bool, bool); bool, bool);
extern tree decl_constant_value_1 (tree); extern tree decl_constant_value_1 (tree, bool);
extern void mark_exp_read (tree); extern void mark_exp_read (tree);
extern tree composite_type (tree, tree); extern tree composite_type (tree, tree);
extern tree build_component_ref (location_t, tree, tree, location_t); extern tree build_component_ref (location_t, tree, tree, location_t);
......
...@@ -1832,20 +1832,20 @@ c_size_in_bytes (const_tree type) ...@@ -1832,20 +1832,20 @@ c_size_in_bytes (const_tree type)
/* Return either DECL or its known constant value (if it has one). */ /* Return either DECL or its known constant value (if it has one). */
tree tree
decl_constant_value_1 (tree decl) decl_constant_value_1 (tree decl, bool in_init)
{ {
if (/* Note that DECL_INITIAL isn't valid for a PARM_DECL. */ if (/* Note that DECL_INITIAL isn't valid for a PARM_DECL. */
TREE_CODE (decl) != PARM_DECL TREE_CODE (decl) != PARM_DECL
&& !TREE_THIS_VOLATILE (decl) && !TREE_THIS_VOLATILE (decl)
&& TREE_READONLY (decl) && TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE && DECL_INITIAL (decl) != NULL_TREE
&& TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK && !error_operand_p (DECL_INITIAL (decl))
/* This is invalid if initial value is not constant. /* This is invalid if initial value is not constant.
If it has either a function call, a memory reference, If it has either a function call, a memory reference,
or a variable, then re-evaluating it could give different results. */ or a variable, then re-evaluating it could give different results. */
&& TREE_CONSTANT (DECL_INITIAL (decl)) && TREE_CONSTANT (DECL_INITIAL (decl))
/* Check for cases where this is sub-optimal, even though valid. */ /* Check for cases where this is sub-optimal, even though valid. */
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) && (in_init || TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR))
return DECL_INITIAL (decl); return DECL_INITIAL (decl);
return decl; return decl;
} }
...@@ -1858,7 +1858,7 @@ decl_constant_value (tree decl) ...@@ -1858,7 +1858,7 @@ decl_constant_value (tree decl)
{ {
/* Don't change a variable array bound or initial value to a constant /* Don't change a variable array bound or initial value to a constant
in a place where a variable is invalid. */ in a place where a variable is invalid. */
return current_function_decl ? decl_constant_value_1 (decl) : decl; return current_function_decl ? decl_constant_value_1 (decl, false) : decl;
} }
/* Convert the array expression EXP to a pointer. */ /* Convert the array expression EXP to a pointer. */
......
2018-01-13 Jakub Jelinek <jakub@redhat.com>
PR c/83801
* gcc.dg/pr83801.c: New test.
2018-01-13 Paul Thomas <pault@gcc.gnu.org> 2018-01-13 Paul Thomas <pault@gcc.gnu.org>
PR fortran/52162 PR fortran/52162
......
/* PR c/83801 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-original" } */
static const char a[] = "01234567890123456789012345678901234567890123456789012345678901234567890123456789";
static const char b = a[27];
struct S { const char c[30]; const char d[30]; };
static const struct S e[] = { { "01234567890123456789012345678", "90123456789012345678901234567" },
{ "89012345678901234567890123456", "78901234567890123456789012345" } };
static const char f = e[1].c[4];
char
foo (int i)
{
return a[i];
}
char
bar (int i)
{
return e[0].d[i];
}
/* { dg-final { scan-tree-dump {a\[i]} "original" } } */
/* { dg-final { scan-tree-dump-not {"01234567890123456789012345678901234567890123456789012345678901234567890123456789"\[i]} "original" } } */
/* { dg-final { scan-tree-dump {e\[0]\.d\[i]} "original" } } */
/* { dg-final { scan-tree-dump-not {"90123456789012345678901234567"\[i]} "original" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment