1 // RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -std=c++11 -Wunreachable-code-aggressive -Wno-unused-value -Wno-tautological-compare
2 
3 int &halt() __attribute__((noreturn));
4 int &live();
5 int dead();
6 int liveti() throw(int);
7 int (*livetip)() throw(int);
8 
test1()9 int test1() {
10   try {
11     live();
12   } catch (int i) {
13     live();
14   }
15   return 1;
16 }
17 
test2()18 void test2() {
19   try {
20     live();
21   } catch (int i) {
22     live();
23   }
24   try {
25     liveti();
26   } catch (int i) {
27     live();
28   }
29   try {
30     livetip();
31   } catch (int i) {
32     live();
33   }
34   throw 1;
35   dead();       // expected-warning {{will never be executed}}
36 }
37 
38 
test3()39 void test3() {
40   halt()
41     --;         // expected-warning {{will never be executed}}
42   // FIXME: The unreachable part is just the '?', but really all of this
43   // code is unreachable and shouldn't be separately reported.
44   halt()        // expected-warning {{will never be executed}}
45     ?
46     dead() : dead();
47   live(),
48     float
49       (halt()); // expected-warning {{will never be executed}}
50 }
51 
52 namespace Test4 {
53   struct S {
54     int mem;
55   } s;
56   S &foor();
test4()57   void test4() {
58     halt(), foor()// expected-warning {{will never be executed}}
59       .mem;
60   }
61 }
62 
63 namespace Test5 {
64   struct S {
65     int mem;
66   } s;
67   S &foonr() __attribute__((noreturn));
test5()68   void test5() {
69     foonr()
70       .mem;       // expected-warning {{will never be executed}}
71   }
72 }
73 
test6()74 void test6() {
75   struct S {
76     ~S() { }
77     S(int i) { }
78   };
79   live(),
80     S
81       (halt());  // expected-warning {{will never be executed}}
82 }
83 
84 // Don't warn about unreachable code in template instantiations, as
85 // they may only be unreachable in that specific instantiation.
86 void isUnreachable();
87 
test_unreachable_templates()88 template <typename T> void test_unreachable_templates() {
89   T::foo();
90   isUnreachable();  // no-warning
91 }
92 
93 struct TestUnreachableA {
94   static void foo() __attribute__((noreturn));
95 };
96 struct TestUnreachableB {
97   static void foo();
98 };
99 
test_unreachable_templates_harness()100 void test_unreachable_templates_harness() {
101   test_unreachable_templates<TestUnreachableA>();
102   test_unreachable_templates<TestUnreachableB>();
103 }
104 
105 // Do warn about explicit template specializations, as they represent
106 // actual concrete functions that somebody wrote.
107 
funcToSpecialize()108 template <typename T> void funcToSpecialize() {}
funcToSpecialize()109 template <> void funcToSpecialize<int>() {
110   halt();
111   dead(); // expected-warning {{will never be executed}}
112 }
113 
114 // Handle 'try' code dominating a dead return.
115 enum PR19040_test_return_t
116 { PR19040_TEST_FAILURE };
117 namespace PR19040_libtest
118 {
119   class A {
120   public:
121     ~A ();
122   };
123 }
PR19040_fn1()124 PR19040_test_return_t PR19040_fn1 ()
125 {
126     try
127     {
128         throw PR19040_libtest::A ();
129     } catch (...)
130     {
131         return PR19040_TEST_FAILURE;
132     }
133     return PR19040_TEST_FAILURE; // expected-warning {{will never be executed}}
134 }
135 
136 __attribute__((noreturn))
137 void raze();
138 
139 namespace std {
140 template<typename T> struct basic_string {
basic_stringstd::basic_string141   basic_string(const T* x) {}
~basic_stringstd::basic_string142   ~basic_string() {};
143 };
144 typedef basic_string<char> string;
145 }
146 
testStr()147 std::string testStr() {
148   raze();
149   return ""; // expected-warning {{'return' will never be executed}}
150 }
151 
testStrWarn(const char * s)152 std::string testStrWarn(const char *s) {
153   raze();
154   return s; // expected-warning {{will never be executed}}
155 }
156 
testBool()157 bool testBool() {
158   raze();
159   return true; // expected-warning {{'return' will never be executed}}
160 }
161 
162 static const bool ConditionVar = 1;
test_global_as_conditionVariable()163 int test_global_as_conditionVariable() {
164   if (ConditionVar)
165     return 1;
166   return 0; // no-warning
167 }
168 
169 // Handle unreachable temporary destructors.
170 class A {
171 public:
172   A();
173   ~A();
174 };
175 
176 __attribute__((noreturn))
177 void raze(const A& x);
178 
test_with_unreachable_tmp_dtors(int x)179 void test_with_unreachable_tmp_dtors(int x) {
180   raze(x ? A() : A()); // no-warning
181 }
182 
183 // Test sizeof - sizeof in enum declaration.
184 enum { BrownCow = sizeof(long) - sizeof(char) };
185 enum { CowBrown = 8 - 1 };
186 
187 
test_enum_sizeof_arithmetic()188 int test_enum_sizeof_arithmetic() {
189   if (BrownCow)
190     return 1;
191   return 2;
192 }
193 
test_enum_arithmetic()194 int test_enum_arithmetic() {
195   if (CowBrown)
196     return 1;
197   return 2; // expected-warning {{never be executed}}
198 }
199 
test_arithmetic()200 int test_arithmetic() {
201   if (8 -1)
202     return 1;
203   return 2; // expected-warning {{never be executed}}
204 }
205 
test_treat_const_bool_local_as_config_value()206 int test_treat_const_bool_local_as_config_value() {
207   const bool controlValue = false;
208   if (!controlValue)
209     return 1;
210   test_treat_const_bool_local_as_config_value(); // no-warning
211   return 0;
212 }
213 
test_treat_non_const_bool_local_as_non_config_value()214 int test_treat_non_const_bool_local_as_non_config_value() {
215   bool controlValue = false;
216   if (!controlValue)
217     return 1;
218   // There is no warning here because 'controlValue' isn't really
219   // a control value at all.  The CFG will not treat this
220   // branch as unreachable.
221   test_treat_non_const_bool_local_as_non_config_value(); // no-warning
222   return 0;
223 }
224 
test_do_while(int x)225 void test_do_while(int x) {
226   // Handle trivial expressions with
227   // implicit casts to bool.
228   do {
229     break;
230   } while (0); // no-warning
231 }
232 
233 class Frobozz {
234 public:
235   Frobozz(int x);
236   ~Frobozz();
237 };
238 
test_return_object(int flag)239 Frobozz test_return_object(int flag) {
240   return Frobozz(flag);
241   return Frobozz(42);  // expected-warning {{'return' will never be executed}}
242 }
243 
test_return_object_control_flow(int flag)244 Frobozz test_return_object_control_flow(int flag) {
245   return Frobozz(flag);
246   return Frobozz(flag ? 42 : 24); // expected-warning {{code will never be executed}}
247 }
248 
249 void somethingToCall();
250 
isConstExprConfigValue()251 static constexpr bool isConstExprConfigValue() { return true; }
252 
test_const_expr_config_value()253 int test_const_expr_config_value() {
254  if (isConstExprConfigValue()) {
255    somethingToCall();
256    return 0;
257  }
258  somethingToCall(); // no-warning
259  return 1;
260 }
test_const_expr_config_value_2()261 int test_const_expr_config_value_2() {
262  if (!isConstExprConfigValue()) {
263    somethingToCall(); // no-warning
264    return 0;
265  }
266  somethingToCall();
267  return 1;
268 }
269 
270 class Frodo {
271 public:
272   static const bool aHobbit = true;
273 };
274 
test_static_class_var()275 void test_static_class_var() {
276   if (Frodo::aHobbit)
277     somethingToCall();
278   else
279     somethingToCall(); // no-warning
280 }
281 
test_static_class_var(Frodo & F)282 void test_static_class_var(Frodo &F) {
283   if (F.aHobbit)
284     somethingToCall();
285   else
286     somethingToCall(); // no-warning
287 }
288 
test_unreachable_for_null_increment()289 void test_unreachable_for_null_increment() {
290   for (unsigned i = 0; i < 10 ; ) // no-warning
291     break;
292 }
293 
test_unreachable_forrange_increment()294 void test_unreachable_forrange_increment() {
295   int x[10] = { 0 };
296   for (auto i : x) { // expected-warning {{loop will run at most once (loop increment never executed)}}
297     break;
298   }
299 }
300 
calledFun()301 void calledFun() {}
302 
303 // Test "silencing" with parentheses.
test_with_paren_silencing(int x)304 void test_with_paren_silencing(int x) {
305   if (false) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}}
306   if ((false)) calledFun(); // no-warning
307 
308   if (true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
309     calledFun();
310   else
311     calledFun(); // expected-warning {{will never be executed}}
312 
313   if ((true))
314     calledFun();
315   else
316     calledFun(); // no-warning
317 
318   if (!true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
319     calledFun(); // expected-warning {{code will never be executed}}
320   else
321     calledFun();
322 
323   if ((!true))
324     calledFun(); // no-warning
325   else
326     calledFun();
327 
328   if (!(true))
329     calledFun(); // no-warning
330   else
331     calledFun();
332 }
333 
test_with_paren_silencing_impcast(int x)334 void test_with_paren_silencing_impcast(int x) {
335   if (0) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}}
336   if ((0)) calledFun(); // no-warning
337 
338   if (1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
339     calledFun();
340   else
341     calledFun(); // expected-warning {{will never be executed}}
342 
343   if ((1))
344     calledFun();
345   else
346     calledFun(); // no-warning
347 
348   if (!1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
349     calledFun(); // expected-warning {{code will never be executed}}
350   else
351     calledFun();
352 
353   if ((!1))
354     calledFun(); // no-warning
355   else
356     calledFun();
357 
358   if (!(1))
359     calledFun(); // no-warning
360   else
361     calledFun();
362 }
363 
tautological_compare(bool x,int y)364 void tautological_compare(bool x, int y) {
365   if (x > 10)           // expected-note {{silence}}
366     calledFun();        // expected-warning {{will never be executed}}
367   if (10 < x)           // expected-note {{silence}}
368     calledFun();        // expected-warning {{will never be executed}}
369   if (x == 10)          // expected-note {{silence}}
370     calledFun();        // expected-warning {{will never be executed}}
371 
372   if (x < 10)           // expected-note {{silence}}
373     calledFun();
374   else
375     calledFun();        // expected-warning {{will never be executed}}
376   if (10 > x)           // expected-note {{silence}}
377     calledFun();
378   else
379     calledFun();        // expected-warning {{will never be executed}}
380   if (x != 10)          // expected-note {{silence}}
381     calledFun();
382   else
383     calledFun();        // expected-warning {{will never be executed}}
384 
385   if (y != 5 && y == 5) // expected-note {{silence}}
386     calledFun();        // expected-warning {{will never be executed}}
387 
388   if (y > 5 && y < 4)   // expected-note {{silence}}
389     calledFun();        // expected-warning {{will never be executed}}
390 
391   if (y < 10 || y > 5)  // expected-note {{silence}}
392     calledFun();
393   else
394     calledFun();        // expected-warning {{will never be executed}}
395 
396   if (y == -1 && y != -1)  // expected-note {{silence}}
397     calledFun();        // expected-warning {{will never be executed}}
398 
399   // TODO: Extend warning to the following code:
400   if (x < -1)
401     calledFun();
402   if (x == -1)
403     calledFun();
404 
405   if (x != -1)
406     calledFun();
407   else
408     calledFun();
409   if (-1 > x)
410     calledFun();
411   else
412     calledFun();
413 
414 }
415