/* 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); }