1 // RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion
2 
a()3 void a() {  // expected-warning{{call itself}}
4   a();
5 }
6 
b(int x)7 void b(int x) {  // expected-warning{{call itself}}
8   if (x)
9     b(x);
10   else
11     b(x+1);
12 }
13 
c(int x)14 void c(int x) {
15   if (x)
16     c(5);
17 }
18 
d(int x)19 void 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
26 void e();
27 void f();
28 
e()29 void e() { f(); }
f()30 void f() { e(); }
31 
g()32 void g() {  // expected-warning{{call itself}}
33   while (true)
34     g();
35 
36   g();
37 }
38 
h(int x)39 void h(int x) {
40   while (x < 5) {
41     h(x+1);
42   }
43 }
44 
i(int x)45 void i(int x) {  // expected-warning{{call itself}}
46   while (x < 5) {
47     --x;
48   }
49   i(0);
50 }
51 
j()52 int j() {  // expected-warning{{call itself}}
53   return 5 + j();
54 }
55 
56 // Don't warn on infinite loops
k()57 void k() {
58   while(true) {
59     k();
60   }
61 }
62 
l()63 void l() {
64   while (true) {}
65 
66   l();
67 }
68 
m()69 void m() {
70   static int count = 5;
71   if (count >0) {
72     count--;
73     l();
74   }
75   while (true) {}
76 }
77 
78 class S {
79   static void a();
80   void b();
81 };
82 
a()83 void S::a() {  // expected-warning{{call itself}}
84   return a();
85 }
86 
b()87 void S::b() {  // expected-warning{{call itself}}
88   int i = 0;
89   do {
90     ++i;
91     b();
92   } while (i > 5);
93 }
94 
95 template<class member>
96 struct T {
97   member m;
aT98   void a() { return a(); }  // expected-warning{{call itself}}
bT99   static void b() { return b(); }  // expected-warning{{call itself}}
100 };
101 
test_T()102 void test_T() {
103   T<int> foo;
104   foo.a();  // expected-note{{in instantiation}}
105   foo.b();  // expected-note{{in instantiation}}
106 }
107 
108 class U {
109   U* u;
Fun()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.
117 template <int value>
sum()118 int sum() {
119   return value + sum<value/2>();
120 }
121 
122 template<>
sum()123 int sum<1>() { return 1; }
124 
125 template<int x, int y>
calculate_value()126 int 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 
133 int value = calculate_value<1,1>();
134 
135 void DoSomethingHere();
136 
137 // DoStuff<0,0>() is instantiated, but never called.
138 template<int First, int Last>
DoStuff()139 int 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 }
150 int stuff = DoStuff<0, 1>();
151 
152 template<int x>
153 struct Wrapper {
runWrapper154   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   }
run2Wrapper160   static int run2() {  // expected-warning{{call itself}}
161     return run2();
162   }
163 };
164 
165 template <int x>
test_wrapper()166 int test_wrapper() {
167   if (x != 0)
168     return Wrapper<x>::run() +
169            Wrapper<x>::run2();  // expected-note{{instantiation}}
170   return 0;
171 }
172 
173 int wrapper_sum = test_wrapper<2>();  // expected-note{{instantiation}}
174