From 1301e18f69ced6a14a7648a24d1eb3addd836b6c Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 10 Mar 2025 09:31:41 +0100 Subject: 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 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. --- gcc/gimple-ssa-warn-access.cc | 4 ++++ gcc/testsuite/c-c++-common/attr-nonstring-11.c | 8 ++++---- gcc/testsuite/c-c++-common/attr-nonstring-12.c | 14 ++++++++++++-- 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'gcc') diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 351f487..305b6356 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -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) diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-11.c b/gcc/testsuite/c-c++-common/attr-nonstring-11.c index 12fbc90..745e993 100644 --- a/gcc/testsuite/c-c++-common/attr-nonstring-11.c +++ b/gcc/testsuite/c-c++-common/attr-nonstring-11.c @@ -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)); diff --git a/gcc/testsuite/c-c++-common/attr-nonstring-12.c b/gcc/testsuite/c-c++-common/attr-nonstring-12.c index 75787e8..739e336 100644 --- a/gcc/testsuite/c-c++-common/attr-nonstring-12.c +++ b/gcc/testsuite/c-c++-common/attr-nonstring-12.c @@ -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." } */ } -- cgit v1.1