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