1 /* Test to verify that snprintf can determine the length of a dynamically
2 constructed string argument and fold the result into a constant.
4 { dg-options "-O2 -Wall -fdump-tree-optimized" } */
6 typedef __SIZE_TYPE__
size_t;
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
, ...);
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)
18 #define FAIL(name, counter) do { \
19 extern void FAILNAME (name, counter) (void); \
20 FAILNAME (name, counter)(); \
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. */
29 if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
31 #define ARGS(...) __VA_ARGS__
33 #define T(expect, init, fmt, ...) \
36 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
39 /* Exercise a non-const local char array initialized by a string literal. */
40 void test_assign_string (void)
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]);
52 /* Exercise a non-const local char array initialized by an initializer
54 void test_assign_init_list (void)
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]);
70 /* Enabled only on x86_64 to work around PR 83543. */
73 #define T(expect, init, fmt, ...) \
75 struct { int n; char a[sizeof init]; } \
76 s = { sizeof init, init }; \
77 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
80 /* Exercise a non-const local struct initialized by an initializer
82 void test_assign_aggregate (void)
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]);
94 /* { dg-final { scan-tree-dump-times "Function test_assign_aggregate" 1 "optimized" { xfail { { ! x86_64-*-* } || { ilp32 } } } } } */
99 #define T(expect, init, fmt, ...) \
101 char a[sizeof init]; \
103 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
106 /* Exercise a local char array initialized by a call to strcpy. */
107 void test_local_strcpy (void)
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]);
122 #define T(expect, init, fmt, ...) \
126 ELIM (expect == snprintf (0, 0, fmt, __VA_ARGS__)); \
129 /* Exercise a VLA initialized by a call to strcpy. */
130 void test_vla_strcpy (unsigned n
)
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]);
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" } } */