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