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
This commit is contained in:
parent
9a520f4073
commit
a45f71f537
@ -1,5 +1,8 @@
|
||||
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)
|
||||
into memcpy (x, y, 1) if memcpy can be expanded inline.
|
||||
|
||||
|
90
gcc/expr.c
90
gcc/expr.c
@ -8299,20 +8299,31 @@ is_aligning_offset (tree offset, tree exp)
|
||||
tree
|
||||
string_constant (tree arg, tree *ptr_offset)
|
||||
{
|
||||
tree array, offset;
|
||||
STRIP_NOPS (arg);
|
||||
|
||||
if (TREE_CODE (arg) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
|
||||
if (TREE_CODE (arg) == ADDR_EXPR)
|
||||
{
|
||||
*ptr_offset = size_zero_node;
|
||||
return TREE_OPERAND (arg, 0);
|
||||
}
|
||||
if (TREE_CODE (arg) == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (arg, 0)) == ARRAY_REF
|
||||
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg, 0), 0)) == STRING_CST)
|
||||
{
|
||||
*ptr_offset = convert (sizetype, TREE_OPERAND (TREE_OPERAND (arg, 0), 1));
|
||||
return TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
|
||||
if (TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
|
||||
{
|
||||
*ptr_offset = size_zero_node;
|
||||
return TREE_OPERAND (arg, 0);
|
||||
}
|
||||
else if (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL)
|
||||
{
|
||||
array = TREE_OPERAND (arg, 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)
|
||||
{
|
||||
@ -8323,17 +8334,62 @@ string_constant (tree arg, tree *ptr_offset)
|
||||
STRIP_NOPS (arg1);
|
||||
|
||||
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);
|
||||
return TREE_OPERAND (arg0, 0);
|
||||
array = TREE_OPERAND (arg0, 0);
|
||||
offset = arg1;
|
||||
}
|
||||
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);
|
||||
return TREE_OPERAND (arg1, 0);
|
||||
array = 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;
|
||||
|
@ -1,5 +1,8 @@
|
||||
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-2.c: New test.
|
||||
* gcc.c-torture/execute/builtins/memmove-2-lib.c: New.
|
||||
|
@ -0,0 +1 @@
|
||||
#include "lib/strlen.c"
|
68
gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3.c
Normal file
68
gcc/testsuite/gcc.c-torture/execute/builtins/strlen-3.c
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user