Attribute nonstring is currently only allowed on arrays and pointers to plain char, but -Wstringop-truncation triggers even for strncpy calls whose arguments are arrays of signed or unsigned char (with or without a cast to char*).
To help deal with -Wstringop-truncation in the Linux kernel it was suggested to me that it would be useful to be able to make use of the attribute on all three narrow char types. Apparently, there are enough calls to strncpy in the Linux kernel with arguments of the other char types that trigger the new warning, and the warning is considered sufficiently useful that making use of the attribute to suppress the warning rather than changing it ignore the other two char types is preferable. The attached patch relaxes the restriction and lets GCC accept attribute nonstring on all three narrow character types as well as their qualified forms. Tested on x86_64-linux. Martin
PR tree-optimization/84725 - enable attribute nonstring for all narrow character types gcc/c-family/ChangeLog: PR tree-optimization/84725 * c-attribs.c (handle_nonstring_attribute): Allow attribute nonstring with all three narrow character types, including their qualified forms. gcc/testsuite/ChangeLog: PR tree-optimization/84725 * c-c++-common/Wstringop-truncation-4.c: New test. * c-c++-common/attr-nonstring-5.c: New test. Index: gcc/c-family/c-attribs.c =================================================================== --- gcc/c-family/c-attribs.c (revision 258259) +++ gcc/c-family/c-attribs.c (working copy) @@ -3194,8 +3194,13 @@ handle_nonstring_attribute (tree *node, tree name, 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; } Index: gcc/testsuite/c-c++-common/Wstringop-truncation-4.c =================================================================== --- gcc/testsuite/c-c++-common/Wstringop-truncation-4.c (nonexistent) +++ gcc/testsuite/c-c++-common/Wstringop-truncation-4.c (working copy) @@ -0,0 +1,125 @@ +/* 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 "-O -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); + strncpy ((char*)p->b, s, sizeof p->b); + strncpy ((char*)p->c, s, sizeof p->c); +} + +struct Pointers +{ + char *p; + signed char *q; + unsigned char *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 a[4]; + const signed char b[4]; + const unsigned char c[4]; +}; + +void test_const_arrays (struct ConstArrays *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 ConstPointers +{ + const char *p; + const signed char *q; + const unsigned char *r; +}; + +void test_const_pointers (struct ConstPointers *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 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 (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 (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 (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 (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" } */ +} Index: gcc/testsuite/c-c++-common/attr-nonstring-5.c =================================================================== --- gcc/testsuite/c-c++-common/attr-nonstring-5.c (nonexistent) +++ gcc/testsuite/c-c++-common/attr-nonstring-5.c (working copy) @@ -0,0 +1,131 @@ +/* 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" } */