1// 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>(); 130 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}} 153