PR tree-optimization/91567 - Spurious -Wformat-overflow warnings building glibc ...
[gcc.git] / gcc / testsuite / gcc.dg / tree-ssa / builtin-snprintf-6.c
1 /* Test to verify that snprintf can determine the length of a dynamically
2 constructed string argument and fold the result into a constant.
3 { dg-do compile }
4 { dg-options "-O2 -Wall -fdump-tree-optimized" } */
5
6 typedef __SIZE_TYPE__ size_t;
7
8 char* strcpy (char * restrict, const char * restrict);
9 int sprintf (char * restrict, const char *restrict, ...);
10 int snprintf (char * restrict, size_t, const char *restrict, ...);
11
12
13 #define CONCAT(x, y) x ## y
14 #define CAT(x, y) CONCAT (x, y)
15 #define FAILNAME(name, counter) \
16 CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
17
18 #define FAIL(name, counter) do { \
19 extern void FAILNAME (name, counter) (void); \
20 FAILNAME (name, counter)(); \
21 } while (0)
22
23 /* Macro to emit a call to funcation named
24 call_in_true_branch_not_eliminated_on_line_NNN()
25 for each call that's expected to be eliminated. The dg-final
26 scan-tree-dump-time directive at the bottom of the test verifies
27 that no such call appears in output. */
28 #define ELIM(expr) \
29 if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
30
31 #define ARGS(...) __VA_ARGS__
32
33 #define T(expect, init, fmt, ...) \
34 do { \
35 char a[] = init; \
36 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
37 } while (0)
38
39 /* Exercise a non-const local char array initialized by a string literal. */
40 void test_assign_string (void)
41 {
42 T (0, "", "%s", a);
43 T (1, "1", "%s", a);
44 T (4, "1234", "%s", a);
45 T (5, "123", "s=%s", a);
46 T (5, "1234", "s=%s", a + 1);
47 T (2, "1234", "s=%s", a + 4);
48 T (5, "12345", "s=%s", &a[2]);
49 T (5, "123456", "s=%.*s", 3, &a[2]);
50 }
51
52 /* Exercise a non-const local char array initialized by an initializer
53 list. */
54 void test_assign_init_list (void)
55 {
56 T (0, ARGS ({ 0 }), "%s", a);
57 T (1, ARGS ({ 1, 0 }), "%s", a);
58 T (3, ARGS ({ [3] = 0, [1] = 2, [0] = 1, [2] = 3 }), "%s", a);
59 T (3, ARGS ({ [3] = 0, [1] = 2, [0] = 1, [2] = 3, [4] = 0 }), "%s", a);
60 T (4, ARGS ({ 1, 2, 3, 4, 0 }), "%s", a);
61 T (5, ARGS ({ 1, 2, 3, 0 }), "s=%s", a);
62 T (5, ARGS ({ 1, 2, 3, 4, 0 }), "s=%s", a + 1);
63 T (2, ARGS ({ 1, 2, 3, 4, 0 }), "s=%s", a + 4);
64 T (5, ARGS ({ 1, 2, 3, 4, 5, 0 }), "s=%s", &a[2]);
65 T (5, ARGS ({ 1, 2, 3, 4, 5, 6, 0 }), "s=%.*s", 3, &a[2]);
66 }
67
68 #if __x86_64__
69
70 /* Enabled only on x86_64 to work around PR 83543. */
71
72 #undef T
73 #define T(expect, init, fmt, ...) \
74 do { \
75 struct { int n; char a[sizeof init]; } \
76 s = { sizeof init, init }; \
77 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
78 } while (0)
79
80 /* Exercise a non-const local struct initialized by an initializer
81 list. */
82 void test_assign_aggregate (void)
83 {
84 T (0, "", "%s", s.a);
85 T (1, "1", "%s", s.a);
86 T (4, "1234", "%s", s.a);
87 T (5, "123", "s=%s", s.a);
88 T (5, "1234", "s=%s", s.a + 1);
89 T (2, "1234", "s=%s", s.a + 4);
90 T (5, "12345", "s=%s", &s.a[2]);
91 T (5, "123456", "s=%.*s", 3, &s.a[2]);
92 }
93
94 /* { dg-final { scan-tree-dump-times "Function test_assign_aggregate" 1 "optimized" { xfail { { ! x86_64-*-* } || { ilp32 } } } } } */
95
96 #endif /* x86_64 */
97
98 #undef T
99 #define T(expect, init, fmt, ...) \
100 do { \
101 char a[sizeof init]; \
102 strcpy (a, init); \
103 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
104 } while (0)
105
106 /* Exercise a local char array initialized by a call to strcpy. */
107 void test_local_strcpy (void)
108 {
109 T (0, "", "%s", a);
110 T (1, "1", "%s", a);
111 T (2, "12", "%s", a);
112 T (3, "123", "%s", a);
113 T (4, "1234", "%s", a);
114 T (5, "123", "s=%s", a);
115 T (5, "1234", "s=%s", a + 1);
116 T (2, "1234", "s=%s", a + 4);
117 T (5, "12345", "s=%s", &a[2]);
118 T (5, "123456", "s=%.*s", 3, &a[2]);
119 }
120
121 #undef T
122 #define T(expect, init, fmt, ...) \
123 do { \
124 char a[n]; \
125 strcpy (a, init); \
126 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
127 } while (0)
128
129 /* Exercise a VLA initialized by a call to strcpy. */
130 void test_vla_strcpy (unsigned n)
131 {
132 T (0, "", "%s", a);
133 T (1, "1", "%s", a);
134 T (2, "12", "%s", a);
135 T (3, "123", "%s", a);
136 T (4, "1234", "%s", a);
137 T (5, "123", "s=%s", a);
138 T (5, "1234", "s=%s", a + 1);
139 T (2, "1234", "s=%s", a + 4);
140 T (5, "12345", "s=%s", &a[2]);
141 T (5, "123456", "s=%.*s", 3, &a[2]);
142 }
143
144 /* { dg-final { scan-tree-dump-times "printf" 0 "optimized" } }
145 { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
146 { dg-final { scan-tree-dump-times "not_eliminated" 0 "optimized" } } */