Clang Project

clang_source_code/test/SemaCXX/warn-unreachable.cpp
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
3int &halt() __attribute__((noreturn));
4int &live();
5int dead();
6int liveti() throw(int);
7int (*livetip)() throw(int);
8
9int test1() {
10  try {
11    live();
12  } catch (int i) {
13    live();
14  }
15  return 1;
16}
17
18void 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
39void 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
52namespace Test4 {
53  struct S {
54    int mem;
55  } s;
56  S &foor();
57  void test4() {
58    halt(), foor()// expected-warning {{will never be executed}}
59      .mem;       
60  }
61}
62
63namespace Test5 {
64  struct S {
65    int mem;
66  } s;
67  S &foonr() __attribute__((noreturn));
68  void test5() {
69    foonr()
70      .mem;       // expected-warning {{will never be executed}}
71  }
72}
73
74void 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.
86void isUnreachable();
87
88template <typename T> void test_unreachable_templates() {
89  T::foo();
90  isUnreachable();  // no-warning
91}
92
93struct TestUnreachableA {
94  static void foo() __attribute__((noreturn));
95};
96struct TestUnreachableB {
97  static void foo();
98};
99
100void 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
108template <typename T> void funcToSpecialize() {}
109template <> void funcToSpecialize<int>() {
110  halt();
111  dead(); // expected-warning {{will never be executed}}
112}
113
114// Handle 'try' code dominating a dead return.
115enum PR19040_test_return_t
116{ PR19040_TEST_FAILURE };
117namespace PR19040_libtest
118{
119  class A {
120  public:
121    ~A ();
122  };
123}
124PR19040_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))
137void raze();
138
139namespace std {
140template<typename T> struct basic_string {
141  basic_string(const T* x) {}
142  ~basic_string() {};
143};
144typedef basic_string<char> string;
145}
146
147std::string testStr() {
148  raze();
149  return ""; // expected-warning {{'return' will never be executed}}
150}
151
152std::string testStrWarn(const char *s) {
153  raze();
154  return s; // expected-warning {{will never be executed}}
155}
156
157bool testBool() {
158  raze();
159  return true; // expected-warning {{'return' will never be executed}}
160}
161
162static const bool ConditionVar = 1;
163int test_global_as_conditionVariable() {
164  if (ConditionVar)
165    return 1;
166  return 0; // no-warning
167}
168
169// Handle unreachable temporary destructors.
170class A {
171public:
172  A();
173  ~A();
174};
175
176__attribute__((noreturn))
177void raze(const A& x);
178
179void test_with_unreachable_tmp_dtors(int x) {
180  raze(x ? A() : A()); // no-warning
181}
182
183// Test sizeof - sizeof in enum declaration.
184enum { BrownCow = sizeof(long) - sizeof(char) };
185enum { CowBrown = 8 - 1 };
186
187
188int test_enum_sizeof_arithmetic() {
189  if (BrownCow)
190    return 1;
191  return 2;
192}
193
194int test_enum_arithmetic() {
195  if (CowBrown)
196    return 1;
197  return 2; // expected-warning {{never be executed}}
198}
199
200int test_arithmetic() {
201  if (8 -1)
202    return 1;
203  return 2; // expected-warning {{never be executed}}
204}
205
206int 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
214int 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
225void 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
233class Frobozz {
234public:
235  Frobozz(int x);
236  ~Frobozz();
237};
238
239Frobozz test_return_object(int flag) {
240  return Frobozz(flag);
241  return Frobozz(42);  // expected-warning {{'return' will never be executed}}
242}
243
244Frobozz 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
249void somethingToCall();
250
251static constexpr bool isConstExprConfigValue() { return true; }
252
253int test_const_expr_config_value() {
254 if (isConstExprConfigValue()) {
255   somethingToCall();
256   return 0;
257 }
258 somethingToCall(); // no-warning
259 return 1;
260}
261int test_const_expr_config_value_2() {
262 if (!isConstExprConfigValue()) {
263   somethingToCall(); // no-warning
264   return 0;
265 }
266 somethingToCall();
267 return 1;
268}
269
270class Frodo {
271public:
272  static const bool aHobbit = true;
273};
274
275void test_static_class_var() {
276  if (Frodo::aHobbit)
277    somethingToCall();
278  else
279    somethingToCall(); // no-warning
280}
281
282void test_static_class_var(Frodo &F) {
283  if (F.aHobbit)
284    somethingToCall();
285  else
286    somethingToCall(); // no-warning
287}
288
289void test_unreachable_for_null_increment() {
290  for (unsigned i = 0; i < 10 ; ) // no-warning
291    break;
292}
293
294void 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
301void calledFun() {}
302
303// Test "silencing" with parentheses.
304void 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
334void 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
364void 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  // TODO: Extend warning to the following code:
397  if (x < -1)
398    calledFun();
399  if (x == -1)
400    calledFun();
401
402  if (x != -1)
403    calledFun();
404  else
405    calledFun();
406  if (-1 > x)
407    calledFun();
408  else
409    calledFun();
410
411  if (y == -1 && y != -1)
412    calledFun();
413}
414