1  /* A copy of infinite-recursion-2.c, to see what inlining does to the IR
       2     when we see it.
       3  
       4     Many cases get converted by the optimizer into iteration, and
       5     into infinite loops, sometimes trivial ones.
       6  
       7     Right now this is a documented limitation of the warning, but perhaps
       8     could be readdressed by moving the analyzer earlier.   */
       9  
      10  /* { dg-additional-options "-O3" } */
      11  
      12  void test_direct (void)
      13  {
      14    test_direct (); /* Ideally would warn here, but it becomes an infinite loop.  */
      15  }
      16  
      17  void test_guarded (int flag)
      18  {
      19    if (flag)
      20      test_guarded (flag);  /* Ideally would warn here, but it becomes an infinite loop.  */
      21  }
      22  
      23  void test_flipped_guard (int flag)
      24  {
      25    if (flag)
      26      test_guarded (!flag);
      27  }
      28  
      29  void test_param_variant (int depth)
      30  {
      31    if (depth > 0)
      32      test_param_variant (depth - 1);
      33  }
      34  
      35  void test_unguarded_param_variant (int depth)
      36  {
      37    test_unguarded_param_variant (depth - 1); /* Ideally would warn here, but it becomes an infinite loop.  */
      38  }
      39  
      40  int g;
      41  
      42  void test_global_variant ()
      43  {
      44    if (g-- > 0)
      45      test_global_variant ();
      46  }
      47  
      48  /* This is a bounded recursion, as "n" is decremented before recursing... */
      49  
      50  int test_while_do_predecrement_param (int n)
      51  {
      52    int x = 0;
      53    while (n)
      54      x += test_while_do_predecrement_param (--n);
      55    return x;
      56  }
      57  
      58  /* ...whereas this one is unbounded, as "n" is decremented *after* the
      59     recursive call, and so is repeatedly called with the same value.  */
      60  
      61  int test_while_do_postdecrement_param (int n)
      62  {
      63    int x = 0;
      64    while (n)
      65      x += test_while_do_postdecrement_param (n--); /* { dg-warning "infinite recursion" } */
      66    return x;
      67  }
      68  /* This is a bounded recursion, as "n" is decremented before recursing... */
      69  
      70  int test_do_while_predecrement_param (int n)
      71  {
      72    int x = 0;
      73    do
      74      x += test_do_while_predecrement_param (--n);
      75    while (--n);
      76    return x;
      77  }
      78  
      79  /* ...whereas this one is unbounded, as "n" is decremented *after* the
      80     recursive call, and so is repeatedly called with the same value.  */
      81  
      82  int test_do_while_postdecrement_param (int n)
      83  {
      84    int x = 0;
      85    do
      86      x += test_do_while_postdecrement_param (n--); /* { dg-warning "infinite recursion" } */
      87    while (--n);
      88    return x;
      89  }
      90  
      91  /* Various cases of decrementing "n" as the recursion proceeds where
      92     not every path recurses, but we're not actually checking "n", so
      93     if "flag" is true it's an infinite recursion.  */
      94  
      95  void test_partially_guarded_postdecrement (int flag, int n)
      96  {
      97    /* Ideally we'd catch this, but it becomes an infinite loop.  */
      98    if (flag)
      99      test_partially_guarded_postdecrement (flag, n--);
     100  }
     101  
     102  void test_partially_guarded_predecrement (int flag, int n)
     103  {
     104    /* We fail to report this; we see that "n" is changing,
     105       though it isn't relevant to whether we recurse.  */
     106    if (flag)
     107      test_partially_guarded_predecrement (flag, --n); /* { dg-warning "infinite recursion" "TODO" { xfail *-*-* } } */
     108  }
     109  
     110  void test_partially_guarded_subtract (int flag, int n)
     111  {
     112    /* We fail to report this; we see that "n" is changing,
     113       though it isn't relevant to whether we recurse.  */
     114    if (flag)
     115      test_partially_guarded_subtract (flag, n - 1); /* { dg-warning "infinite recursion" "TODO" { xfail *-*-* } } */
     116  }