1 /* PR tree-optimization/84468 - Inconsistent -Wstringop-truncation warnings
2    with -O2
3    { dg-do compile }
4    { dg-options "-O2 -Wstringop-truncation -ftrack-macro-expansion=0 -g" }  */
5 
6 #define strncpy __builtin_strncpy
7 
8 struct A
9 {
10   char a[4];
11 };
12 
no_pred_succ_lit(struct A * p)13 void no_pred_succ_lit (struct A *p)
14 {
15   /* The following is folded early on, before the strncpy statement
16      has a basic block.  Verify that the case is handled gracefully
17      (i.e., there's no assumption that the statement does have
18      a basic block).  */
19   strncpy (p->a, "1234", sizeof p->a - 1);    /* { dg-warning "\\\[-Wstringop-truncation" } */
20 }
21 
22 /* Verify a strncpy call in a basic block with no predecessor or
23    successor.  */
no_pred_succ(struct A * p,const struct A * q)24 void no_pred_succ (struct A *p, const struct A *q)
25 {
26   strncpy (p->a, q->a, sizeof p->a - 1);      /* { dg-warning "\\\[-Wstringop-truncation" } */
27 }
28 
29 
30 /* Verify a strncpy call in a basic block with no successor.  */
no_succ(struct A * p,const struct A * q)31 void no_succ (struct A *p, const struct A *q)
32 {
33   if (q->a)
34     strncpy (p->a, q->a, sizeof p->a - 1);    /* { dg-warning "\\\[-Wstringop-truncation" } */
35 }
36 
37 /* Verify a strncpy call in a basic block with nul assignment in
38    a successor block.  */
succ(struct A * p,const struct A * q)39 void succ (struct A *p, const struct A *q)
40 {
41   /* Verify that the assignment suppresses the warning for the conditional
42      strcnpy call.  The conditional should be folded to true since the
43      address of an array can never be null (see bug 84470).  */
44   if (q->a)
45     strncpy (p->a, q->a, sizeof p->a - 1);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
46 
47   p->a[sizeof p->a - 1] = 0;
48 }
49 
50 
succ_2(struct A * p,const struct A * q,int i)51 void succ_2 (struct A *p, const struct A *q, int i)
52 {
53   /* Same as above but with a conditional that cannot be eliminated.  */
54   if (i < 0)
55     strncpy (p->a, q->a, sizeof p->a - 1);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
56 
57   p->a[sizeof p->a - 1] = 0;
58 }
59 
60 
61 /* Verify a strncpy call in a basic block with nul assignment in
62    the next successor block.  */
next_succ(struct A * p,const struct A * q,int i,int j)63 int next_succ (struct A *p, const struct A *q, int i, int j)
64 {
65   /* Same as above but with a nested conditionals with else clauses.  */
66   if (i < 0)
67     {
68       if (j < 0)
69 	strncpy (p->a, q->a, sizeof p->a - 1);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
70     }
71   else
72     __builtin_strcpy (p->a, q->a);
73 
74   p->a[sizeof p->a - 1] = 0;
75   return 0;
76 }
77 
78 
next_succ_1(struct A * p,const struct A * q,int i,int j)79 int next_succ_1 (struct A *p, const struct A *q, int i, int j)
80 {
81   /* Same as above but with a nested conditionals with else clauses.  */
82   if (i < 0)
83     {
84       if (j < 0)
85 	strncpy (p->a, q->a, sizeof p->a - 1);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
86       else
87 	strncpy (p->a, q->a, sizeof p->a - 2);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
88     }
89 
90   p->a[sizeof p->a - 2] = 0;
91   return 1;
92 }
93 
94 
next_succ_2(struct A * p,const struct A * q,int i,int j)95 int next_succ_2 (struct A *p, const struct A *q, int i, int j)
96 {
97   /* Same as above but with a nested conditionals with else clauses.  */
98   if (i < 0)
99     {
100       if (j < 0)
101 	strncpy (p->a, q->a, sizeof p->a - 1);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
102       else
103 	strncpy (p->a, q->a, sizeof p->a - 2);    /* { dg-bogus "\\\[-Wstringop-truncation" } */
104     }
105   else
106     __builtin_strcpy (p->a, q->a);
107 
108   p->a[sizeof p->a - 2] = 0;
109   return 2;
110 }
111 
112 
cond_succ_warn(struct A * p,const struct A * q,int i)113 void cond_succ_warn (struct A *p, const struct A *q, int i)
114 {
115   /* Verify that a conditional assignment doesn't suppress the warning.  */
116   strncpy (p->a, q->a, sizeof p->a - 1);      /* { dg-warning "\\\[-Wstringop-truncation" } */
117 
118   if (i < 0)
119     p->a[sizeof p->a - 1] = 0;
120 }
121 
cond_succ_nowarn(struct A * p,const struct A * q)122 void cond_succ_nowarn (struct A *p, const struct A *q)
123 {
124   /* Verify that distinct but provably equivalent conditionals are
125      recognized and don't trigger the warning.  */
126   if (p != q)
127     strncpy (p->a, q->a, sizeof p->a - 1);
128 
129   if (p->a != q->a)
130     p->a[sizeof p->a - 1] = 0;
131 }
132