blob: 67fce0375d8d4f645b08dd161bfbf1d3abc4553c [file] [log] [blame]
/* Test to exercise attribute "nonstring".
{ dg-do compile }
{ dg-options "-O2 -Wattributes -Wstringop-truncation -ftrack-macro-expansion=0" } */
#define ATTR(list) __attribute__ (list)
#define NONSTR ATTR ((nonstring))
#define strncpy(d, s, n) (__builtin_strncpy ((d), (s), (n)), sink (d))
void sink (void*);
/* Global string with an unknown bound. */
extern char gsx[];
/* Global string with an known bound. */
extern char gs3[3];
/* Global non-strings with an unknown bound. */
extern NONSTR char gax_1[];
extern char NONSTR gax_2[];
extern char gax_3[] NONSTR;
/* Global non-strings with a known bound. */
NONSTR char gns3[3];
char NONSTR gns4[4];
char gns5[5] NONSTR;
/* Global string pointer. */
extern char *ps_1;
/* Global non-string pointers. */
extern NONSTR char *pns_1;
extern char* NONSTR pns_2;
extern char *pns_3 NONSTR;
struct MemArrays
{
NONSTR char ma3[3];
char NONSTR ma4[4];
char ma5[5] NONSTR;
char max[] NONSTR;
};
void test_array (const char *s, unsigned n)
{
const char s7[] = "1234567";
strncpy (gs3, "", 0); /* { dg-warning "destination unchanged after copying no bytes" } */
strncpy (gs3, "a", 1); /* { dg-warning "output truncated before terminating nul copying 1 byte from a string of the same length" } */
strncpy (gs3, "a", 2);
strncpy (gs3, "a", 3);
strncpy (gs3, "ab", 3);
strncpy (gs3, "abc", 3); /* { dg-warning "output truncated before terminating nul copying 3 bytes from a string of the same length" } */
/* It might perhaps be helpful to diagnose certain truncation even
for non-strings. Then again, since the destination has been
explicitly annotated as non-string, it might be viewed as a false
positive. A valid use case seen in Glibc goes something like this:
#if FOO
# define S "1234"
#else
# define S "12345678"
#endif
strncpy (d, S, 8);
*/
strncpy (gax_3, s7, 3);
strncpy (gax_1, "a", 1);
strncpy (gax_2, "ab", 2);
strncpy (gax_3, "abc", 3);
strncpy (gax_3, s7, 3);
strncpy (gax_1, s, 1);
strncpy (gax_2, s, 1);
strncpy (gax_3, s, 1);
strncpy (gax_1, s, n);
strncpy (gax_2, s, n);
strncpy (gax_3, s, n);
}
void test_pointer (const char *s, unsigned n)
{
const char s7[] = "1234567";
strncpy (pns_1, "a", 1);
strncpy (pns_2, "ab", 2);
strncpy (pns_3, "abc", 3);
strncpy (pns_3, s7, 3);
strncpy (pns_1, s, 1);
strncpy (pns_2, s, 1);
strncpy (pns_3, s, 1);
strncpy (pns_1, s, n);
strncpy (pns_2, s, n);
strncpy (pns_3, s, n);
}
void test_member_array (struct MemArrays *p, const char *s, unsigned n)
{
const char s7[] = "1234567";
strncpy (p->ma3, "", 0);
strncpy (p->ma3, "a", 1);
strncpy (p->ma4, "ab", 2);
strncpy (p->ma5, "abc", 3);
strncpy (p->max, "abcd", 4);
strncpy (p->max, s7, 5);
strncpy (p->ma3, s, 1);
strncpy (p->ma4, s, 1);
strncpy (p->ma5, s, 1);
strncpy (p->max, s, 1);
strncpy (p->ma3, s7, n);
strncpy (p->ma4, s7, n);
strncpy (p->ma5, s7, n);
strncpy (p->max, s7, n);
}