1// RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion
2
3void a() {  // expected-warning{{call itself}}
4  a();
5}
6
7void b(int x) {  // expected-warning{{call itself}}
8  if (x)
9    b(x);
10  else
11    b(x+1);
12}
13
14void c(int x) {
15  if (x)
16    c(5);
17}
18
19void d(int x) {  // expected-warning{{call itself}}
20  if (x)
21    ++x;
22  return d(x);
23}
24
25// Doesn't warn on mutually recursive functions
26void e();
27void f();
28
29void e() { f(); }
30void f() { e(); }
31
32// Don't warn on infinite loops
33void g() {
34  while (true)
35    g();
36
37  g();
38}
39
40void h(int x) {
41  while (x < 5) {
42    h(x+1);
43  }
44}
45
46void i(int x) {  // expected-warning{{call itself}}
47  while (x < 5) {
48    --x;
49  }
50  i(0);
51}
52
53int j() {  // expected-warning{{call itself}}
54  return 5 + j();
55}
56
57class S {
58  static void a();
59  void b();
60};
61
62void S::a() {  // expected-warning{{call itself}}
63  return a();
64}
65
66void S::b() {  // expected-warning{{call itself}}
67  int i = 0;
68  do {
69    ++i;
70    b();
71  } while (i > 5);
72}
73
74template<class member>
75struct T {
76  member m;
77  void a() { return a(); }  // expected-warning{{call itself}}
78  static void b() { return b(); }  // expected-warning{{call itself}}
79};
80
81void test_T() {
82  T<int> foo;
83  foo.a();  // expected-note{{in instantiation}}
84  foo.b();  // expected-note{{in instantiation}}
85}
86
87class U {
88  U* u;
89  void Fun() {  // expected-warning{{call itself}}
90    u->Fun();
91  }
92};
93
94// No warnings on templated functions
95// sum<0>() is instantiated, does recursively call itself, but never runs.
96template <int value>
97int sum() {
98  return value + sum<value/2>();
99}
100
101template<>
102int sum<1>() { return 1; }
103
104template<int x, int y>
105int calculate_value() {
106  if (x != y)
107    return sum<x - y>();  // This instantiates sum<0>() even if never called.
108  else
109    return 0;
110}
111
112int value = calculate_value<1,1>();
113
114void DoSomethingHere();
115
116// DoStuff<0,0>() is instantiated, but never called.
117template<int First, int Last>
118int DoStuff() {
119  if (First + 1 == Last) {
120    // This branch gets removed during <0, 0> instantiation in so CFG for this
121    // function goes straight to the else branch.
122    DoSomethingHere();
123  } else {
124    DoStuff<First, (First + Last)/2>();
125    DoStuff<(First + Last)/2, Last>();
126  }
127  return 0;
128}
129int stuff = DoStuff<0, 1>();
130
131template<int x>
132struct Wrapper {
133  static int run() {
134    // Similar to the above, Wrapper<0>::run() will discard the if statement.
135    if (x == 1)
136      return 0;
137    return Wrapper<x/2>::run();
138  }
139  static int run2() {  // expected-warning{{call itself}}
140    return run2();
141  }
142};
143
144template <int x>
145int test_wrapper() {
146  if (x != 0)
147    return Wrapper<x>::run() +
148           Wrapper<x>::run2();  // expected-note{{instantiation}}
149  return 0;
150}
151
152int wrapper_sum = test_wrapper<2>();  // expected-note{{instantiation}}
153