1 /* Verify that
2    { dg-do compile }
3    { dg-options "-O2 -Wstringop-truncation -Wno-stringop-overflow -ftrack-macro-expansion=0" } */
4 
5 typedef __SIZE_TYPE__ size_t;
6 
7 #define stpncpy(d, s, n) __builtin_stpncpy ((d), (s), (n))
8 #define strncpy(d, s, n) __builtin_stpncpy ((d), (s), (n))
9 
10 void sink (void*);
11 
12 struct A {
13   char arr[3] __attribute__ ((nonstring));
14   char str[3];
15 };
16 
17 struct B { struct A a[3]; int i; };
18 struct C { struct B b[3]; int i; };
19 
stpncpy_arr_1(struct C * pc,const char * s)20 void stpncpy_arr_1 (struct C *pc, const char *s)
21 {
22   stpncpy (pc->b[0].a[0].arr, s, sizeof pc->b[0].a[0].arr);
23   sink (pc->b[0].a[0].arr);
24 
25   stpncpy (pc->b[0].a[1].arr, s, sizeof pc->b[0].a[1].arr);
26   sink (pc->b[0].a[1].arr);
27 
28   stpncpy (pc->b[0].a[2].arr, s, sizeof pc->b[0].a[2].arr);
29   sink (pc->b[0].a[2].arr);
30 
31   stpncpy (pc->b[1].a[0].arr, s, sizeof pc->b[1].a[0].arr);
32   sink (pc->b[1].a[0].arr);
33 
34   stpncpy (pc->b[1].a[1].arr, s, sizeof pc->b[1].a[1].arr);
35   sink (pc->b[1].a[1].arr);
36 
37   stpncpy (pc->b[1].a[2].arr, s, sizeof pc->b[1].a[2].arr);
38   sink (pc->b[1].a[2].arr);
39 
40   stpncpy (pc->b[2].a[0].arr, s, sizeof pc->b[2].a[0].arr);
41   sink (pc->b[2].a[0].arr);
42 
43   stpncpy (pc->b[2].a[1].arr, s, sizeof pc->b[2].a[1].arr);
44   sink (pc->b[2].a[1].arr);
45 
46   stpncpy (pc->b[2].a[2].arr, s, sizeof pc->b[2].a[2].arr);
47   sink (pc->b[2].a[2].arr);
48 }
49 
stpncpy_str_nowarn_1(struct C * pc,const char * s)50 void stpncpy_str_nowarn_1 (struct C *pc, const char *s)
51 {
52   stpncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str)[-1] = 0;   /* { dg-bogus "\\\[-Wstringop-truncation" } */
53 }
54 
stpncpy_str_nowarn_2(struct C * pc,const char * s)55 void stpncpy_str_nowarn_2 (struct C *pc, const char *s)
56 {
57   *stpncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str - 1) = 0;   /* { dg-bogus "\\\[-Wstringop-truncation" } */
58 }
59 
stpncpy_str_nowarn_3(struct C * pc,const char * s)60 void stpncpy_str_nowarn_3 (struct C *pc, const char *s)
61 {
62   char *d = stpncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str);   /* { dg-bogus "\\\[-Wstringop-truncation" } */
63 
64   d[-1] = 0;
65 }
66 
stpncpy_str_nowarn_4(struct C * pc,const char * s)67 void stpncpy_str_nowarn_4 (struct C *pc, const char *s)
68 {
69   char *d = stpncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str - 1);   /* { dg-bogus "\\\[-Wstringop-truncation" } */
70 
71   *d = 0;
72 }
73 
strncpy_arr_1(struct C * pc,const char * s)74 void strncpy_arr_1 (struct C *pc, const char *s)
75 {
76   strncpy (pc->b[0].a[0].arr, s, sizeof pc->b[0].a[0].arr);
77   sink (pc->b[0].a[0].arr);
78 
79   strncpy (pc->b[0].a[1].arr, s, sizeof pc->b[0].a[1].arr);
80   sink (pc->b[0].a[1].arr);
81 
82   strncpy (pc->b[0].a[2].arr, s, sizeof pc->b[0].a[2].arr);
83   sink (pc->b[0].a[2].arr);
84 }
85 
strncpy_str_nowarn_1(struct C * pc,const char * s)86 void strncpy_str_nowarn_1 (struct C *pc, const char *s)
87 {
88   strncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str);   /* { dg-bogus "\\\[-Wstringop-truncation" } */
89 
90   pc->b[0].a[0].str[sizeof pc->b[0].a[0].str - 1] = 0;
91 }
92 
strncpy_str_warn_1(struct C * pc,const char * s)93 void strncpy_str_warn_1 (struct C *pc, const char *s)
94 {
95   strncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str);   /* { dg-warning "specified bound 3 equals destination size" } */
96 
97   pc->b[1].a[0].str[sizeof pc->b[0].a[0].str - 1] = 0;
98 }
99 
strncpy_str_warn_2(struct C * pc,const char * s)100 void strncpy_str_warn_2 (struct C *pc, const char *s)
101 {
102   strncpy (pc->b[0].a[0].str, s, sizeof pc->b[0].a[0].str);   /* { dg-warning "specified bound 3 equals destination size" } */
103 
104   pc->b[0].a[1].str[sizeof pc->b[0].a[0].str - 1] = 0;
105 }
106