+2018-03-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/84725
+ * c-attribs.c (handle_nonstring_attribute): Allow attribute nonstring
+ with all three narrow character types, including their qualified forms.
+
2018-03-12 Martin Sebor <msebor@redhat.com>
PR tree-optimization/83456
if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
{
+ /* Accept the attribute on arrays and pointers to all three
+ narrow character types. */
tree eltype = TREE_TYPE (type);
- if (eltype == char_type_node)
+ eltype = TYPE_MAIN_VARIANT (eltype);
+ if (eltype == char_type_node
+ || eltype == signed_char_type_node
+ || eltype == unsigned_char_type_node)
return NULL_TREE;
}
@item nonstring
@cindex @code{nonstring} variable attribute
The @code{nonstring} variable attribute specifies that an object or member
-declaration with type array of @code{char} or pointer to @code{char} is
-intended to store character arrays that do not necessarily contain
-a terminating @code{NUL} character. This is useful in detecting uses
-of such arrays or pointers with functions that expect NUL-terminated
-strings, and to avoid warnings when such an array or pointer is used
-as an argument to a bounded string manipulation function such as
-@code{strncpy}. For example, without the attribute, GCC will issue
-a warning for the @code{strncpy} call below because it may truncate
-the copy without appending the terminating @code{NUL} character. Using
-the attribute makes it possible to suppress the warning. However, when
-the array is declared with the attribute the call to @code{strlen} is
+declaration with type array of @code{char}, @code{signed char}, or
+@code{unsigned char}, or pointer to such a type is intended to store
+character arrays that do not necessarily contain a terminating @code{NUL}.
+This is useful in detecting uses of such arrays or pointers with functions
+that expect @code{NUL}-terminated strings, and to avoid warnings when such
+an array or pointer is used as an argument to a bounded string manipulation
+function such as @code{strncpy}. For example, without the attribute, GCC
+will issue a warning for the @code{strncpy} call below because it may
+truncate the copy without appending the terminating @code{NUL} character.
+Using the attribute makes it possible to suppress the warning. However,
+when the array is declared with the attribute the call to @code{strlen} is
diagnosed because when the array doesn't contain a @code{NUL}-terminated
string the call is undefined. To copy, compare, of search non-string
character arrays use the @code{memcpy}, @code{memcmp}, @code{memchr},
+2018-03-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/84725
+ * c-c++-common/Wstringop-truncation-4.c: New test.
+ * c-c++-common/attr-nonstring-5.c: New test.
+
2018-03-13 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.target/aarch64/sve/unpack_fcvt_signed_1.c: Expect zips rather
--- /dev/null
+/* PR middle-end/84725 - enable attribute nonstring for all narrow character
+ types
+ Verify that -Wstringop-truncation is issued for uses of arrays and
+ pointers to qualified forms of characters of all three types.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wstringop-truncation" } */
+
+#if __cplusplus
+extern "C"
+#endif
+char* strncpy (char*, const char*, __SIZE_TYPE__);
+
+#define S "1234"
+
+struct Arrays
+{
+ char a[4];
+ signed char b[4];
+ unsigned char c[4];
+};
+
+void test_arrays (struct Arrays *p, const char *s)
+{
+ strncpy (p->a, s, sizeof p->a); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->b, s, sizeof p->b); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->c, s, sizeof p->c); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct Pointers
+{
+ char *p;
+ signed char *q;
+ unsigned char *r;
+};
+
+void test_pointers (struct Pointers *p)
+{
+ strncpy (p->p, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->q, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->r, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct ConstArrays
+{
+ const char a[4];
+ const signed char b[4];
+ const unsigned char c[4];
+};
+
+void test_const_arrays (struct ConstArrays *p, const char *s)
+{
+ strncpy ((char*)p->a, s, sizeof p->a); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->b, s, sizeof p->b); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->c, s, sizeof p->c); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct ConstPointers
+{
+ const char *p;
+ const signed char *q;
+ const unsigned char *r;
+};
+
+void test_const_pointers (struct ConstPointers *p)
+{
+ strncpy ((char*)p->p, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->q, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->r, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct VolatileArrays
+{
+ volatile char a[4];
+ volatile signed char b[4];
+ volatile unsigned char c[4];
+};
+
+void test_volatile_arrays (struct VolatileArrays *p, const char *s)
+{
+ strncpy ((char*)p->a, s, sizeof p->a); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->b, s, sizeof p->b); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->c, s, sizeof p->c); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct VolatilePointers
+{
+ volatile char *p;
+ volatile signed char *q;
+ volatile unsigned char *r;
+};
+
+void test_volatile_pointers (struct VolatilePointers *p)
+{
+ strncpy ((char*)p->p, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->q, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->r, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct ConstVolatileArrays
+{
+ const volatile char a[4];
+ const volatile signed char b[4];
+ const volatile unsigned char c[4];
+};
+
+void test_const_volatile_arrays (struct ConstVolatileArrays *p, const char *s)
+{
+ strncpy ((char*)p->a, s, sizeof p->a); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->b, s, sizeof p->b); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->c, s, sizeof p->c); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+struct ConstVolatilePointers
+{
+ const volatile char *p;
+ const volatile signed char *q;
+ const volatile unsigned char *r;
+};
+
+void test_const_volatile_pointers (struct ConstVolatilePointers *p)
+{
+ strncpy ((char*)p->p, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->q, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+ strncpy ((char*)p->r, S, sizeof S - 1); /* { dg-warning "\\\[-Wstringop-truncation" } */
+}
+
+/* { dg-prune-output "-Wdiscarded-qualifiers" } */
--- /dev/null
+/* PR middle-end/84725 - enable attribute nonstring for all narrow character
+ types
+ Verify that using attribute nonstring with all three narrow character
+ types is accepted and using arrays and pointers to characters of all
+ three types (including their qualified forms) declared with the
+ attributes doesn't trigger -Wstringop-truncation warnings.
+ { dg-do compile }
+ { dg-options "-O -Wall -Wstringop-truncation" } */
+
+#if __cplusplus
+extern "C"
+#endif
+char* strncpy (char*, const char*, __SIZE_TYPE__);
+
+#define NONSTR __attribute__ ((nonstring))
+
+#define S "1234"
+
+struct Arrays
+{
+ char NONSTR a[4];
+ signed char NONSTR b[4];
+ unsigned char NONSTR c[4];
+};
+
+void test_arrays (struct Arrays *p, const char *s)
+{
+ strncpy (p->a, s, sizeof p->a);
+ strncpy ((char*)p->b, s, sizeof p->b);
+ strncpy ((char*)p->c, s, sizeof p->c);
+}
+
+struct Pointers
+{
+ char NONSTR *p;
+ signed char NONSTR *q;
+ unsigned char NONSTR *r;
+};
+
+void test_pointers (struct Pointers *p)
+{
+ strncpy (p->p, S, sizeof S - 1);
+ strncpy ((char*)p->q, S, sizeof S - 1);
+ strncpy ((char*)p->r, S, sizeof S - 1);
+}
+
+struct ConstArrays
+{
+ const char NONSTR a[4];
+ const signed char NONSTR b[4];
+ const unsigned char NONSTR c[4];
+};
+
+void test_const_arrays (struct ConstArrays *p, const char *s)
+{
+ strncpy ((char*)p->a, s, sizeof p->a);
+ strncpy ((char*)p->b, s, sizeof p->b);
+ strncpy ((char*)p->c, s, sizeof p->c);
+}
+
+struct ConstPointers
+{
+ const char NONSTR *p;
+ const signed char NONSTR *q;
+ const unsigned char NONSTR *r;
+};
+
+void test_const_pointers (struct ConstPointers *p)
+{
+ strncpy ((char*)p->p, S, sizeof S - 1);
+ strncpy ((char*)p->q, S, sizeof S - 1);
+ strncpy ((char*)p->r, S, sizeof S - 1);
+}
+
+struct VolatileArrays
+{
+ volatile char NONSTR a[4];
+ volatile signed char NONSTR b[4];
+ volatile unsigned char NONSTR c[4];
+};
+
+void test_volatile_arrays (struct VolatileArrays *p, const char *s)
+{
+ strncpy ((char*)p->a, s, sizeof p->a);
+ strncpy ((char*)p->b, s, sizeof p->b);
+ strncpy ((char*)p->c, s, sizeof p->c);
+}
+
+struct VolatilePointers
+{
+ volatile char NONSTR *p;
+ volatile signed char NONSTR *q;
+ volatile unsigned char NONSTR *r;
+};
+
+void test_volatile_pointers (struct VolatilePointers *p)
+{
+ strncpy ((char*)p->p, S, sizeof S - 1);
+ strncpy ((char*)p->q, S, sizeof S - 1);
+ strncpy ((char*)p->r, S, sizeof S - 1);
+}
+
+struct ConstVolatileArrays
+{
+ const volatile char NONSTR a[4];
+ const volatile signed char NONSTR b[4];
+ const volatile unsigned char NONSTR c[4];
+};
+
+void test_const_volatile_arrays (struct ConstVolatileArrays *p, const char *s)
+{
+ strncpy ((char*)p->a, s, sizeof p->a);
+ strncpy ((char*)p->b, s, sizeof p->b);
+ strncpy ((char*)p->c, s, sizeof p->c);
+}
+
+struct ConstVolatilePointers
+{
+ const volatile char NONSTR *p;
+ const volatile signed char NONSTR *q;
+ const volatile unsigned char NONSTR *r;
+};
+
+void test_const_volatile_pointers (struct ConstVolatilePointers *p)
+{
+ strncpy ((char*)p->p, S, sizeof S - 1);
+ strncpy ((char*)p->q, S, sizeof S - 1);
+ strncpy ((char*)p->r, S, sizeof S - 1);
+}
+
+/* { dg-prune-output "-Wdiscarded-qualifiers" } */