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 9 int test1() { 10 try { 11 live(); 12 } catch (int i) { 13 live(); 14 } 15 return 1; 16 } 17 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 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 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 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 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 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 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 104 template <typename T> void 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 } 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 { 137 basic_string(const T* x) {} 138 ~basic_string() {}; 139 }; 140 typedef basic_string<char> string; 141 } 142 143 std::string testStr() { 144 raze(); 145 return ""; // expected-warning {{'return' will never be executed}} 146 } 147 148 std::string testStrWarn(const char *s) { 149 raze(); 150 return s; // expected-warning {{will never be executed}} 151 } 152 153 bool testBool() { 154 raze(); 155 return true; // expected-warning {{'return' will never be executed}} 156 } 157 158 static const bool ConditionVar = 1; 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 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 184 int test_enum_sizeof_arithmetic() { 185 if (BrownCow) 186 return 1; 187 return 2; 188 } 189 190 int test_enum_arithmetic() { 191 if (CowBrown) 192 return 1; 193 return 2; // expected-warning {{never be executed}} 194 } 195 196 int test_arithmetic() { 197 if (8 -1) 198 return 1; 199 return 2; // expected-warning {{never be executed}} 200 } 201 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 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 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 235 Frobozz test_return_object(int flag) { 236 return Frobozz(flag); 237 return Frobozz(42); // expected-warning {{'return' will never be executed}} 238 } 239 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 247 static constexpr bool isConstExprConfigValue() { return true; } 248 249 int test_const_expr_config_value() { 250 if (isConstExprConfigValue()) { 251 somethingToCall(); 252 return 0; 253 } 254 somethingToCall(); // no-warning 255 return 1; 256 } 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 271 void test_static_class_var() { 272 if (Frodo::aHobbit) 273 somethingToCall(); 274 else 275 somethingToCall(); // no-warning 276 } 277 278 void test_static_class_var(Frodo &F) { 279 if (F.aHobbit) 280 somethingToCall(); 281 else 282 somethingToCall(); // no-warning 283 } 284 285 void test_unreachable_for_null_increment() { 286 for (unsigned i = 0; i < 10 ; ) // no-warning 287 break; 288 } 289 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 297 void calledFun() {} 298 299 // Test "silencing" with parentheses. 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 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 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