gimple-ssa-warn-access: Adjust maybe_warn_nonstring_arg for nonstring multidimensional arrays [PR117178]

The following patch fixes 4 xfails in attr-nonstring-11.c (and results in 2
false positive warnings in attr-nonstring-12.c not being produced either).
The thing is that maybe_warn_nonstring_arg simply assumed that nonstring
arrays must be single-dimensional, so when it sees a nonstring decl with
ARRAY_TYPE, it just used its dimension.  With multi-dimensional arrays
that is not the right dimension to use though, it can be dimension of
some outer dimension, e.g. if we have
char a[5][6][7] __attribute__((nonstring)) if decl is
a[5] it would assume maximum non-NUL terminated string length of 5 rather than
7, if a[5][6] it would assume 6 and only for a[5][6][0] it would assume the
correct 7.  So, the following patch looks through all the outer dimensions
to reach the innermost one (which for attribute nonstring is guaranteed to
have char/unsigned char/signed char element type).

2025-03-10  Jakub Jelinek  <jakub@redhat.com>

	PR c/117178
	* gimple-ssa-warn-access.cc (maybe_warn_nonstring_arg): Look through
	multi-dimensional array types, stop at the innermost ARRAY_TYPE.

	* c-c++-common/attr-nonstring-11.c: Remove xfails.
	* c-c++-common/attr-nonstring-12.c (warn_strcmp_cst_1,
	warn_strcmp_cst_2): Don't expect any warnings here.
	(warn_strcmp_cst_3, warn_strcmp_cst_4): New functions with expected
	warnings.
This commit is contained in:
Jakub Jelinek 2025-03-10 09:31:41 +01:00 committed by Jakub Jelinek
parent 62a6a53766
commit 1301e18f69
3 changed files with 20 additions and 6 deletions

View file

@ -602,6 +602,10 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
bool known_size = false;
tree type = TREE_TYPE (decl);
while (TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
type = TREE_TYPE (type);
/* Determine the array size. For arrays of unknown bound and
pointers reset BOUND to trigger the appropriate warning. */
if (TREE_CODE (type) == ARRAY_TYPE)

View file

@ -165,8 +165,8 @@ void test_strcmp (struct MemArrays *p)
void test_strncmp_warn (struct MemArrays *p)
{
enum { N = sizeof arr[2] };
T (strncmp (str[2], arr[2], N)); /* { dg-bogus "argument 2 declared attribute 'nonstring' is smaller than the specified bound 4" "" { xfail *-*-* } } */
T (strncmp (arr[2], str[2], N)); /* { dg-bogus "argument 1 declared attribute 'nonstring' is smaller than the specified bound 4" "" { xfail *-*-* } } */
T (strncmp (str[2], arr[2], N));
T (strncmp (arr[2], str[2], N));
T (strncmp (str[2], arr[2], N + 1)); /* { dg-warning "argument 2 declared attribute .nonstring. is smaller than the specified bound 5" } */
T (strncmp (arr[2], str[2], N + 1)); /* { dg-warning "argument 1 declared attribute .nonstring. is smaller than the specified bound 5" } */
@ -237,7 +237,7 @@ void test_stpncpy_warn (struct MemArrays *p, unsigned n)
enum { N = sizeof arr[2] };
T (stpncpy (str[2], str[2], N));
T (stpncpy (str[2], arr[2], N)); /* { dg-bogus "argument 2 declared attribute 'nonstring' is smaller than the specified bound 4" "" { xfail *-*-* } } */
T (stpncpy (str[2], arr[2], N));
T (stpncpy (arr[2], str[2], N));
T (stpncpy (str[2], *ptr, N));
@ -370,7 +370,7 @@ void test_stnrdup_warn (struct MemArrays *p)
enum { N = sizeof arr[2] };
T (strndup (str[2], N));
T (strndup (arr[2], N)); /* { dg-bogus "argument 1 declared attribute 'nonstring' is smaller than the specified bound 4" "" { xfail *-*-* } } */
T (strndup (arr[2], N));
T (strndup (*ptr, N));
T (strndup (*parr, N));

View file

@ -26,12 +26,22 @@ enum { X = sizeof ar5[2] + 1 };
int warn_strcmp_cst_1 (void)
{
return strcmp ("bar", arx[3]); /* { dg-warning "argument 2 declared attribute .nonstring." } */
return strcmp ("bar", arx[3]);
}
int warn_strcmp_cst_2 (void)
{
return strcmp (arx[3], "foo"); /* { dg-warning "argument 1 declared attribute .nonstring." } */
return strcmp (arx[3], "foo");
}
int warn_strcmp_cst_3 (void)
{
return strcmp ("barfoobazquxcorge1", arx[3]); /* { dg-warning "argument 2 declared attribute .nonstring." } */
}
int warn_strcmp_cst_4 (void)
{
return strcmp (arx[3], "foobarbazquxcorge1"); /* { dg-warning "argument 1 declared attribute .nonstring." } */
}