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