1 /* PR tree-optimization/83821 - local aggregate initialization defeats
2    strlen optimization
3    Verify that stores that overwrite an interior nul are correctly
4    reflected in strlen results.
5    { dg-do run }
6    { dg-options "-O2 -Wall" }
7    { dg-require-effective-target alloca } */
8 
9 #define false (0 == 1)
10 #define true (0 == 0)
11 #define assert(e)							\
12   ((e) ? (void)0 : (__builtin_printf ("assertion failed on line %i\n",	\
13 				      __LINE__), __builtin_abort ()))
14 
15 #define ATTR(...) __attribute__ ((__VA_ARGS__))
16 
ATTR(always_inline)17 static inline int ATTR (always_inline)
18 assign_and_get_length (char *p, _Bool clear)
19 {
20   p[0] = 'a';
21 
22   if (clear)
23     p[1] = 0;
24 
25   p[2] = 'c';
26 
27   if (clear)
28     p[3] = 0;
29 
30   p[1] = 'b';
31 
32   return __builtin_strlen (p);
33 }
34 
ATTR(noipa)35 ATTR (noipa) void array_get_length (void)
36 {
37   char a[4];
38   unsigned n = assign_and_get_length (a, true);
39   assert (n == 3);
40 }
41 
ATTR(noipa)42 ATTR (noipa) void clear_array_get_length (void)
43 {
44   char a[4] = { };
45   unsigned n = assign_and_get_length (a, false);
46   assert (n == 3);
47 }
48 
ATTR(noipa)49 ATTR (noipa) void calloc_get_length (void)
50 {
51   char *p = __builtin_calloc (5, 1);
52   unsigned n = assign_and_get_length (p, false);
53   assert (n == 3);
54 }
55 
ATTR(noipa)56 ATTR (noipa) void malloc_get_length (void)
57 {
58   char *p = __builtin_malloc (5);
59   unsigned n = assign_and_get_length (p, true);
60   assert (n == 3);
61 }
62 
ATTR(noipa)63 ATTR (noipa) void vla_get_length (int n)
64 {
65   char a[n];
66   unsigned len = assign_and_get_length (a, true);
67   assert (len == 3);
68 }
69 
70 
ATTR(always_inline)71 static inline void ATTR (always_inline)
72 assign_and_test_length (char *p, _Bool clear)
73 {
74   p[0] = 'a';
75 
76   if (clear)
77     p[1] = 0;
78 
79   p[2] = 'c';
80 
81   if (clear)
82     p[3] = 0;
83 
84   unsigned n0 =  __builtin_strlen (p);
85 
86   p[1] = 'b';
87 
88   unsigned n1 =  __builtin_strlen (p);
89   assert (n0 != n1);
90 }
91 
ATTR(noipa)92 ATTR (noipa) void array_test_length (void)
93 {
94   char a[4];
95   assign_and_test_length (a, true);
96 }
97 
ATTR(noipa)98 ATTR (noipa) void clear_array_test_length (void)
99 {
100   char a[4] = { };
101   assign_and_test_length (a, false);
102 }
103 
ATTR(noipa)104 ATTR (noipa) void calloc_test_length (void)
105 {
106   char *p = __builtin_calloc (5, 1);
107   assign_and_test_length (p, false);
108 }
109 
ATTR(noipa)110 ATTR (noipa) void malloc_test_length (void)
111 {
112   char *p = __builtin_malloc (5);
113   assign_and_test_length (p, true);
114 }
115 
ATTR(noipa)116 ATTR (noipa) void vla_test_length (int n)
117 {
118   char a[n];
119   assign_and_test_length (a, true);
120 }
121 
main(void)122 int main (void)
123 {
124   array_get_length ();
125   clear_array_get_length ();
126   calloc_get_length ();
127   malloc_get_length ();
128   vla_get_length (4);
129 
130   array_test_length ();
131   clear_array_test_length ();
132   calloc_test_length ();
133   malloc_test_length ();
134   vla_test_length (4);
135 }
136 
137