PR middle-end/85602 - -Wsizeof-pointer-memaccess for strncat with size of source
[official-gcc.git] / gcc / testsuite / c-c++-common / attr-nonstring-8.c
blob15b68ed23a24cb77e456f8fa0b2b5e831432ce8d
1 /* PR middle-end/85602 - -Wsizeof-pointer-memaccess for strncat with size
2 of source
3 { dg-do compile }
4 { dg-options "-O2 -Wno-array-bounds -Wsizeof-pointer-memaccess -Wstringop-truncation -ftrack-macro-expansion=0" } */
6 #include "../gcc.dg/range.h"
8 typedef __SIZE_TYPE__ size_t;
10 #if __cplusplus
11 extern "C" {
12 #endif
14 char* strcpy (char*, const char*);
15 size_t strlen (const char*);
16 char* strncat (char*, const char*, __SIZE_TYPE__);
17 char* strncpy (char*, const char*, __SIZE_TYPE__);
19 #if __cplusplus
21 #endif
23 #define NONSTR __attribute__ ((nonstring))
25 NONSTR char nd3[3];
26 NONSTR char nd4[4];
27 NONSTR char nd5[5];
29 NONSTR char ns3[3];
30 NONSTR char ns4[4];
31 NONSTR char ns5[5];
33 NONSTR char* pns;
35 void sink (void*, ...);
37 #define T(call) sink (call)
39 /* Verify that for a nonstring source array of an unknown length
40 a warning is issued only when the bound exceeds the array size. */
42 void test_strncat_nonstring_cst (char *d)
44 T (strncat (d, ns3, 1));
45 T (strncat (d, ns3, 2));
46 T (strncat (d, ns3, 3));
47 T (strncat (d, ns3, sizeof ns3));
48 T (strncat (d, ns3, 4)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 4" } */
50 T (strncat (d, ns4, 1));
51 T (strncat (d, ns4, 2));
52 T (strncat (d, ns4, 3));
53 T (strncat (d, ns4, 4));
54 T (strncat (d, ns4, sizeof ns4));
55 T (strncat (d, ns4, 5)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
57 T (strncat (nd3, ns3, 1));
58 T (strncat (nd3, ns3, 2));
59 T (strncat (nd3, ns3, 3)); /* { dg-warning "specified bound 3 equals destination size" } */
60 T (strncat (nd3, ns3, 4)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 4" } */
61 /* { dg-warning "specified bound 4 exceeds destination size 3" "" { target *-*-* } .-1 } */
63 T (strncat (d, pns, sizeof pns)); /* { dg-warning "argument to .sizeof. in .strncat. call is the same expression as the source" } */
67 void test_strncat_nonstring_var (char *d, size_t n)
69 /* In the following the bound coulld apply to either the destination
70 or the source. The expected use of strncat() is to pass it as
71 the bound DSIZE - strlen(D) - 1 so the call below is diagnosed. */
72 T (strncat (d, ns3, n)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
74 T (strncat (d, ns3, UR (0, 1)));
75 T (strncat (d, ns3, UR (1, 2)));
76 T (strncat (d, ns3, UR (2, 3)));
77 T (strncat (d, ns3, UR (3, 4))); /* { dg-warning "argument 2 declared attribute 'nonstring' may be smaller than the specified bound \\\[3, 4]" } */
78 T (strncat (d, ns3, UR (4, 5))); /* { dg-warning "argument 2 declared attribute 'nonstring' is smaller than the specified bound \\\[4, 5]" } */
80 /* Verify that the call below (the intended use of strncat()) is
81 also diagnosed. */
82 T (strncat (d, ns3, 256 - strlen (d) - 1)); /* { dg-warning "argument 2 declared attribute .nonstring." } */
84 T (strncat (nd3, ns5, UR (0, 1)));
85 T (strncat (nd3, ns5, UR (1, 2)));
86 T (strncat (nd3, ns5, UR (2, 3)));
87 T (strncat (nd3, ns5, UR (3, 4)));
88 T (strncat (nd3, ns5, UR (4, 5))); /* { dg-warning "specified bound between 4 and 5 exceeds destination size 3" } */
90 T (strncat (nd5, ns3, UR (0, 1)));
91 T (strncat (nd5, ns3, UR (1, 2)));
92 T (strncat (nd5, ns3, UR (2, 3)));
93 T (strncat (nd5, ns3, UR (3, 4))); /* { dg-warning "argument 2 declared attribute 'nonstring' may be smaller than the specified bound \\\[3, 4]" } */
96 /* Verify that for a nonstring source array of a known length (i.e.,
97 a nonstring array containing a nul-terminated string) a warning
98 is issued only for certain truncation.
100 The test cases are split up to work around bug 81343 (or one like
101 it). */
103 void test_strncat_string_1_1 (char *d)
105 strcpy (ns3, "1");
106 T (strncat (d, ns3, 1)); /* { dg-warning "output truncated before terminating nul copying 1 byte from a string of the same length" } */
109 void test_strncat_string_1_2 (char *d)
111 strcpy (ns3, "1");
112 T (strncat (d, ns3, 2));
115 void test_strncat_string_1_3 (char *d)
117 strcpy (ns3, "1");
118 T (strncat (d, ns3, 3));
121 void test_strncat_string_2_1 (char *d)
123 strcpy (ns3, "12");
124 T (strncat (d, ns3, 1)); /* { dg-warning "output truncated copying 1 byte from a string of length 2" } */
127 void test_strncat_string_2_2 (char *d)
129 strcpy (ns3, "12");
130 T (strncat (d, ns3, 2)); /* { dg-warning "output truncated before terminating nul copying 2 bytes from a string of the same length" } */
133 void test_strncat_string_2_3 (char *d)
135 strcpy (ns3, "12");
136 T (strncat (d, ns3, 3));
140 void test_strcncpy_nonstring_cst (char *d)
142 T (strncpy (d, ns3, 1));
143 T (strncpy (d, ns3, 2));
144 T (strncpy (d, ns3, 3));
145 T (strncpy (d, ns3, sizeof ns3));
146 T (strncpy (d, ns3, 4)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 4" } */