xref: /minix3/external/bsd/llvm/dist/clang/test/SemaCXX/warn-infinite-recursion.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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