aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/c-c++-common/analyzer/infinite-recursion-inlining.c
blob: 9dd5590acc04fc7282a6479883cd2ea6afbee6a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* A copy of infinite-recursion-2.c, to see what inlining does to the IR
   when we see it.

   Many cases get converted by the optimizer into iteration, and
   into infinite loops, sometimes trivial ones.

   Right now this is a documented limitation of the warning, but perhaps
   could be readdressed by moving the analyzer earlier.   */

/* { dg-additional-options "-O3" } */

void test_direct (void)
{
  test_direct ();
} /* { dg-warning "infinite-loop" } */

void test_guarded (int flag)
{
  if (flag) /* { dg-warning "infinite-loop" } */
    test_guarded (flag);
}

void test_flipped_guard (int flag)
{
  if (flag)
    test_guarded (!flag);
}

void test_param_variant (int depth)
{
  if (depth > 0)
    test_param_variant (depth - 1);
}

void test_unguarded_param_variant (int depth)
{
  test_unguarded_param_variant (depth - 1); /* { dg-warning "infinite-loop" } */
}

int g;

void test_global_variant ()
{
  if (g-- > 0)
    test_global_variant ();
}

/* This is a bounded recursion, as "n" is decremented before recursing... */

int test_while_do_predecrement_param (int n)
{
  int x = 0;
  while (n)
    x += test_while_do_predecrement_param (--n);
  return x;
}

/* ...whereas this one is unbounded, as "n" is decremented *after* the
   recursive call, and so is repeatedly called with the same value.  */

int test_while_do_postdecrement_param (int n)
{
  int x = 0;
  while (n)
    x += test_while_do_postdecrement_param (n--); /* { dg-warning "infinite recursion" } */
  return x;
}
/* This is a bounded recursion, as "n" is decremented before recursing... */

int test_do_while_predecrement_param (int n)
{
  int x = 0;
  do
    x += test_do_while_predecrement_param (--n);
  while (--n);
  return x;
}

/* ...whereas this one is unbounded, as "n" is decremented *after* the
   recursive call, and so is repeatedly called with the same value.  */

int test_do_while_postdecrement_param (int n)
{
  int x = 0;
  do
    x += test_do_while_postdecrement_param (n--); /* { dg-warning "infinite recursion" } */
  while (--n);
  return x;
}

/* Various cases of decrementing "n" as the recursion proceeds where
   not every path recurses, but we're not actually checking "n", so
   if "flag" is true it's an infinite recursion (which looks like an
   infinite loop after inlining).  */

void test_partially_guarded_postdecrement (int flag, int n)
{
  if (flag) /* { dg-warning "infinite loop" } */
    test_partially_guarded_postdecrement (flag, n--);
}

void test_partially_guarded_predecrement (int flag, int n)
{
  if (flag) /* { dg-warning "infinite loop" } */
    test_partially_guarded_predecrement (flag, --n);
}

void test_partially_guarded_subtract (int flag, int n)
{
  if (flag) /* { dg-warning "infinite loop" } */
    test_partially_guarded_subtract (flag, n - 1);
}