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
52void 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
61void 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
70void 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.
82void isUnreachable();
83
84template <typename T> void test_unreachable_templates() {
85  T::foo();
86  isUnreachable();  // no-warning
87}
88
89struct TestUnreachableA {
90  static void foo() __attribute__((noreturn));
91};
92struct TestUnreachableB {
93  static void foo();
94};
95
96void 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
104template <typename T> void funcToSpecialize() {}
105template <> void funcToSpecialize<int>() {
106  halt();
107  dead(); // expected-warning {{will never be executed}}
108}
109
110// Handle 'try' code dominating a dead return.
111enum PR19040_test_return_t
112{ PR19040_TEST_FAILURE };
113namespace PR19040_libtest
114{
115  class A {
116  public:
117    ~A ();
118  };
119}
120PR19040_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))
133void raze();
134
135namespace std {
136template<typename T> struct basic_string {
137  basic_string(const T* x) {}
138  ~basic_string() {};
139};
140typedef basic_string<char> string;
141}
142
143std::string testStr() {
144  raze();
145  return ""; // expected-warning {{'return' will never be executed}}
146}
147
148std::string testStrWarn(const char *s) {
149  raze();
150  return s; // expected-warning {{will never be executed}}
151}
152
153bool testBool() {
154  raze();
155  return true; // expected-warning {{'return' will never be executed}}
156}
157
158static const bool ConditionVar = 1;
159int test_global_as_conditionVariable() {
160  if (ConditionVar)
161    return 1;
162  return 0; // no-warning
163}
164
165// Handle unreachable temporary destructors.
166class A {
167public:
168  A();
169  ~A();
170};
171
172__attribute__((noreturn))
173void raze(const A& x);
174
175void test_with_unreachable_tmp_dtors(int x) {
176  raze(x ? A() : A()); // no-warning
177}
178
179// Test sizeof - sizeof in enum declaration.
180enum { BrownCow = sizeof(long) - sizeof(char) };
181enum { CowBrown = 8 - 1 };
182
183
184int test_enum_sizeof_arithmetic() {
185  if (BrownCow)
186    return 1;
187  return 2;
188}
189
190int test_enum_arithmetic() {
191  if (CowBrown)
192    return 1;
193  return 2; // expected-warning {{never be executed}}
194}
195
196int test_arithmetic() {
197  if (8 -1)
198    return 1;
199  return 2; // expected-warning {{never be executed}}
200}
201
202int 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
210int 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
221void 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
229class Frobozz {
230public:
231  Frobozz(int x);
232  ~Frobozz();
233};
234
235Frobozz test_return_object(int flag) {
236  return Frobozz(flag);
237  return Frobozz(42);  // expected-warning {{'return' will never be executed}}
238}
239
240Frobozz 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
245void somethingToCall();
246
247static constexpr bool isConstExprConfigValue() { return true; }
248
249int test_const_expr_config_value() {
250 if (isConstExprConfigValue()) {
251   somethingToCall();
252   return 0;
253 }
254 somethingToCall(); // no-warning
255 return 1;
256}
257int test_const_expr_config_value_2() {
258 if (!isConstExprConfigValue()) {
259   somethingToCall(); // no-warning
260   return 0;
261 }
262 somethingToCall();
263 return 1;
264}
265
266class Frodo {
267public:
268  static const bool aHobbit = true;
269};
270
271void test_static_class_var() {
272  if (Frodo::aHobbit)
273    somethingToCall();
274  else
275    somethingToCall(); // no-warning
276}
277
278void test_static_class_var(Frodo &F) {
279  if (F.aHobbit)
280    somethingToCall();
281  else
282    somethingToCall(); // no-warning
283}
284
285void test_unreachable_for_null_increment() {
286  for (unsigned i = 0; i < 10 ; ) // no-warning
287    break;
288}
289
290void 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
297void calledFun() {}
298
299// Test "silencing" with parentheses.
300void 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
330void 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
360void 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