PR3609
Mark Mitchell
mark@codesourcery.com
Thu Aug 9 10:24:00 GMT 2001
Franz --
Here is a patch that disables the strlen over-optimization. I've
tested it in the usual ways, but I'd like to have you verify that it
fixes your kernel bug before I check it in. Would you let me know
ASAP?
Thanks,
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2001-08-09 Mark Mitchell <mark@codesourcery.com>
* builtins.c (c_strlen): Do not try to optimize the case where
we are taking the length of a string formed by adding a
non-constant value to a string constant.
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.94.2.5
diff -c -p -r1.94.2.5 builtins.c
*** builtins.c 2001/08/04 00:24:13 1.94.2.5
--- builtins.c 2001/08/09 17:18:37
*************** c_strlen (src)
*** 240,265 ****
max = TREE_STRING_LENGTH (src) - 1;
ptr = TREE_STRING_POINTER (src);
! if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
! {
! /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
! compute the offset to the following null if we don't know where to
! start searching for it. */
! int i;
!
! for (i = 0; i < max; i++)
! if (ptr[i] == 0)
! return 0;
! /* We don't know the starting offset, but we do know that the string
! has no internal zero bytes. We can assume that the offset falls
! within the bounds of the string; otherwise, the programmer deserves
! what he gets. Subtract the offset from the length of the string,
! and return that. This would perhaps not be valid if we were dealing
! with named arrays in addition to literal string constants. */
! return size_diffop (size_int (max), offset_node);
! }
/* We have a known offset into the string. Start searching there for
a null character. */
--- 240,258 ----
max = TREE_STRING_LENGTH (src) - 1;
ptr = TREE_STRING_POINTER (src);
! /* If we don't know what the OFFSET is, we can't figure out the
! length. It's tempting to say that it must be the length of the
! string, less the offset, if there are no embedded NULs in SRC --
! but that's not safe. In particular, the OFFSET might point past
! SRC into another string; consider something like:
! strlen((char*) ((size_t)("abc") + 47));
! This kind of code appears in the Linux kernel. There's nothing
! about this that is invalid, although it clearly depends on
! knowledge of where the compiler will put the string "abc". */
! if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
! return NULL_TREE;
/* We have a known offset into the string. Start searching there for
a null character. */
Index: testsuite/gcc.c-torture/execute/string-opt-3.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-3.c,v
retrieving revision 1.5
diff -c -p -r1.5 string-opt-3.c
*** string-opt-3.c 2000/12/27 15:29:52 1.5
--- string-opt-3.c 2001/08/09 17:18:49
***************
*** 1,4 ****
! /* Copyright (C) 2000 Free Software Foundation.
Ensure all expected transformations of builtin strlen, strcmp,
strrchr and rindex occur and perform correctly.
--- 1,4 ----
! /* Copyright (C) 2000, 2001 Free Software Foundation.
Ensure all expected transformations of builtin strlen, strcmp,
strrchr and rindex occur and perform correctly.
*************** int main()
*** 22,29 ****
--- 22,35 ----
abort ();
if (strlen (foo + 4) != 7)
abort ();
+ #ifndef __OPTIMIZE__
+ /* We intentionally do not try to optimize this to a builtin, so we
+ cannot do this test when optimizing. */
if (strlen (foo + (x++ & 7)) != 5)
abort ();
+ #else
+ x++;
+ #endif
if (x != 7)
abort ();
if (strcmp (foo, "hello") <= 0)
Index: testsuite/gcc.c-torture/execute/string-opt-8.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c,v
retrieving revision 1.5
diff -c -p -r1.5 string-opt-8.c
*** string-opt-8.c 2001/01/03 16:54:46 1.5
--- string-opt-8.c 2001/08/09 17:18:49
*************** extern void abort (void);
*** 9,14 ****
--- 9,16 ----
typedef __SIZE_TYPE__ size_t;
extern int strncmp (const char *, const char *, size_t);
+ int ok_to_call_strncmp;
+
int main ()
{
const char *const s1 = "hello world";
*************** int main ()
*** 42,47 ****
--- 44,52 ----
if (strncmp ("aaaaa", "hello", 1) >= 0)
abort();
+ /* From here on, we will call strncmp, but that's what we expect. */
+ ok_to_call_strncmp = 1;
+
s2 = s1; s3 = s1+4;
if (strncmp (++s2, ++s3, 0) != 0 || s2 != s1+1 || s3 != s1+5)
abort();
*************** int main ()
*** 228,239 ****
}
#ifdef __OPTIMIZE__
! /* When optimizing, all the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
! static char *
strncmp(const char *s1, const char *s2, size_t n)
{
! abort();
}
#endif
--- 233,257 ----
}
#ifdef __OPTIMIZE__
! /* When optimizing, some of the above cases should be transformed into
something else. So any remaining calls to the original function
should abort. */
! static int
strncmp(const char *s1, const char *s2, size_t n)
{
! size_t i;
!
! if (!ok_to_call_strncmp)
! abort();
!
! for (i = 0; i < n; ++i)
! {
! if (s1[i] < s2[i])
! return -1;
! else if (s2[i] < s1[i])
! return 1;
! }
!
! return 0;
}
#endif
More information about the Gcc-patches
mailing list