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