https://gcc.gnu.org/g:1301e18f69ced6a14a7648a24d1eb3addd836b6c

commit r15-7921-g1301e18f69ced6a14a7648a24d1eb3addd836b6c
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Mon Mar 10 09:31:41 2025 +0100

    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  <ja...@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.

Diff:
---
 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(-)

diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 351f48765101..305b63567fea 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 12fbc9005e33..745e99382fe3 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 75787e898be9..739e336c0b56 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." } */
 }

Reply via email to