blob: e5a5a18b6571792edb5c7dc6b820a5230222abe8 [file] [log] [blame]
 // RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion void a() { // expected-warning{{call itself}} a(); } void b(int x) { // expected-warning{{call itself}} if (x) b(x); else b(x+1); } void c(int x) { if (x) c(5); } void d(int x) { // expected-warning{{call itself}} if (x) ++x; return d(x); } // Doesn't warn on mutually recursive functions void e(); void f(); void e() { f(); } void f() { e(); } void g() { // expected-warning{{call itself}} while (true) g(); g(); } void h(int x) { while (x < 5) { h(x+1); } } void i(int x) { // expected-warning{{call itself}} while (x < 5) { --x; } i(0); } int j() { // expected-warning{{call itself}} return 5 + j(); } // Don't warn on infinite loops void k() { while(true) { k(); } } void l() { while (true) {} l(); } void m() { static int count = 5; if (count >0) { count--; l(); } while (true) {} } class S { static void a(); void b(); }; void S::a() { // expected-warning{{call itself}} return a(); } void S::b() { // expected-warning{{call itself}} int i = 0; do { ++i; b(); } while (i > 5); } template struct T { member m; void a() { return a(); } // expected-warning{{call itself}} static void b() { return b(); } // expected-warning{{call itself}} }; void test_T() { T foo; foo.a(); // expected-note{{in instantiation}} foo.b(); // expected-note{{in instantiation}} } class U { U* u; void Fun() { // expected-warning{{call itself}} u->Fun(); } }; // No warnings on templated functions // sum<0>() is instantiated, does recursively call itself, but never runs. template int sum() { return value + sum(); } template<> int sum<1>() { return 1; } template int calculate_value() { if (x != y) return sum(); // This instantiates sum<0>() even if never called. else return 0; } int value = calculate_value<1,1>(); void DoSomethingHere(); // DoStuff<0,0>() is instantiated, but never called. template int DoStuff() { if (First + 1 == Last) { // This branch gets removed during <0, 0> instantiation in so CFG for this // function goes straight to the else branch. DoSomethingHere(); } else { DoStuff(); DoStuff<(First + Last)/2, Last>(); } return 0; } int stuff = DoStuff<0, 1>(); template struct Wrapper { static int run() { // Similar to the above, Wrapper<0>::run() will discard the if statement. if (x == 1) return 0; return Wrapper::run(); } static int run2() { // expected-warning{{call itself}} return run2(); } }; template int test_wrapper() { if (x != 0) return Wrapper::run() + Wrapper::run2(); // expected-note{{instantiation}} return 0; } int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}}