(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
attr-nonstring-6.c
       1  /* PR 85623 - strncmp() warns about attribute 'nonstring' incorrectly
       2     in -Wstringop-overflow
       3    { dg-do compile }
       4    { dg-options "-O2 -Wstringop-overread -ftrack-macro-expansion=0" } */
       5  
       6  #include "../gcc.dg/range.h"
       7  
       8  #if __cplusplus
       9  extern "C" {
      10  #endif
      11  
      12  extern int strcmp (const char*, const char*);
      13  extern int strncmp (const char*, const char*, size_t);
      14  extern int strncasecmp (const char*, const char*, size_t);
      15  
      16  extern size_t strspn (const char*, const char*);
      17  extern size_t strcspn (const char*, const char*);
      18  
      19  #if __cplusplus
      20  }
      21  #endif
      22  
      23  #define S26 "0123456789abcdefghijklmnopqrstuvwxyz"
      24  #define S(n) (S26 + sizeof S26 - 1 - (n))
      25  
      26  char __attribute__ ((nonstring)) a3[3];
      27  char __attribute__ ((nonstring)) a5[5];
      28  
      29  void sink (int);
      30  
      31  #define T(call)   sink (call)
      32  
      33  void test_strcmp_cst (void)
      34  {
      35    /* Verify that no warning is issued for strcmp() calls with a non-string
      36       array argument when the other argument is a string whose length is
      37       less than the size of the array.  Because the function stops reading
      38       at the first nul character there is no chance that it will read past
      39       the end of the array.  */
      40    T (strcmp (S (0), a3));
      41    T (strcmp (S (1), a3));
      42    T (strcmp (S (2), a3));
      43    /* The following reads a3[3].  */
      44    T (strcmp (S (3), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
      45    /* The following also reads past the end of a3.  */
      46    T (strcmp (S (9), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
      47  
      48    T (strcmp (a3, S (0)));
      49    T (strcmp (a3, S (1)));
      50    T (strcmp (a3, S (2)));
      51    T (strcmp (a3, S (3)));   /* { dg-warning "\\\[-Wstringop-overread" } */
      52    T (strcmp (a3, S (9)));   /* { dg-warning "\\\[-Wstringop-overread" } */
      53  }
      54  
      55  
      56  void test_strcmp_range (const char *s)
      57  {
      58    s = signed_value () < 0 ? S (0) : S (1);
      59    T (strcmp (a3, s));
      60  
      61    s = signed_value () < 0 ? S (0) : S (2);
      62    T (strcmp (a3, s));
      63  
      64    s = signed_value () < 0 ? S (0) : S (3);
      65    T (strcmp (a3, s));       /* { dg-warning "\\\[-Wstringop-overread" } */
      66  
      67    s = signed_value () < 0 ? S (1) : S (2);
      68    T (strcmp (a3, s));
      69  
      70    s = signed_value () < 0 ? S (1) : S (3);
      71    T (strcmp (a3, s));       /* { dg-warning "\\\[-Wstringop-overread" } */
      72  
      73    s = signed_value () < 0 ? S (3) : S (4);
      74    T (strcmp (a3, s));       /* { dg-warning "\\\[-Wstringop-overread" } */
      75  }
      76  
      77  
      78  void test_strncmp_cst (void)
      79  {
      80    T (strncmp (S (0), a3, 1));
      81    T (strncmp (S (1), a3, 2));
      82    T (strncmp (S (2), a3, 3));
      83    T (strncmp (S (3), a3, 3));
      84    T (strncmp (S (3), a3, 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
      85  
      86    T (strncmp (S (9), a3, 3));
      87    T (strncmp (S (9), a3, 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
      88    T (strncmp (S (9), a3, 5));   /* { dg-warning "\\\[-Wstringop-overread" } */
      89  
      90    T (strncmp (a3, S (0), 1));
      91    T (strncmp (a3, S (1), 2));
      92    T (strncmp (a3, S (2), 3));
      93    T (strncmp (a3, S (3), 3));
      94    T (strncmp (a3, S (3), 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
      95  
      96    T (strncmp (a3, S (9), 3));
      97    T (strncmp (a3, S (9), 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
      98    T (strncmp (a3, S (9), 5));   /* { dg-warning "\\\[-Wstringop-overread" } */
      99  }
     100  
     101  void test_strncmp_range (const char *s)
     102  {
     103    T (strncmp (a3, S (2), UR (0, 3)));
     104    T (strncmp (a3, S (2), UR (1, 4)));
     105    T (strncmp (a3, S (2), UR (2, 5)));
     106    T (strncmp (a3, S (2), UR (3, 6)));
     107    T (strncmp (a3, S (2), UR (4, 7)));
     108  
     109    T (strncmp (a3, S (5), UR (0, 3)));
     110    T (strncmp (a3, S (5), UR (1, 4)));
     111    T (strncmp (a3, S (5), UR (2, 5)));
     112    T (strncmp (a3, S (5), UR (3, 6)));
     113    T (strncmp (a3, S (5), UR (4, 7)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     114    T (strncmp (a3, S (5), UR (7, 9)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     115  
     116    s = signed_value () < 0 ? S (0) : S (1);
     117    T (strncmp (a3, s, UR (1, 3)));
     118    T (strncmp (a3, s, UR (2, 5)));
     119  
     120    s = signed_value () < 0 ? S (2) : S (5);
     121    T (strncmp (a3, s, UR (1, 3)));
     122  
     123    s = signed_value () < 0 ? S (2) : S (5);
     124    T (strncmp (a3, s, UR (1, 4)));
     125    T (strncmp (a3, s, UR (2, 5)));
     126    T (strncmp (a3, s, UR (3, 6)));
     127    T (strncmp (a3, s, UR (4, 7)));       /* { dg-warning "\\\[-Wstringop-overread" } */
     128  }
     129  
     130  void test_strncasecmp (void)
     131  {
     132    T (strncasecmp (S (0), a3, 1));
     133    T (strncasecmp (S (1), a3, 2));
     134    T (strncasecmp (S (2), a3, 3));
     135    T (strncasecmp (S (3), a3, 3));
     136    T (strncasecmp (S (3), a3, 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
     137  
     138    T (strncasecmp (S (9), a3, 3));
     139    T (strncasecmp (S (9), a3, 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
     140    T (strncasecmp (S (9), a3, 5));   /* { dg-warning "\\\[-Wstringop-overread" } */
     141  
     142    T (strncasecmp (a3, S (0), 1));
     143    T (strncasecmp (a3, S (1), 2));
     144    T (strncasecmp (a3, S (2), 3));
     145    T (strncasecmp (a3, S (3), 3));
     146    T (strncasecmp (a3, S (3), 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
     147  
     148    T (strncasecmp (a3, S (9), 3));
     149    T (strncasecmp (a3, S (9), 4));   /* { dg-warning "\\\[-Wstringop-overread" } */
     150    T (strncasecmp (a3, S (9), 5));   /* { dg-warning "\\\[-Wstringop-overread" } */
     151  }
     152  
     153  void test_strspn (void)
     154  {
     155    /* strspn must traverse all characters in the second argument except
     156       when the first string is empty. */
     157    T (strspn (S (0), a3));
     158    T (strspn (S (1), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     159    T (strspn (S (2), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     160    T (strspn (S (3), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     161    T (strspn (S (9), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     162  
     163    /* Similarly, strspn must traverse all characters in the first argument
     164       except when the second string is empty. */
     165    T (strspn (a3, S (0)));
     166    T (strspn (a3, S (1)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     167    T (strspn (a3, S (2)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     168    T (strspn (a3, S (3)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     169    T (strspn (a3, S (9)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     170  }
     171  
     172  void test_strcspn (void)
     173  {
     174    T (strcspn (S (0), a3));
     175    T (strcspn (S (1), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     176    T (strcspn (S (2), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     177    T (strcspn (S (3), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     178    T (strcspn (S (9), a3));   /* { dg-warning "\\\[-Wstringop-overread" } */
     179  
     180    T (strcspn (a3, S (0)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     181    T (strcspn (a3, S (1)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     182    T (strcspn (a3, S (2)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     183    T (strcspn (a3, S (3)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     184    T (strcspn (a3, S (9)));   /* { dg-warning "\\\[-Wstringop-overread" } */
     185  }