(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-45.c
       1  /* PR tree-optimization/81384 - built-in form of strnlen missing
       2     Test to verify that strnlen built-in expansion works correctly
       3     in the absence of tree strlen optimization.
       4     { dg-do compile }
       5     { dg-options "-O2 -Wall -Wno-stringop-overflow -fdump-tree-optimized" } */
       6  
       7  #include "strlenopt.h"
       8  
       9  #define PTRDIFF_MAX __PTRDIFF_MAX__
      10  #define SIZE_MAX    __SIZE_MAX__
      11  
      12  typedef __SIZE_TYPE__ size_t;
      13  
      14  extern void abort (void);
      15  extern size_t strnlen (const char *, size_t);
      16  
      17  #define CAT(x, y) x ## y
      18  #define CONCAT(x, y) CAT (x, y)
      19  #define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
      20  
      21  #define FAIL(name) do {				\
      22      extern void FAILNAME (name) (void);		\
      23      FAILNAME (name)();				\
      24    } while (0)
      25  
      26  /* Macro to emit a call to funcation named
      27       call_in_true_branch_not_eliminated_on_line_NNN()
      28     for each call that's expected to be eliminated.  The dg-final
      29     scan-tree-dump-time directive at the bottom of the test verifies
      30     that no such call appears in output.  */
      31  #define ELIM(expr) \
      32    if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
      33  
      34  /* Macro to emit a call to a function named
      35       call_made_in_{true,false}_branch_on_line_NNN()
      36     for each call that's expected to be retained.  The dg-final
      37     scan-tree-dump-time directive at the bottom of the test verifies
      38     that the expected number of both kinds of calls appears in output
      39     (a pair for each line with the invocation of the KEEP() macro.  */
      40  #define KEEP(expr)				\
      41    if (expr)					\
      42      FAIL (made_in_true_branch);			\
      43    else						\
      44      FAIL (made_in_false_branch)
      45  
      46  extern char c;
      47  extern char a1[1];
      48  extern char a3[3];
      49  extern char a5[5];
      50  extern char a3_7[3][7];
      51  extern char ax[];
      52  
      53  void elim_strnlen_arr_cst (void)
      54  {
      55    /* The length of a string stored in a one-element array must be zero.
      56       The result reported by strnlen() for such an array can be non-zero
      57       only when the bound is equal to 1 (in which case the result must
      58       be one).  */
      59    ELIM (strnlen (&c, 0) == 0);
      60    ELIM (strnlen (&c, 1) < 2);
      61    ELIM (strnlen (&c, 2) == 0);
      62    ELIM (strnlen (&c, 9) == 0);
      63    ELIM (strnlen (&c, PTRDIFF_MAX) == 0);
      64    ELIM (strnlen (&c, SIZE_MAX) == 0);
      65    ELIM (strnlen (&c, -1) == 0);
      66  
      67    ELIM (strnlen (a1, 0) == 0);
      68    ELIM (strnlen (a1, 1) < 2);
      69    ELIM (strnlen (a1, 2) == 0);
      70    ELIM (strnlen (a1, 9) == 0);
      71    ELIM (strnlen (a1, PTRDIFF_MAX) == 0);
      72    ELIM (strnlen (a1, SIZE_MAX) == 0);
      73    ELIM (strnlen (a1, -1) == 0);
      74  
      75    ELIM (strnlen (a3, 0) == 0);
      76    ELIM (strnlen (a3, 1) < 2);
      77    ELIM (strnlen (a3, 2) < 3);
      78    ELIM (strnlen (a3, 3) < 4);
      79    ELIM (strnlen (a3, 9) < 4);
      80    ELIM (strnlen (a3, PTRDIFF_MAX) < 4);
      81    ELIM (strnlen (a3, SIZE_MAX) < 4);
      82    ELIM (strnlen (a3, -1) < 4);
      83  
      84    ELIM (strnlen (a3_7[0], 0) == 0);
      85    ELIM (strnlen (a3_7[0], 1) < 2);
      86    ELIM (strnlen (a3_7[0], 2) < 3);
      87    ELIM (strnlen (a3_7[0], 3) < 4);
      88    ELIM (strnlen (a3_7[0], 9) <= 9);
      89    ELIM (strnlen (a3_7[0], PTRDIFF_MAX) <= sizeof a3_7);
      90    ELIM (strnlen (a3_7[0], SIZE_MAX) <= sizeof a3_7);
      91    ELIM (strnlen (a3_7[0], -1) <= sizeof a3_7);
      92  
      93    ELIM (strnlen (a3_7[2], 0) == 0);
      94    ELIM (strnlen (a3_7[2], 1) < 2);
      95    ELIM (strnlen (a3_7[2], 2) < 3);
      96    ELIM (strnlen (a3_7[2], 3) < 4);
      97    ELIM (strnlen (a3_7[2], 9) <= 9);
      98    ELIM (strnlen (a3_7[2], PTRDIFF_MAX) < sizeof a3_7);
      99    ELIM (strnlen (a3_7[2], SIZE_MAX) < sizeof a3_7);
     100    ELIM (strnlen (a3_7[2], -1) < sizeof a3_7);
     101  
     102    ELIM (strnlen ((char*)a3_7, 0) == 0);
     103    ELIM (strnlen ((char*)a3_7, 1) < 2);
     104    ELIM (strnlen ((char*)a3_7, 2) < 3);
     105    ELIM (strnlen ((char*)a3_7, 3) < 4);
     106    ELIM (strnlen ((char*)a3_7, 9) < 10);
     107    ELIM (strnlen ((char*)a3_7, 19) < 20);
     108    ELIM (strnlen ((char*)a3_7, 21) <= sizeof a3_7);
     109    ELIM (strnlen ((char*)a3_7, 23) <= sizeof a3_7);
     110    ELIM (strnlen ((char*)a3_7, PTRDIFF_MAX) <= sizeof a3_7);
     111    ELIM (strnlen ((char*)a3_7, SIZE_MAX) <= sizeof a3_7);
     112    ELIM (strnlen ((char*)a3_7, -1) <= sizeof a3_7);
     113  
     114    ELIM (strnlen (ax, 0) == 0);
     115    ELIM (strnlen (ax, 1) < 2);
     116    ELIM (strnlen (ax, 2) < 3);
     117    ELIM (strnlen (ax, 9) < 10);
     118    ELIM (strnlen (ax, PTRDIFF_MAX) < PTRDIFF_MAX);
     119    ELIM (strnlen (ax, SIZE_MAX) < PTRDIFF_MAX);
     120    ELIM (strnlen (ax, -1) < PTRDIFF_MAX);
     121  }
     122  
     123  
     124  void elim_strnlen_str_cst (void)
     125  {
     126    const char *s0 = "";
     127    const char *s1 = "1";
     128    const char *s3 = "123";
     129  
     130    ELIM (strnlen (s0, 0) == 0);
     131    ELIM (strnlen (s0, 1) == 0);
     132    ELIM (strnlen (s0, 9) == 0);
     133    ELIM (strnlen (s0, PTRDIFF_MAX) == 0);
     134    ELIM (strnlen (s0, SIZE_MAX) == 0);
     135    ELIM (strnlen (s0, -1) == 0);
     136  
     137    ELIM (strnlen (s1, 0) == 0);
     138    ELIM (strnlen (s1, 1) == 1);
     139    ELIM (strnlen (s1, 9) == 1);
     140    ELIM (strnlen (s1, PTRDIFF_MAX) == 1);
     141    ELIM (strnlen (s1, SIZE_MAX) == 1);
     142    ELIM (strnlen (s1, -2) == 1);
     143  
     144    ELIM (strnlen (s3, 0) == 0);
     145    ELIM (strnlen (s3, 1) == 1);
     146    ELIM (strnlen (s3, 2) == 2);
     147    ELIM (strnlen (s3, 3) == 3);
     148    ELIM (strnlen (s3, 9) == 3);
     149    ELIM (strnlen (s3, PTRDIFF_MAX) == 3);
     150    ELIM (strnlen (s3, SIZE_MAX) == 3);
     151    ELIM (strnlen (s3, -2) == 3);
     152  }
     153  
     154  void elim_strnlen_range (char *s)
     155  {
     156    const char *s0 = "";
     157    const char *s1 = "1";
     158    const char *s3 = "123";
     159  
     160    size_t n_0_1 = (size_t)s & 1;
     161    size_t n_0_2 = ((size_t)s & 3) < 3 ? ((size_t)s & 3) : 2;
     162    size_t n_0_3 = (size_t)s & 3;
     163    size_t n_1_2 = n_0_1 + 1;
     164  
     165    ELIM (strnlen (s0, n_0_1) == 0);
     166    ELIM (strnlen (s0, n_0_2) == 0);
     167    ELIM (strnlen (s0, n_1_2) == 0);
     168  
     169    ELIM (strnlen (s1, n_0_1) < 2);
     170    ELIM (strnlen (s1, n_0_2) < 2);
     171    ELIM (strnlen (s1, n_0_3) < 2);
     172  
     173    ELIM (strnlen (s1, n_1_2) > 0);
     174    ELIM (strnlen (s1, n_1_2) < 2);
     175  
     176    ELIM (strnlen (s3, n_0_1) < 2);
     177    ELIM (strnlen (s3, n_0_2) < 3);
     178    ELIM (strnlen (s3, n_0_3) < 4);
     179  
     180    ELIM (strnlen (s3, n_1_2) > 0);
     181    ELIM (strnlen (s3, n_1_2) < 4);
     182  }
     183  
     184  
     185  #line 1000
     186  
     187  void keep_strnlen_arr_cst (void)
     188  {
     189    KEEP (strnlen (&c, 1) == 0);
     190    KEEP (strnlen (&c, 1) == 1);
     191  
     192    KEEP (strnlen (a1, 1) == 0);
     193    KEEP (strnlen (a1, 1) == 1);
     194  
     195    KEEP (strnlen (ax, 9) < 9);
     196  }
     197  
     198  struct FlexArrays
     199  {
     200    char c;
     201    char a0[0];   /* Access to internal zero-length arrays are undefined.  */
     202    char a1[1];
     203  };
     204  
     205  void keep_strnlen_memarr_cst (struct FlexArrays *p)
     206  {
     207    KEEP (strnlen (&p->c, 1) == 0);
     208    KEEP (strnlen (&p->c, 1) == 1);
     209  
     210  #if 0
     211    /* Accesses to internal zero-length arrays are undefined so avoid
     212       exercising them.  */
     213    KEEP (strnlen (p->a0, 1) == 0);
     214    KEEP (strnlen (p->a0, 1) == 1);
     215    KEEP (strnlen (p->a0, 9) < 9);
     216  #endif
     217  
     218    KEEP (strnlen (p->a1, 1) == 0);
     219    KEEP (strnlen (p->a1, 1) == 1);
     220  
     221    KEEP (strnlen (p->a1, 2) == 0);
     222    KEEP (strnlen (p->a1, 2) == 1);
     223    KEEP (strnlen (p->a1, 2) == 2);
     224  
     225    KEEP (strnlen (p->a1, 9) < 9);
     226  }
     227  
     228  /* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
     229  
     230     { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 13 "optimized" } }
     231     { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 13 "optimized" } } */