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