1 /* { dg-do compile } */
2 /* { dg-options "-O2 -Wformat -Wformat-truncation=2 -ftrack-macro-expansion=0" } */
3 
4 typedef struct
5 {
6   char a0[0];
7   /* Separate a0 from a1 to prevent the former from being substituted
8      for the latter and causing false positives.  */
9   int: 8;
10   char a1[1];
11   char a2[2];
12   char a3[3];
13   char a4[4];
14   char ax[];
15 } Arrays;
16 
17 char buffer[1024];
18 #define buffer(size) (buffer + sizeof buffer - size)
19 
value_range(int min,int max)20 static int value_range (int min, int max)
21 {
22   extern int value (void);
23   int val = value ();
24   return val < min || max < val ? min : val;
25 }
26 
27 #define R(min, max)  value_range (min, max)
28 
29 /* Verify that calls to snprintf whose return value is unused are
30    diagnosed if certain or possible truncation is detected.  */
31 
32 #define T(size, ...) \
33   __builtin_snprintf (buffer (size), size, __VA_ARGS__)
34 
test_int_retval_unused(void)35 void test_int_retval_unused (void)
36 {
37   T (2, "%i", 123);          /* { dg-warning "output truncated" } */
38   T (2, "%i", R (1, 99));    /* { dg-warning "output may be truncated" } */
39   T (2, "%i", R (10, 99));   /* { dg-warning "output truncated" } */
40   T (3, "%i%i", R (1, 99), R (1, 99));   /* { dg-warning "output may be truncated" } */
41 }
42 
test_string_retval_unused(const Arrays * ar)43 void test_string_retval_unused (const Arrays *ar)
44 {
45   /* At level 2 strings of unknown length are assumed to be 1 character
46      long, so the following is diagnosed.  */
47   T (1, "%-s", ar->a0);   /* { dg-warning "output may be truncated" } */
48   T (1, "%-s", ar->a1);
49   T (1, "%-s", ar->a2);   /* { dg-warning "output may be truncated" } */
50 }
51 
52 
53 /* Verify that (at -Wformat-trunc=2) calls to snprintf whose return value
54    is used are diagnosed the same way as those whose value is unused.  */
55 
56 volatile int retval;
57 
58 #undef T
59 #define T(size, ...) \
60   retval = __builtin_snprintf (buffer (size), size, __VA_ARGS__)
61 
test_int_retval_used(void)62 void test_int_retval_used (void)
63 {
64   T (2, "%i", 123);          /* { dg-warning "output truncated" } */
65   T (2, "%i", R (1, 99));    /* { dg-warning "output may be truncated" } */
66   T (2, "%i", R (10, 99));   /* { dg-warning "output truncated" } */
67   T (3, "%i%i", R (1, 99), R (1, 99));   /* { dg-warning "output may be truncated" } */
68 }
69 
test_string_retval_used(const Arrays * ar)70 void test_string_retval_used (const Arrays *ar)
71 {
72   T (1, "%-s", ar->a0);   /* { dg-warning "output may be truncated" } */
73   T (1, "%-s", ar->a1);
74   T (1, "%-s", ar->a2);   /* { dg-warning "output may be truncated" } */
75 }
76