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 // Don't warn on infinite loops 57 void k() { 58 while(true) { 59 k(); 60 } 61 } 62 63 void l() { 64 while (true) {} 65 66 l(); 67 } 68 69 void m() { 70 static int count = 5; 71 if (count >0) { 72 count--; 73 l(); 74 } 75 while (true) {} 76 } 77 78 class S { 79 static void a(); 80 void b(); 81 }; 82 83 void S::a() { // expected-warning{{call itself}} 84 return a(); 85 } 86 87 void S::b() { // expected-warning{{call itself}} 88 int i = 0; 89 do { 90 ++i; 91 b(); 92 } while (i > 5); 93 } 94 95 template<class member> 96 struct T { 97 member m; 98 void a() { return a(); } // expected-warning{{call itself}} 99 static void b() { return b(); } // expected-warning{{call itself}} 100 }; 101 102 void test_T() { 103 T<int> foo; 104 foo.a(); // expected-note{{in instantiation}} 105 foo.b(); // expected-note{{in instantiation}} 106 } 107 108 class U { 109 U* u; 110 void Fun() { // expected-warning{{call itself}} 111 u->Fun(); 112 } 113 }; 114 115 // No warnings on templated functions 116 // sum<0>() is instantiated, does recursively call itself, but never runs. 117 template <int value> 118 int sum() { 119 return value + sum<value/2>(); 120 } 121 122 template<> 123 int sum<1>() { return 1; } 124 125 template<int x, int y> 126 int calculate_value() { 127 if (x != y) 128 return sum<x - y>(); // This instantiates sum<0>() even if never called. 129 else 130 return 0; 131 } 132 133 int value = calculate_value<1,1>(); 134 135 void DoSomethingHere(); 136 137 // DoStuff<0,0>() is instantiated, but never called. 138 template<int First, int Last> 139 int DoStuff() { 140 if (First + 1 == Last) { 141 // This branch gets removed during <0, 0> instantiation in so CFG for this 142 // function goes straight to the else branch. 143 DoSomethingHere(); 144 } else { 145 DoStuff<First, (First + Last)/2>(); 146 DoStuff<(First + Last)/2, Last>(); 147 } 148 return 0; 149 } 150 int stuff = DoStuff<0, 1>(); 151 152 template<int x> 153 struct Wrapper { 154 static int run() { 155 // Similar to the above, Wrapper<0>::run() will discard the if statement. 156 if (x == 1) 157 return 0; 158 return Wrapper<x/2>::run(); 159 } 160 static int run2() { // expected-warning{{call itself}} 161 return run2(); 162 } 163 }; 164 165 template <int x> 166 int test_wrapper() { 167 if (x != 0) 168 return Wrapper<x>::run() + 169 Wrapper<x>::run2(); // expected-note{{instantiation}} 170 return 0; 171 } 172 173 int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} 174 175 namespace std { 176 class type_info { 177 public: 178 virtual ~type_info(); 179 const char *name() const { return __name; } 180 bool operator==(const type_info &__arg) const { 181 return __name == __arg.__name; 182 } 183 184 bool operator!=(const type_info &__arg) const { 185 return !operator==(__arg); 186 } 187 188 protected: 189 const char *__name; 190 }; 191 } // namespace std 192 struct Q { 193 virtual ~Q() = default; 194 }; 195 196 Q q; 197 Q &evaluated_recursive_function(int x) { // expected-warning{{call itself}} 198 (void)typeid(evaluated_recursive_function(x)); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}} 199 return q; 200 } 201 202 int unevaluated_recursive_function() { 203 (void)typeid(unevaluated_recursive_function()); 204 return 0; 205 } 206