libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / testsuite / gcc.dg / tree-ssa / builtin-snprintf-7.c
blobbf5072e955cfbeefe0dae36fb04448276fca8e00
1 /* Test to verify that snprintf can determine the correct range
2 of lengths of dynamically constructed string arguments.
3 { dg-do compile }
4 { dg-options "-O2 -Wall -fdump-tree-optimized" } */
6 typedef __SIZE_TYPE__ size_t;
8 void* memcpy (void*, const void*, size_t);
10 char* strcpy (char * restrict, const char * restrict);
11 int snprintf (char * restrict, size_t, const char *restrict, ...);
13 void sink (void*, ...);
15 #define CONCAT(x, y) x ## y
16 #define CAT(x, y) CONCAT (x, y)
17 #define FAILNAME(name, counter) \
18 CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
20 #define FAIL(name, counter) do { \
21 extern void FAILNAME (name, counter) (void); \
22 FAILNAME (name, counter)(); \
23 } while (0)
25 /* Macro to emit a call to funcation named
26 call_in_true_branch_not_eliminated_on_line_NNN()
27 for each call that's expected to be eliminated. The dg-final
28 scan-tree-dump-time directive at the bottom of the test verifies
29 that no such call appears in output. */
30 #define VERIFY_ELIM(expr) \
31 if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
33 /* Macro to emit a call to a function named
34 call_made_in_{true,false}_branch_on_line_NNN()
35 for each call that's expected to be retained. The dg-final
36 scan-tree-dump-time directive at the bottom of the test verifies
37 that the expected number of both kinds of calls appears in output
38 (a pair for each line with the invocation of the KEEP() macro. */
39 #define VERIFY_KEEP(expr) \
40 if (expr) \
41 FAIL (made_in_true_branch, __COUNTER__); \
42 else \
43 FAIL (made_in_false_branch, __COUNTER__)
45 #define ARGS(...) __VA_ARGS__
47 /* Each test macro expands to a new function to get around bug 81776
48 - missing sprintf optimization due to pointer escape analysis. */
49 #define ELIM(expect, dst, init, fmt, ...) \
50 void CAT (test_func_on_line_, __LINE__)(void) \
51 { \
52 memcpy (dst, init, sizeof (init) - 1); \
53 const int res = snprintf (0, 0, fmt, __VA_ARGS__); \
54 VERIFY_ELIM (expect res); \
55 } typedef void dummy_typedef
57 #define KEEP(expect, dst, init, fmt, ...) \
58 void CAT (test_func_on_line_, __LINE__)(void) \
59 { \
60 memcpy (dst, init, sizeof (init) - 1); \
61 const int ret = snprintf (0, 0, fmt, __VA_ARGS__); \
62 VERIFY_KEEP (expect ret); \
63 } typedef void dummy_typedef
66 /* Verify that conditions involving snprintf calls with a string
67 of some minimum but otherwise unbounded length stored in an array
68 of unknown bound are not folded unless the format string itself
69 restricts the maximum. The string could be longer than INT_MAX
70 making the snprintf call fail and return a negative value. */
72 extern char gax[];
74 KEEP (1 <=, gax, "1", "%s", gax);
75 KEEP (2 <=, gax, "12", "%s", gax);
76 KEEP (3 <=, gax, "123", "%s", gax);
78 ELIM (3 ==, gax, "123", "%.3s", gax);
79 ELIM (5 ==, gax, "123", "%.3s%.2s", gax, gax);
82 /* Disabled. The global pointer passed to memcpy as the destination
83 might point at itself, i.e., gptr == &gptr is a valid argument to
84 memcpy.
86 extern char *gptr;
88 KEEP (1 <=, gptr, "1", "%s", gptr);
89 KEEP (2 <=, gptr, "12", "%s", gptr);
90 KEEP (3 <=, gptr, "123", "%s", gptr);
92 ELIM (3 ==, gptr, "123", "%.3s", gptr);
93 ELIM (5 ==, gptr, "123", "%.3s%.2s", gptr, gptr);
97 /* Verify that conditions involving snprintf calls with a string
98 of some minimum but otherwise unbounded length stored in an array
99 of a known bound are folded. The longest string that can be
100 stored in such arrays is bounded by the size of the array. */
102 extern char ga4[4];
104 ELIM (0 <=, ga4, "\0", "%s", ga4);
105 ELIM (3 >=, ga4, "\0", "%s", ga4);
107 ELIM (1 <=, ga4, "1", "%s", ga4);
108 ELIM (0 <=, ga4, "1", "%s", ga4 + 1);
109 ELIM (0 <=, ga4, "1", "%s", &ga4[1]);
111 ELIM (3 >=, ga4, "1", "%s", ga4);
112 ELIM (2 >=, ga4, "1", "%s", ga4 + 1);
113 ELIM (2 >=, ga4, "1", "%s", &ga4[1]);
115 ELIM (2 <=, ga4, "12", "%s", ga4);
116 ELIM (3 >=, ga4, "12", "%s", ga4);
118 ELIM (3 <=, ga4, "123", "%s", ga4);
119 ELIM (3 ==, ga4, "123", "%.3s", ga4);
120 ELIM (5 ==, ga4, "123", "%.3s%.2s", ga4, ga4);
122 /* Verify conditionals involving dynamically created strings of known
123 length stored in local arrays. */
125 #undef ELIM
126 #define ELIM(expect, N1, N2, init1, init2, fmt, ...) \
127 void CAT (test_func_on_line_, __LINE__)(int i) \
129 char a1[N1], a2[N2]; \
130 memcpy (a1, init1, sizeof (init1) - 1); \
131 memcpy (a2, init2, sizeof (init2) - 1); \
132 const int res = snprintf (0, 0, fmt, __VA_ARGS__); \
133 VERIFY_ELIM (expect res); \
134 } typedef void dummy_typedef
136 ELIM (0 ==, 2, 2, "\0", "\0", "%s", i ? a1 : a2);
137 ELIM (2 ==, 2, 2, "\0", "\0", "s=%s", i ? a1 : a2);
139 ELIM (1 ==, 2, 2, "a\0", "b\0", "%s", i ? a1 : a2);
140 ELIM (3 ==, 2, 2, "a\0", "b\0", "s=%s", i ? a1 : a2);
142 ELIM (2 ==, 3, 5, "ab\0", "cd\0", "%s", i ? a1 : a2);
143 ELIM (3 ==, 3, 5, "ab\0", "cd\0", "%3s", i ? a1 : a2);
144 ELIM (3 ==, 5, 5, "abcd\0", "efgh\0", "%.3s", i ? a1 : a2);
146 ELIM (3 ==, 4, 1, "abc\0", "", "%s", i ? a1 : "def");
147 ELIM (4 ==, 1, 5, "", "efgh\0", "%s", i ? "abcd" : a2);
149 ELIM (4 ==, 5, 5, "abcd\0", "efgh\0", "%s", i < 0 ? a1 : 0 < i ? a2 : "ijkl");
151 /* { dg-final { scan-tree-dump-times "_not_eliminated" 0 "optimized" } }
152 { dg-final { scan-tree-dump-times "call_made_" 6 "optimized" } } */