1  /* Test to verify that strlen() calls with conditional expressions
       2     and unterminated arrays or pointers to such things as arguments
       3     are evaluated without making assumptions about array sizes.  */
       4  
       5  extern __SIZE_TYPE__ strlen (const char *);
       6  
       7  unsigned nfails;
       8  
       9  #define A(expr, N)						\
      10    do {								\
      11      const char *_s = (expr);					\
      12      unsigned _n = strlen (_s);					\
      13      ((_n == N)							\
      14       ? 0							\
      15       : (__builtin_printf ("line %i: strlen ((%s) = (\"%s\"))"	\
      16  			  " == %u failed\n",			\
      17  			  __LINE__, #expr, _s, N),		\
      18  	++nfails));						\
      19    } while (0)
      20  
      21  
      22  volatile int i0 = 0;
      23  
      24  const char ca[2][3] = { "12" };
      25  const char cb[2][3] = { { '1', '2', '3', }, { '4' } };
      26  
      27  char va[2][3] = { "123" };
      28  char vb[2][3] = { { '1', '2', '3', }, { '4', '5' } };
      29  
      30  const char *s = "123456";
      31  
      32  
      33  static void test_binary_cond_expr_global (void)
      34  {
      35    A (i0 ? "1" : ca[0], 2);
      36    A (i0 ? ca[0] : "123", 3);
      37  
      38    /* The call to strlen (cb[0]) is strictly undefined because the array
      39       isn't nul-terminated.  This test verifies that the strlen range
      40       optimization doesn't assume that the argument is necessarily nul
      41       terminated.
      42       Ditto for strlen (vb[0]).  */
      43    A (i0 ? "1" : cb[0], 4);              /* GCC 8.2 failure */
      44    A (i0 ? cb[0] : "12", 2);
      45  
      46    A (i0 ? "1" : va[0], 3);              /* GCC 8.2 failure */
      47    A (i0 ? va[0] : "1234", 4);
      48  
      49    A (i0 ? "1" : vb[0], 5);              /* GCC 8.2 failure */
      50    A (i0 ? vb[0] : "12", 2);
      51  }
      52  
      53  
      54  static void test_binary_cond_expr_local (void)
      55  {
      56    const char lca[2][3] = { "12" };
      57    const char lcb[2][3] = { { '1', '2', '3', }, { '4' } };
      58  
      59    char lva[2][3] = { "123" };
      60    char lvb[2][3] = { { '1', '2', '3', }, { '4', '5' } };
      61  
      62    /* Also undefined as above.  */
      63    A (i0 ? "1" : lca[0], 2);
      64    A (i0 ? lca[0] : "123", 3);
      65  
      66    A (i0 ? "1" : lcb[0], 4);             /* GCC 8.2 failure */
      67    A (i0 ? lcb[0] : "12", 2);
      68  
      69    A (i0 ? "1" : lva[0], 3);             /* GCC 8.2 failure */
      70    A (i0 ? lva[0] : "1234", 4);
      71  
      72    A (i0 ? "1" : lvb[0], 5);             /* GCC 8.2 failure */
      73    A (i0 ? lvb[0] : "12", 2);
      74  }
      75  
      76  
      77  static void test_ternary_cond_expr (void)
      78  {
      79    /* Also undefined.  */
      80    A (i0 == 0 ? s : i0 == 1 ? vb[0] : "123", 6);
      81    A (i0 == 0 ? vb[0] : i0 == 1 ? s : "123", 5);
      82    A (i0 == 0 ? "123" : i0 == 1 ? s : vb[0], 3);
      83  }
      84  
      85  
      86  const char (*pca)[3] = &ca[0];
      87  const char (*pcb)[3] = &cb[0];
      88  
      89  char (*pva)[3] = &va[0];
      90  char (*pvb)[3] = &vb[0];
      91  
      92  static void test_binary_cond_expr_arrayptr (void)
      93  {
      94    /* Also undefined.  */
      95    A (i0 ? *pca : *pcb, 4);              /* GCC 8.2 failure */
      96    A (i0 ? *pcb : *pca, 2);
      97  
      98    A (i0 ? *pva : *pvb, 5);              /* GCC 8.2 failure */
      99    A (i0 ? *pvb : *pva, 3);
     100  }
     101  
     102  
     103  int main (void)
     104  {
     105    test_binary_cond_expr_global ();
     106    test_binary_cond_expr_local ();
     107  
     108    test_ternary_cond_expr ();
     109    test_binary_cond_expr_arrayptr ();
     110  
     111    if (nfails)
     112      __builtin_abort ();
     113  }