Clang Project

clang_source_code/test/SemaCXX/warn-infinite-recursion.cpp
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
32void g() {  // expected-warning{{call itself}}
33  while (true)
34    g();
35
36  g();
37}
38
39void h(int x) {
40  while (x < 5) {
41    h(x+1);
42  }
43}
44
45void i(int x) {  // expected-warning{{call itself}}
46  while (x < 5) {
47    --x;
48  }
49  i(0);
50}
51
52int j() {  // expected-warning{{call itself}}
53  return 5 + j();
54}
55
56// Don't warn on infinite loops
57void k() {
58  while(true) {
59    k();
60  }
61}
62
63void l() {
64  while (true) {}
65
66  l();
67}
68
69void m() {
70  static int count = 5;
71  if (count >0) {
72    count--;
73    l();
74  }
75  while (true) {}
76}
77
78class S {
79  static void a();
80  void b();
81};
82
83void S::a() {  // expected-warning{{call itself}}
84  return a();
85}
86
87void S::b() {  // expected-warning{{call itself}}
88  int i = 0;
89  do {
90    ++i;
91    b();
92  } while (i > 5);
93}
94
95template<class member>
96struct T {
97  member m;
98  void a() { return a(); }  // expected-warning{{call itself}}
99  static void b() { return b(); }  // expected-warning{{call itself}}
100};
101
102void test_T() {
103  T<int> foo;
104  foo.a();  // expected-note{{in instantiation}}
105  foo.b();  // expected-note{{in instantiation}}
106}
107
108class U {
109  U* u;
110  void Fun() {  // expected-warning{{call itself}}
111    u->Fun();
112  }
113};
114
115// No warnings on templated functions
116// sum<0>() is instantiated, does recursively call itself, but never runs.
117template <int value>
118int sum() {
119  return value + sum<value/2>();
120}
121
122template<>
123int sum<1>() { return 1; }
124
125template<int x, int y>
126int calculate_value() {
127  if (x != y)
128    return sum<x - y>();  // This instantiates sum<0>() even if never called.
129  else
130    return 0;
131}
132
133int value = calculate_value<1,1>();
134
135void DoSomethingHere();
136
137// DoStuff<0,0>() is instantiated, but never called.
138template<int First, int Last>
139int DoStuff() {
140  if (First + 1 == Last) {
141    // This branch gets removed during <0, 0> instantiation in so CFG for this
142    // function goes straight to the else branch.
143    DoSomethingHere();
144  } else {
145    DoStuff<First, (First + Last)/2>();
146    DoStuff<(First + Last)/2, Last>();
147  }
148  return 0;
149}
150int stuff = DoStuff<0, 1>();
151
152template<int x>
153struct Wrapper {
154  static int run() {
155    // Similar to the above, Wrapper<0>::run() will discard the if statement.
156    if (x == 1)
157      return 0;
158    return Wrapper<x/2>::run();
159  }
160  static int run2() {  // expected-warning{{call itself}}
161    return run2();
162  }
163};
164
165template <int x>
166int test_wrapper() {
167  if (x != 0)
168    return Wrapper<x>::run() +
169           Wrapper<x>::run2();  // expected-note{{instantiation}}
170  return 0;
171}
172
173int wrapper_sum = test_wrapper<2>();  // expected-note{{instantiation}}
174