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