diff options
Diffstat (limited to 'gcc/testsuite/c-c++-common/attr-nonstring-2.c')
-rw-r--r-- | gcc/testsuite/c-c++-common/attr-nonstring-2.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-2.c b/gcc/testsuite/c-c++-common/attr-nonstring-2.c new file mode 100644 index 00000000000..6e273e785a0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/attr-nonstring-2.c @@ -0,0 +1,123 @@ +/* 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); /* { dg-warning "output truncated copying 3 bytes from a string of length 7" } */ + + 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, "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); +} |