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