(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
analyzer/
infinite-recursion-5.c
       1  /* Adapted from gcc.dg/Winfinite-recursion.c.  */
       2  
       3  #define NORETURN __attribute__ ((noreturn))
       4  
       5  typedef __SIZE_TYPE__ size_t;
       6  
       7  extern void abort (void);
       8  extern void exit (int);
       9  
      10  extern int ei;
      11  int (*pfi_v)(void);
      12  
      13  
      14  /* Make sure the warning doesn't assume every call has a DECL.  */
      15  
      16  int nowarn_pfi_v (void)
      17  {
      18    return pfi_v ();
      19  }
      20  
      21  
      22  int warn_fi_v (void)
      23  {
      24    return warn_fi_v ();               // { dg-warning "-Wanalyzer-infinite-recursion" }
      25  }
      26  
      27  /* Verify #pragma suppression works.  */
      28  
      29  #pragma GCC diagnostic push
      30  #pragma GCC diagnostic ignored "-Wanalyzer-infinite-recursion"
      31  
      32  int suppress_warn_fi_v (void)
      33  {
      34    return suppress_warn_fi_v ();
      35  }
      36  
      37  #pragma GCC diagnostic pop
      38  
      39  
      40  int nowarn_fi_v (void)
      41  {
      42    if (ei++ == 0)
      43      return nowarn_fi_v ();
      44    return 0;
      45  }
      46  
      47  /* -Winfinite-recursion warns for this, but
      48     -Wanalyzer-infinite-recursion doesn't.  */
      49  
      50  int warn_if_i (int i)
      51  {
      52    if (i > 0)
      53      return warn_if_i (--i);
      54    else if (i < 0)
      55      return warn_if_i (-i);
      56    else
      57      return warn_if_i (7);
      58  }
      59  
      60  
      61  int nowarn_if_i (int i)
      62  {
      63    if (i > 0)
      64      return nowarn_if_i (--i);
      65    else if (i < 0)
      66      return nowarn_if_i (-i);
      67    else
      68      return -1;
      69  }
      70  
      71  int nowarn_switch (int i, int a[])
      72  {
      73    switch (i)
      74      {
      75      case 0: return nowarn_switch (a[3], a + 1);
      76      case 1: return nowarn_switch (a[5], a + 2);
      77      case 2: return nowarn_switch (a[7], a + 3);
      78      case 3: return nowarn_switch (a[9], a + 4);
      79      }
      80    return 77;
      81  }
      82  
      83  /* -Winfinite-recursion warns for this, but
      84     -Wanalyzer-infinite-recursion doesn't.  */
      85  
      86  int warn_switch (int i, int a[])
      87  {
      88    switch (i)
      89      {
      90      case 0: return warn_switch (a[3], a + 1);
      91      case 1: return warn_switch (a[5], a + 2);
      92      case 2: return warn_switch (a[7], a + 3);
      93      case 3: return warn_switch (a[9], a + 4);
      94      default: return warn_switch (a[1], a + 5);
      95      }
      96  }
      97  
      98  NORETURN void fnoreturn (void);
      99  
     100  /* Verify there's no warning for a function that doesn't return.  */
     101  int nowarn_call_noret (void)
     102  {
     103    fnoreturn ();
     104  }
     105  
     106  int warn_call_noret_r (void)
     107  {
     108    warn_call_noret_r ();             // { dg-warning "-Wanalyzer-infinite-recursion" }
     109    fnoreturn ();
     110  }
     111  
     112  /* -Winfinite-recursion warns for this, but
     113     -Wanalyzer-infinite-recursion doesn't.  */
     114  
     115  int
     116  warn_noret_call_abort_r (char *s, int n)
     117  {
     118    if (!s)
     119      abort ();
     120  
     121    if (n > 7)
     122      abort ();
     123  
     124    return n + warn_noret_call_abort_r (s, n - 1);
     125  }
     126  
     127  NORETURN void nowarn_noret_call_abort_r (int n)
     128  {
     129    if (n > 7)
     130      abort ();
     131  
     132    nowarn_noret_call_abort_r (n - 1);
     133  }
     134  
     135  /* -Winfinite-recursion warns for this, but
     136     -Wanalyzer-infinite-recursion doesn't.  */
     137  
     138  int warn_call_abort_r (int n)
     139  {
     140    n += warn_call_abort_r (n - 1);
     141    if (n > 7)   // unreachable
     142      abort ();
     143    return n;
     144  }
     145  
     146  
     147  /* -Winfinite-recursion warns for this, but
     148     -Wanalyzer-infinite-recursion doesn't.  */
     149  
     150  int warn_call_exit_r (int n)
     151  {
     152    n += warn_call_exit_r (n - 1);
     153    if (n > 7)
     154      exit (0);
     155    return n;
     156  }
     157  
     158  struct __jmp_buf_tag { };
     159  typedef struct __jmp_buf_tag jmp_buf[1];
     160  
     161  extern jmp_buf jmpbuf;
     162  
     163  /* A call to longjmp() breaks infinite recursion.  Verify it suppresses
     164     the warning.  */
     165  
     166  int nowarn_call_longjmp_r (int n)
     167  {
     168    if (n > 7)
     169      __builtin_longjmp (jmpbuf, 1);
     170    return n + nowarn_call_longjmp_r (n - 1);
     171  }
     172  
     173  /* -Winfinite-recursion warns for this, but
     174     -Wanalyzer-infinite-recursion doesn't.  */
     175  
     176  int warn_call_longjmp_r (int n)
     177  {
     178    n += warn_call_longjmp_r (n - 1);
     179    if (n > 7)
     180      __builtin_longjmp (jmpbuf, 1);
     181    return n;
     182  }
     183  
     184  
     185  struct __sigjmp_buf_tag { };
     186  typedef struct __sigjmp_buf_tag sigjmp_buf[1];
     187  
     188  extern sigjmp_buf sigjmpbuf;
     189  
     190  /* GCC has no __builtin_siglongjmp().  */
     191  extern void siglongjmp (sigjmp_buf, int);
     192  
     193  /* A call to longjmp() breaks infinite recursion.  Verify it suppresses
     194     the warning.  */
     195  
     196  int nowarn_call_siglongjmp_r (int n)
     197  {
     198    if (n > 7)
     199      siglongjmp (sigjmpbuf, 1);
     200    return n + nowarn_call_siglongjmp_r (n - 1);
     201  }
     202  
     203  /* -Winfinite-recursion doesn't warn for this unbounded recursion, but
     204     -Wanalyzer-infinite-recursion does.  */
     205  
     206  int nowarn_while_do_call_r (int n)
     207  {
     208    int z = 0;
     209    while (n)
     210      z += nowarn_while_do_call_r (n--); // { dg-warning "-Wanalyzer-infinite-recursion" }
     211    return z;
     212  }
     213  
     214  int warn_do_while_call_r (int n)
     215  {
     216    int z = 0;
     217    do
     218      z += warn_do_while_call_r (n); // { dg-warning "-Wanalyzer-infinite-recursion" }
     219    while (--n);
     220    return z;
     221  }