blob: 0c9da3c1b59e3da73d10d37c4fabb32f22e3f330 [file] [log] [blame]
/* PR tree-optimization/83821 - local aggregate initialization defeats
strlen optimization
Verify that stores that overwrite an interior nul are correctly
reflected in strlen results.
{ dg-do run }
{ dg-options "-O2 -Wall" }
{ dg-require-effective-target alloca } */
#define false (0 == 1)
#define true (0 == 0)
#define assert(e) \
((e) ? (void)0 : (__builtin_printf ("assertion failed on line %i\n", \
__LINE__), __builtin_abort ()))
#define ATTR(...) __attribute__ ((__VA_ARGS__))
static inline int ATTR (always_inline)
assign_and_get_length (char *p, _Bool clear)
{
p[0] = 'a';
if (clear)
p[1] = 0;
p[2] = 'c';
if (clear)
p[3] = 0;
p[1] = 'b';
return __builtin_strlen (p);
}
ATTR (noipa) void array_get_length (void)
{
char a[4];
unsigned n = assign_and_get_length (a, true);
assert (n == 3);
}
ATTR (noipa) void clear_array_get_length (void)
{
char a[4] = { };
unsigned n = assign_and_get_length (a, false);
assert (n == 3);
}
ATTR (noipa) void calloc_get_length (void)
{
char *p = __builtin_calloc (5, 1);
unsigned n = assign_and_get_length (p, false);
assert (n == 3);
}
ATTR (noipa) void malloc_get_length (void)
{
char *p = __builtin_malloc (5);
unsigned n = assign_and_get_length (p, true);
assert (n == 3);
}
ATTR (noipa) void vla_get_length (int n)
{
char a[n];
unsigned len = assign_and_get_length (a, true);
assert (len == 3);
}
static inline void ATTR (always_inline)
assign_and_test_length (char *p, _Bool clear)
{
p[0] = 'a';
if (clear)
p[1] = 0;
p[2] = 'c';
if (clear)
p[3] = 0;
unsigned n0 = __builtin_strlen (p);
p[1] = 'b';
unsigned n1 = __builtin_strlen (p);
assert (n0 != n1);
}
ATTR (noipa) void array_test_length (void)
{
char a[4];
assign_and_test_length (a, true);
}
ATTR (noipa) void clear_array_test_length (void)
{
char a[4] = { };
assign_and_test_length (a, false);
}
ATTR (noipa) void calloc_test_length (void)
{
char *p = __builtin_calloc (5, 1);
assign_and_test_length (p, false);
}
ATTR (noipa) void malloc_test_length (void)
{
char *p = __builtin_malloc (5);
assign_and_test_length (p, true);
}
ATTR (noipa) void vla_test_length (int n)
{
char a[n];
assign_and_test_length (a, true);
}
int main (void)
{
array_get_length ();
clear_array_get_length ();
calloc_get_length ();
malloc_get_length ();
vla_get_length (4);
array_test_length ();
clear_array_test_length ();
calloc_test_length ();
malloc_test_length ();
vla_test_length (4);
}