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 // Don't warn on infinite loops 33 void g() { 34 while (true) 35 g(); 36 37 g(); 38 } 39 40 void h(int x) { 41 while (x < 5) { 42 h(x+1); 43 } 44 } 45 46 void i(int x) { // expected-warning{{call itself}} 47 while (x < 5) { 48 --x; 49 } 50 i(0); 51 } 52 53 int j() { // expected-warning{{call itself}} 54 return 5 + j(); 55 } 56 57 class S { 58 static void a(); 59 void b(); 60 }; 61 62 void S::a() { // expected-warning{{call itself}} 63 return a(); 64 } 65 66 void S::b() { // expected-warning{{call itself}} 67 int i = 0; 68 do { 69 ++i; 70 b(); 71 } while (i > 5); 72 } 73 74 template<class member> 75 struct 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 81 void test_T() { 82 T<int> foo; 83 foo.a(); // expected-note{{in instantiation}} 84 foo.b(); // expected-note{{in instantiation}} 85 } 86 87 class 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. 96 template <int value> 97 int sum() { 98 return value + sum<value/2>(); 99 } 100 101 template<> 102 int sum<1>() { return 1; } 103 104 template<int x, int y> 105 int 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 112 int value = calculate_value<1,1>(); 113 114 void DoSomethingHere(); 115 116 // DoStuff<0,0>() is instantiated, but never called. 117 template<int First, int Last> 118 int 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 } 129 int stuff = DoStuff<0, 1>(); 130 131 template<int x> 132 struct 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 144 template <int x> 145 int test_wrapper() { 146 if (x != 0) 147 return Wrapper<x>::run() + 148 Wrapper<x>::run2(); // expected-note{{instantiation}} 149 return 0; 150 } 151 152 int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} 153