417 lines · cpp
1// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -std=c++11 -Wunreachable-code-aggressive -Wno-unused-value -Wno-tautological-compare2 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 this43 // 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 S81 (halt()); // expected-warning {{will never be executed}}82}83 84// Don't warn about unreachable code in template instantiations, as85// 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-warning91}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 represent106// 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_t116{ PR19040_TEST_FAILURE };117namespace PR19040_libtest118{119 class A {120 public:121 ~A ();122 };123}124PR19040_test_return_t PR19040_fn1 ()125{126 try127 {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-warning167}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-warning181}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-warning211 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 really219 // a control value at all. The CFG will not treat this220 // branch as unreachable.221 test_treat_non_const_bool_local_as_non_config_value(); // no-warning222 return 0;223}224 225void test_do_while(int x) {226 // Handle trivial expressions with227 // implicit casts to bool.228 do {229 break;230 } while (0); // no-warning231}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-warning259 return 1;260}261int test_const_expr_config_value_2() {262 if (!isConstExprConfigValue()) {263 somethingToCall(); // no-warning264 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 else279 somethingToCall(); // no-warning280}281 282void test_static_class_var(Frodo &F) {283 if (F.aHobbit)284 somethingToCall();285 else286 somethingToCall(); // no-warning287}288 289void test_unreachable_for_null_increment() {290 for (unsigned i = 0; i < 10 ; ) // no-warning291 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-warning307 308 if (true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}309 calledFun();310 else311 calledFun(); // expected-warning {{will never be executed}}312 313 if ((true))314 calledFun();315 else316 calledFun(); // no-warning317 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 else321 calledFun();322 323 if ((!true))324 calledFun(); // no-warning325 else326 calledFun();327 328 if (!(true))329 calledFun(); // no-warning330 else331 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-warning337 338 if (1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}339 calledFun();340 else341 calledFun(); // expected-warning {{will never be executed}}342 343 if ((1))344 calledFun();345 else346 calledFun(); // no-warning347 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 else351 calledFun();352 353 if ((!1))354 calledFun(); // no-warning355 else356 calledFun();357 358 if (!(1))359 calledFun(); // no-warning360 else361 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 else375 calledFun(); // expected-warning {{will never be executed}}376 if (10 > x) // expected-note {{silence}}377 calledFun();378 else379 calledFun(); // expected-warning {{will never be executed}}380 if (x != 10) // expected-note {{silence}}381 calledFun();382 else383 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 else394 calledFun(); // expected-warning {{will never be executed}}395 396 if (y == -1 && y != -1) // expected-note {{silence}}397 calledFun(); // expected-warning {{will never be executed}}398 399 if (x == -1) // expected-note {{silence}}400 calledFun(); // expected-warning {{will never be executed}}401 402 if (x != -1) // expected-note {{silence}}403 calledFun();404 else405 calledFun(); // expected-warning {{will never be executed}}406 407 // TODO: Extend warning to the following code:408 if (x < -1)409 calledFun();410 411 if (-1 > x)412 calledFun();413 else414 calledFun();415 416}417