218 lines · cpp
1// RUN: %clang_cc1 %s -fsyntax-only -verify -Winfinite-recursion2 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 else11 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 functions26void e();27void f();28 29void e() { f(); }30void f() { e(); }31 32void g() { // expected-warning{{call itself}}33 while (true)34 g();35 36 g();37}38 39void h(int x) {40 while (x < 5) {41 h(x+1);42 }43}44 45void i(int x) { // expected-warning{{call itself}}46 while (x < 5) {47 --x;48 }49 i(0);50}51 52int j() { // expected-warning{{call itself}}53 return 5 + j();54}55 56// Don't warn on infinite loops57void k() {58 while(true) {59 k();60 }61}62 63void l() {64 while (true) {}65 66 l();67}68 69void m() {70 static int count = 5;71 if (count >0) {72 count--;73 l();74 }75 while (true) {}76}77 78void n() { ::n(); } // expected-warning{{call itself}}79 80class S {81 static void a();82 void b();83};84 85void S::a() { // expected-warning{{call itself}}86 return a();87}88 89void S::b() { // expected-warning{{call itself}}90 int i = 0;91 do {92 ++i;93 b();94 } while (i > 5);95}96 97template<class member>98struct T {99 member m;100 void a() { return a(); } // expected-warning{{call itself}}101 static void b() { return b(); } // expected-warning{{call itself}}102};103 104void test_T() {105 T<int> foo;106 foo.a(); // expected-note{{in instantiation}}107 foo.b(); // expected-note{{in instantiation}}108}109 110class U {111 U* u;112 void Fun() { // expected-warning{{call itself}}113 u->Fun();114 }115};116 117// No warnings on templated functions118// sum<0>() is instantiated, does recursively call itself, but never runs.119template <int value>120int sum() {121 return value + sum<value/2>();122}123 124template<>125int sum<1>() { return 1; }126 127template<int x, int y>128int calculate_value() {129 if (x != y)130 return sum<x - y>(); // This instantiates sum<0>() even if never called.131 else132 return 0;133}134 135int value = calculate_value<1,1>();136 137void DoSomethingHere();138 139// DoStuff<0,0>() is instantiated, but never called.140template<int First, int Last>141int DoStuff() {142 if (First + 1 == Last) {143 // This branch gets removed during <0, 0> instantiation in so CFG for this144 // function goes straight to the else branch.145 DoSomethingHere();146 } else {147 DoStuff<First, (First + Last)/2>();148 DoStuff<(First + Last)/2, Last>();149 }150 return 0;151}152int stuff = DoStuff<0, 1>();153 154template<int x>155struct Wrapper {156 static int run() {157 // Similar to the above, Wrapper<0>::run() will discard the if statement.158 if (x == 1)159 return 0;160 return Wrapper<x/2>::run();161 }162 static int run2() { // expected-warning{{call itself}}163 return run2();164 }165};166 167template <int x>168int test_wrapper() {169 if (x != 0)170 return Wrapper<x>::run() +171 Wrapper<x>::run2(); // expected-note{{instantiation}}172 return 0;173}174 175int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}}176 177namespace std {178class type_info {179public:180 virtual ~type_info();181 const char *name() const { return __name; }182 bool operator==(const type_info &__arg) const {183 return __name == __arg.__name;184 }185 186 bool operator!=(const type_info &__arg) const {187 return !operator==(__arg);188 }189 190protected:191 const char *__name;192};193} // namespace std194struct Q {195 virtual ~Q() = default;196};197 198Q q;199Q &evaluated_recursive_function(int x) { // expected-warning{{call itself}}200 (void)typeid(evaluated_recursive_function(x)); // expected-warning {{expression with side effects will be evaluated despite being used as an operand to 'typeid'}}201 return q;202}203 204int unevaluated_recursive_function() {205 (void)typeid(unevaluated_recursive_function());206 return 0;207}208 209void func1(int i) { // expected-warning {{call itself}}210 if (i || !i)211 func1(i);212}213void func2(int i) { // expected-warning {{call itself}}214 if (!i && i) {}215 else216 func2(i);217}218