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