diff options
Diffstat (limited to 'test/SemaCXX/warn-infinite-recursion.cpp')
-rw-r--r-- | test/SemaCXX/warn-infinite-recursion.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/test/SemaCXX/warn-infinite-recursion.cpp b/test/SemaCXX/warn-infinite-recursion.cpp new file mode 100644 index 0000000..e1b7c54 --- /dev/null +++ b/test/SemaCXX/warn-infinite-recursion.cpp @@ -0,0 +1,152 @@ +// 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(); } + +// Don't warn on infinite loops +void g() { + 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(); +} + +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<class member> +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<int> 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 value> +int sum() { + return value + sum<value/2>(); +} + +template<> +int sum<1>() { return 1; } + +template<int x, int y> +int calculate_value() { + if (x != y) + return sum<x - y>(); // 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 First, int Last> +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<First, (First + Last)/2>(); + DoStuff<(First + Last)/2, Last>(); + } + return 0; +} +int stuff = DoStuff<0, 1>(); + +template<int x> +struct Wrapper { + static int run() { + // Similar to the above, Wrapper<0>::run() will discard the if statement. + if (x == 1) + return 0; + return Wrapper<x/2>::run(); + } + static int run2() { // expected-warning{{call itself}} + return run2(); + } +}; + +template <int x> +int test_wrapper() { + if (x != 0) + return Wrapper<x>::run() + + Wrapper<x>::run2(); // expected-note{{instantiation}} + return 0; +} + +int wrapper_sum = test_wrapper<2>(); // expected-note{{instantiation}} |