summaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common/attr-nonstring-2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/c-c++-common/attr-nonstring-2.c')
-rw-r--r--gcc/testsuite/c-c++-common/attr-nonstring-2.c123
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);
+}