]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/SemaCXX/warn-infinite-recursion.cpp
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):
[FreeBSD/FreeBSD.git] / test / SemaCXX / warn-infinite-recursion.cpp
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}}