(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
tree-ssa/
pr79376.c
       1  /* PR tree-optimization/79376 - wrong lower bound with %s and non-constant
       2     strings in -Wformat-overflow
       3     { dg-do compile }
       4     { dg-options "-O2 -fdump-tree-optimized" } */
       5  
       6  #define CAT(s, n)   s ## n
       7  #define FAIL(line)  CAT (failure_on_line_, line)
       8  
       9  /* Emit a call to a function named failure_on_line_NNN when EXPR is false.  */
      10  #define ASSERT(expr)				\
      11    do {						\
      12      extern void FAIL (__LINE__)(void);		\
      13      if (!(expr)) FAIL (__LINE__)();		\
      14    } while (0)
      15  
      16  #define KEEP(line)  CAT (keep_call_on_line_, line)
      17  
      18  /* Emit a call to a function named keep_call_on_line_NNN when EXPR is true.
      19     Used to verify that the expression need not be the only one that holds.  */
      20  #define ASSERT_MAYBE(expr)			\
      21    do {						\
      22      extern void KEEP (__LINE__)(void);		\
      23      if (expr) KEEP (__LINE__)();		\
      24    } while (0)
      25  
      26  struct Arrays
      27  {
      28    char a1[1];
      29    char a2[2];
      30    char a3[3];
      31    char a4[4];
      32    char a5[5];
      33    char ax[];
      34  };
      35  
      36  void test_arrays (int i, struct Arrays *a)
      37  {
      38    {
      39      const char *s = i < 0 ? a->a3 : a->a1;
      40  
      41      int n = __builtin_snprintf (0, 0, "%-s", s);
      42  
      43      /* Since it's undefined to pass an unterminated array to a %s
      44         directive it would be valid to assume that S above is not
      45         longer than sizeof (A->A3) but the optimization isn't done
      46         because the GIMPLE representation of the %s argument isn't
      47         suffficiently reliable not to confuse it for some other
      48         array.  The argument length is therefore assumed to be in
      49         the range [0, PTRDIFF_MAX - 2] and the sprintf result to be
      50         as big as INT_MAX and possibly even negative if the function
      51         were to fail due to a single directive resulting in more than
      52         the 4,095 byte maximum required to be supported.
      53         ASSERT (0 <= n && n < 3);
      54      */
      55  
      56      ASSERT_MAYBE (0 == n);
      57      ASSERT_MAYBE (1 == n);
      58      ASSERT_MAYBE (2 == n);
      59    }
      60  
      61    {
      62      const char *s = i < 0 ? a->a3 : a->a5;
      63  
      64      int n = __builtin_snprintf (0, 0, "%-s", s);
      65  
      66      /* ASSERT (0 <= n && n < 5); */
      67  
      68      ASSERT_MAYBE (0 == n);
      69      ASSERT_MAYBE (1 == n);
      70      ASSERT_MAYBE (2 == n);
      71      ASSERT_MAYBE (3 == n);
      72      ASSERT_MAYBE (4 == n);
      73    }
      74  }
      75  
      76  void test_string_and_array (int i, struct Arrays *a)
      77  {
      78    {
      79      const char *s = i < 0 ? a->a3 : "1";
      80  
      81      int n = __builtin_snprintf (0, 0, "%-s", s);
      82  
      83      /* ASSERT (0 <= n && n < 3); */
      84  
      85      ASSERT_MAYBE (0 == n);
      86      ASSERT_MAYBE (1 == n);
      87      ASSERT_MAYBE (2 == n);
      88    }
      89  
      90    {
      91      const char *s = i < 0 ? "12" : a->a5;
      92  
      93      int n = __builtin_snprintf (0, 0, "%-s", s);
      94  
      95      /* ASSERT (0 <= n && n < 5); */
      96  
      97      ASSERT_MAYBE (0 == n);
      98      ASSERT_MAYBE (1 == n);
      99      ASSERT_MAYBE (2 == n);
     100      ASSERT_MAYBE (3 == n);
     101      ASSERT_MAYBE (4 == n);
     102    }
     103  
     104    {
     105      const char *s = i < 0 ? a->a4 : 0 < i ? "12" : a->a5;
     106  
     107      int n = __builtin_snprintf (0, 0, "%-s", s);
     108  
     109      /* ASSERT (0 <= n && n < 5); */
     110  
     111      ASSERT_MAYBE (0 == n);
     112      ASSERT_MAYBE (1 == n);
     113      ASSERT_MAYBE (2 == n);
     114      ASSERT_MAYBE (3 == n);
     115      ASSERT_MAYBE (4 == n);
     116    }
     117  }
     118  
     119  /* { dg-final { scan-tree-dump-not "failure_on_line" "optimized"} }
     120     { dg-final { scan-tree-dump-times "keep_call_on_line" 21 "optimized"} } */