(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-84.c
       1  /* PR tree-optimization/83821 - local aggregate initialization defeats
       2     strlen optimization
       3     Verify that stores that overwrite an interior nul are correctly
       4     reflected in strlen results.
       5     { dg-do run }
       6     { dg-options "-O2 -Wall" }
       7     { dg-require-effective-target alloca } */
       8  
       9  #define false (0 == 1)
      10  #define true (0 == 0)
      11  #define assert(e)							\
      12    ((e) ? (void)0 : (__builtin_printf ("assertion failed on line %i\n",	\
      13  				      __LINE__), __builtin_abort ()))
      14  
      15  #define ATTR(...) __attribute__ ((__VA_ARGS__))
      16  
      17  static inline int ATTR (always_inline)
      18  assign_and_get_length (char *p, _Bool clear)
      19  {
      20    p[0] = 'a';
      21  
      22    if (clear)
      23      p[1] = 0;
      24  
      25    p[2] = 'c';
      26  
      27    if (clear)
      28      p[3] = 0;
      29  
      30    p[1] = 'b';
      31  
      32    return __builtin_strlen (p);
      33  }
      34  
      35  ATTR (noipa) void array_get_length (void)
      36  {
      37    char a[4];
      38    unsigned n = assign_and_get_length (a, true);
      39    assert (n == 3);
      40  }
      41  
      42  ATTR (noipa) void clear_array_get_length (void)
      43  {
      44    char a[4] = { };
      45    unsigned n = assign_and_get_length (a, false);
      46    assert (n == 3);
      47  }
      48  
      49  ATTR (noipa) void calloc_get_length (void)
      50  {
      51    char *p = __builtin_calloc (5, 1);
      52    unsigned n = assign_and_get_length (p, false);
      53    assert (n == 3);
      54  }
      55  
      56  ATTR (noipa) void malloc_get_length (void)
      57  {
      58    char *p = __builtin_malloc (5);
      59    unsigned n = assign_and_get_length (p, true);
      60    assert (n == 3);
      61  }
      62  
      63  ATTR (noipa) void vla_get_length (int n)
      64  {
      65    char a[n];
      66    unsigned len = assign_and_get_length (a, true);
      67    assert (len == 3);
      68  }
      69  
      70  
      71  static inline void ATTR (always_inline)
      72  assign_and_test_length (char *p, _Bool clear)
      73  {
      74    p[0] = 'a';
      75  
      76    if (clear)
      77      p[1] = 0;
      78  
      79    p[2] = 'c';
      80  
      81    if (clear)
      82      p[3] = 0;
      83  
      84    unsigned n0 =  __builtin_strlen (p);
      85  
      86    p[1] = 'b';
      87  
      88    unsigned n1 =  __builtin_strlen (p);
      89    assert (n0 != n1);
      90  }
      91  
      92  ATTR (noipa) void array_test_length (void)
      93  {
      94    char a[4];
      95    assign_and_test_length (a, true);
      96  }
      97  
      98  ATTR (noipa) void clear_array_test_length (void)
      99  {
     100    char a[4] = { };
     101    assign_and_test_length (a, false);
     102  }
     103  
     104  ATTR (noipa) void calloc_test_length (void)
     105  {
     106    char *p = __builtin_calloc (5, 1);
     107    assign_and_test_length (p, false);
     108  }
     109  
     110  ATTR (noipa) void malloc_test_length (void)
     111  {
     112    char *p = __builtin_malloc (5);
     113    assign_and_test_length (p, true);
     114  }
     115  
     116  ATTR (noipa) void vla_test_length (int n)
     117  {
     118    char a[n];
     119    assign_and_test_length (a, true);
     120  }
     121  
     122  int main (void)
     123  {
     124    array_get_length ();
     125    clear_array_get_length ();
     126    calloc_get_length ();
     127    malloc_get_length ();
     128    vla_get_length (4);
     129  
     130    array_test_length ();
     131    clear_array_test_length ();
     132    calloc_test_length ();
     133    malloc_test_length ();
     134    vla_test_length (4);
     135  }
     136