Commit a45f71f5 by Jakub Jelinek Committed by Jakub Jelinek

expr.c (string_constant): Handle also read-only variables initialized to string literals.

	* expr.c (string_constant): Handle also read-only variables
	initialized to string literals.

	* gcc.c-torture/execute/builtins/strlen-3.c: New test.
	* gcc.c-torture/execute/builtins/strlen-3-lib.c: New.

From-SVN: r87540
parent 9a520f40
2004-09-15 Jakub Jelinek <jakub@redhat.com> 2004-09-15 Jakub Jelinek <jakub@redhat.com>
* expr.c (string_constant): Handle also read-only variables
initialized to string literals.
* builtins.c (expand_builtin_memmove): Optimize memmove (x, y, 1) * builtins.c (expand_builtin_memmove): Optimize memmove (x, y, 1)
into memcpy (x, y, 1) if memcpy can be expanded inline. into memcpy (x, y, 1) if memcpy can be expanded inline.
......
...@@ -8299,20 +8299,31 @@ is_aligning_offset (tree offset, tree exp) ...@@ -8299,20 +8299,31 @@ is_aligning_offset (tree offset, tree exp)
tree tree
string_constant (tree arg, tree *ptr_offset) string_constant (tree arg, tree *ptr_offset)
{ {
tree array, offset;
STRIP_NOPS (arg); STRIP_NOPS (arg);
if (TREE_CODE (arg) == ADDR_EXPR if (TREE_CODE (arg) == ADDR_EXPR)
&& TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
{ {
*ptr_offset = size_zero_node; if (TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
return TREE_OPERAND (arg, 0); {
} *ptr_offset = size_zero_node;
if (TREE_CODE (arg) == ADDR_EXPR return TREE_OPERAND (arg, 0);
&& TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF }
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)) == STRING_CST) else if (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL)
{ {
*ptr_offset = convert (sizetype, TREE_OPERAND (TREE_OPERAND (arg, 0), 1)); array = TREE_OPERAND (arg, 0);
return TREE_OPERAND (TREE_OPERAND (arg, 0), 0); offset = size_zero_node;
}
else if (TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF)
{
array = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
offset = TREE_OPERAND (TREE_OPERAND (arg, 0), 1);
if (TREE_CODE (array) != STRING_CST
&& TREE_CODE (array) != VAR_DECL)
return 0;
}
else
return 0;
} }
else if (TREE_CODE (arg) == PLUS_EXPR) else if (TREE_CODE (arg) == PLUS_EXPR)
{ {
...@@ -8323,17 +8334,62 @@ string_constant (tree arg, tree *ptr_offset) ...@@ -8323,17 +8334,62 @@ string_constant (tree arg, tree *ptr_offset)
STRIP_NOPS (arg1); STRIP_NOPS (arg1);
if (TREE_CODE (arg0) == ADDR_EXPR if (TREE_CODE (arg0) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST) && (TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST
|| TREE_CODE (TREE_OPERAND (arg0, 0)) == VAR_DECL))
{ {
*ptr_offset = convert (sizetype, arg1); array = TREE_OPERAND (arg0, 0);
return TREE_OPERAND (arg0, 0); offset = arg1;
} }
else if (TREE_CODE (arg1) == ADDR_EXPR else if (TREE_CODE (arg1) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST) && (TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST
|| TREE_CODE (TREE_OPERAND (arg1, 0)) == VAR_DECL))
{ {
*ptr_offset = convert (sizetype, arg0); array = TREE_OPERAND (arg1, 0);
return TREE_OPERAND (arg1, 0); offset = arg0;
} }
else
return 0;
}
else
return 0;
if (TREE_CODE (array) == STRING_CST)
{
*ptr_offset = convert (sizetype, offset);
return array;
}
else if (TREE_CODE (array) == VAR_DECL)
{
int length;
/* Variables initialized to string literals can be handled too. */
if (DECL_INITIAL (array) == NULL_TREE
|| TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
return 0;
/* If they are read-only, non-volatile and bind locally. */
if (! TREE_READONLY (array)
|| TREE_SIDE_EFFECTS (array)
|| ! targetm.binds_local_p (array))
return 0;
/* Avoid const char foo[4] = "abcde"; */
if (DECL_SIZE_UNIT (array) == NULL_TREE
|| TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
|| (length = TREE_STRING_LENGTH (DECL_INITIAL (array))) <= 0
|| compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
return 0;
/* If variable is bigger than the string literal, OFFSET must be constant
and inside of the bounds of the string literal. */
offset = convert (sizetype, offset);
if (compare_tree_int (DECL_SIZE_UNIT (array), length) > 0
&& (! host_integerp (offset, 1)
|| compare_tree_int (offset, length) >= 0))
return 0;
*ptr_offset = offset;
return DECL_INITIAL (array);
} }
return 0; return 0;
......
2004-09-15 Jakub Jelinek <jakub@redhat.com> 2004-09-15 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/builtins/strlen-3.c: New test.
* gcc.c-torture/execute/builtins/strlen-3-lib.c: New.
* gcc.c-torture/execute/builtins/memmove.c (main_test): Formatting. * gcc.c-torture/execute/builtins/memmove.c (main_test): Formatting.
* gcc.c-torture/execute/builtins/memmove-2.c: New test. * gcc.c-torture/execute/builtins/memmove-2.c: New test.
* gcc.c-torture/execute/builtins/memmove-2-lib.c: New. * gcc.c-torture/execute/builtins/memmove-2-lib.c: New.
......
/* Copyright (C) 2004 Free Software Foundation.
Test strlen on const variables initialized to string literals.
Written by Jakub Jelinek, 9/14/2004. */
extern void abort (void);
extern __SIZE_TYPE__ strlen (const char *);
extern char *strcpy (char *, const char *);
const char bar[] = "Hello, World!";
const char baz[] = "hello, world?";
const char larger[20] = "short string";
extern volatile int inside_main;
int l1 = 1;
int x = 6;
void
main_test(void)
{
const char *foo;
int i;
if (strlen (bar) != 13)
abort ();
if (strlen (bar + 3) != 10)
abort ();
if (strlen (&bar[6]) != 7)
abort ();
if (strlen (bar + (x++ & 7)) != 7)
abort ();
if (x != 7)
abort ();
#ifdef __OPTIMIZE__
foo = bar;
for (i = 0; i < 4; ++i)
{
if (i == l1 - 1)
foo = "HELLO, WORLD!";
else if (i == l1)
foo = bar;
else if (i == l1 + 1)
foo = "hello, world!";
else
foo = baz;
}
if (strlen (foo) != 13)
abort ();
#endif
if (strlen (larger) != 12)
abort ();
if (strlen (&larger[10]) != 2)
abort ();
inside_main = 0;
/* This will result in strlen call, because larger
array is bigger than its initializer. */
if (strlen (larger + (x++ & 7)) != 5)
abort ();
if (x != 8)
abort ();
inside_main = 1;
}
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