Home | History | Annotate | Download | only in SemaCXX
      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