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 
32 // Don't warn on infinite loops
g()33 void g() {
34   while (true)
35     g();
36 
37   g();
38 }
39 
h(int x)40 void h(int x) {
41   while (x < 5) {
42     h(x+1);
43   }
44 }
45 
i(int x)46 void i(int x) {  // expected-warning{{call itself}}
47   while (x < 5) {
48     --x;
49   }
50   i(0);
51 }
52 
j()53 int j() {  // expected-warning{{call itself}}
54   return 5 + j();
55 }
56 
57 class S {
58   static void a();
59   void b();
60 };
61 
a()62 void S::a() {  // expected-warning{{call itself}}
63   return a();
64 }
65 
b()66 void S::b() {  // expected-warning{{call itself}}
67   int i = 0;
68   do {
69     ++i;
70     b();
71   } while (i > 5);
72 }
73 
74 template<class member>
75 struct T {
76   member m;
aT77   void a() { return a(); }  // expected-warning{{call itself}}
bT78   static void b() { return b(); }  // expected-warning{{call itself}}
79 };
80 
test_T()81 void test_T() {
82   T<int> foo;
83   foo.a();  // expected-note{{in instantiation}}
84   foo.b();  // expected-note{{in instantiation}}
85 }
86 
87 class U {
88   U* u;
Fun()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.
96 template <int value>
sum()97 int sum() {
98   return value + sum<value/2>();
99 }
100 
101 template<>
sum()102 int sum<1>() { return 1; }
103 
104 template<int x, int y>
calculate_value()105 int 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 
112 int value = calculate_value<1,1>();
113 
114 void DoSomethingHere();
115 
116 // DoStuff<0,0>() is instantiated, but never called.
117 template<int First, int Last>
DoStuff()118 int 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 }
129 int stuff = DoStuff<0, 1>();
130 
131 template<int x>
132 struct Wrapper {
runWrapper133   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   }
run2Wrapper139   static int run2() {  // expected-warning{{call itself}}
140     return run2();
141   }
142 };
143 
144 template <int x>
test_wrapper()145 int test_wrapper() {
146   if (x != 0)
147     return Wrapper<x>::run() +
148            Wrapper<x>::run2();  // expected-note{{instantiation}}
149   return 0;
150 }
151 
152 int wrapper_sum = test_wrapper<2>();  // expected-note{{instantiation}}
153