| // RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -std=c++11 -Wunreachable-code-aggressive -Wno-unused-value -Wno-tautological-compare | 
 |  | 
 | int &halt() __attribute__((noreturn)); | 
 | int &live(); | 
 | int dead(); | 
 | int liveti() throw(int); | 
 | int (*livetip)() throw(int); | 
 |  | 
 | int test1() { | 
 |   try { | 
 |     live(); | 
 |   } catch (int i) { | 
 |     live(); | 
 |   } | 
 |   return 1; | 
 | } | 
 |  | 
 | void test2() { | 
 |   try { | 
 |     live(); | 
 |   } catch (int i) { | 
 |     live(); | 
 |   } | 
 |   try { | 
 |     liveti(); | 
 |   } catch (int i) { | 
 |     live(); | 
 |   } | 
 |   try { | 
 |     livetip(); | 
 |   } catch (int i) { | 
 |     live(); | 
 |   } | 
 |   throw 1; | 
 |   dead();       // expected-warning {{will never be executed}} | 
 | } | 
 |  | 
 |  | 
 | void test3() { | 
 |   halt() | 
 |     --;         // expected-warning {{will never be executed}} | 
 |   // FIXME: The unreachable part is just the '?', but really all of this | 
 |   // code is unreachable and shouldn't be separately reported. | 
 |   halt()        // expected-warning {{will never be executed}} | 
 |     ?  | 
 |     dead() : dead(); | 
 |   live(), | 
 |     float        | 
 |       (halt()); // expected-warning {{will never be executed}} | 
 | } | 
 |  | 
 | namespace Test4 { | 
 |   struct S { | 
 |     int mem; | 
 |   } s; | 
 |   S &foor(); | 
 |   void test4() { | 
 |     halt(), foor()// expected-warning {{will never be executed}} | 
 |       .mem;        | 
 |   } | 
 | } | 
 |  | 
 | namespace Test5 { | 
 |   struct S { | 
 |     int mem; | 
 |   } s; | 
 |   S &foonr() __attribute__((noreturn)); | 
 |   void test5() { | 
 |     foonr() | 
 |       .mem;       // expected-warning {{will never be executed}} | 
 |   } | 
 | } | 
 |  | 
 | void test6() { | 
 |   struct S { | 
 |     ~S() { } | 
 |     S(int i) { } | 
 |   }; | 
 |   live(), | 
 |     S | 
 |       (halt());  // expected-warning {{will never be executed}} | 
 | } | 
 |  | 
 | // Don't warn about unreachable code in template instantiations, as | 
 | // they may only be unreachable in that specific instantiation. | 
 | void isUnreachable(); | 
 |  | 
 | template <typename T> void test_unreachable_templates() { | 
 |   T::foo(); | 
 |   isUnreachable();  // no-warning | 
 | } | 
 |  | 
 | struct TestUnreachableA { | 
 |   static void foo() __attribute__((noreturn)); | 
 | }; | 
 | struct TestUnreachableB { | 
 |   static void foo(); | 
 | }; | 
 |  | 
 | void test_unreachable_templates_harness() { | 
 |   test_unreachable_templates<TestUnreachableA>(); | 
 |   test_unreachable_templates<TestUnreachableB>();  | 
 | } | 
 |  | 
 | // Do warn about explicit template specializations, as they represent | 
 | // actual concrete functions that somebody wrote. | 
 |  | 
 | template <typename T> void funcToSpecialize() {} | 
 | template <> void funcToSpecialize<int>() { | 
 |   halt(); | 
 |   dead(); // expected-warning {{will never be executed}} | 
 | } | 
 |  | 
 | // Handle 'try' code dominating a dead return. | 
 | enum PR19040_test_return_t | 
 | { PR19040_TEST_FAILURE }; | 
 | namespace PR19040_libtest | 
 | { | 
 |   class A { | 
 |   public: | 
 |     ~A (); | 
 |   }; | 
 | } | 
 | PR19040_test_return_t PR19040_fn1 () | 
 | { | 
 |     try | 
 |     { | 
 |         throw PR19040_libtest::A (); | 
 |     } catch (...) | 
 |     { | 
 |         return PR19040_TEST_FAILURE; | 
 |     } | 
 |     return PR19040_TEST_FAILURE; // expected-warning {{will never be executed}} | 
 | } | 
 |  | 
 | __attribute__((noreturn)) | 
 | void raze(); | 
 |  | 
 | namespace std { | 
 | template<typename T> struct basic_string { | 
 |   basic_string(const T* x) {} | 
 |   ~basic_string() {}; | 
 | }; | 
 | typedef basic_string<char> string; | 
 | } | 
 |  | 
 | std::string testStr() { | 
 |   raze(); | 
 |   return ""; // expected-warning {{'return' will never be executed}} | 
 | } | 
 |  | 
 | std::string testStrWarn(const char *s) { | 
 |   raze(); | 
 |   return s; // expected-warning {{will never be executed}} | 
 | } | 
 |  | 
 | bool testBool() { | 
 |   raze(); | 
 |   return true; // expected-warning {{'return' will never be executed}} | 
 | } | 
 |  | 
 | static const bool ConditionVar = 1; | 
 | int test_global_as_conditionVariable() { | 
 |   if (ConditionVar) | 
 |     return 1; | 
 |   return 0; // no-warning | 
 | } | 
 |  | 
 | // Handle unreachable temporary destructors. | 
 | class A { | 
 | public: | 
 |   A(); | 
 |   ~A(); | 
 | }; | 
 |  | 
 | __attribute__((noreturn)) | 
 | void raze(const A& x); | 
 |  | 
 | void test_with_unreachable_tmp_dtors(int x) { | 
 |   raze(x ? A() : A()); // no-warning | 
 | } | 
 |  | 
 | // Test sizeof - sizeof in enum declaration. | 
 | enum { BrownCow = sizeof(long) - sizeof(char) }; | 
 | enum { CowBrown = 8 - 1 }; | 
 |  | 
 |  | 
 | int test_enum_sizeof_arithmetic() { | 
 |   if (BrownCow) | 
 |     return 1; | 
 |   return 2; | 
 | } | 
 |  | 
 | int test_enum_arithmetic() { | 
 |   if (CowBrown) | 
 |     return 1; | 
 |   return 2; // expected-warning {{never be executed}} | 
 | } | 
 |  | 
 | int test_arithmetic() { | 
 |   if (8 -1) | 
 |     return 1; | 
 |   return 2; // expected-warning {{never be executed}} | 
 | } | 
 |  | 
 | int test_treat_const_bool_local_as_config_value() { | 
 |   const bool controlValue = false; | 
 |   if (!controlValue) | 
 |     return 1; | 
 |   test_treat_const_bool_local_as_config_value(); // no-warning | 
 |   return 0; | 
 | } | 
 |  | 
 | int test_treat_non_const_bool_local_as_non_config_value() { | 
 |   bool controlValue = false; | 
 |   if (!controlValue) | 
 |     return 1; | 
 |   // There is no warning here because 'controlValue' isn't really | 
 |   // a control value at all.  The CFG will not treat this | 
 |   // branch as unreachable. | 
 |   test_treat_non_const_bool_local_as_non_config_value(); // no-warning | 
 |   return 0; | 
 | } | 
 |  | 
 | void test_do_while(int x) { | 
 |   // Handle trivial expressions with | 
 |   // implicit casts to bool. | 
 |   do { | 
 |     break; | 
 |   } while (0); // no-warning | 
 | } | 
 |  | 
 | class Frobozz { | 
 | public: | 
 |   Frobozz(int x); | 
 |   ~Frobozz(); | 
 | }; | 
 |  | 
 | Frobozz test_return_object(int flag) { | 
 |   return Frobozz(flag); | 
 |   return Frobozz(42);  // expected-warning {{'return' will never be executed}} | 
 | } | 
 |  | 
 | Frobozz test_return_object_control_flow(int flag) { | 
 |   return Frobozz(flag); | 
 |   return Frobozz(flag ? 42 : 24); // expected-warning {{code will never be executed}} | 
 | } | 
 |  | 
 | void somethingToCall(); | 
 |  | 
 | static constexpr bool isConstExprConfigValue() { return true; } | 
 |  | 
 | int test_const_expr_config_value() { | 
 |  if (isConstExprConfigValue()) { | 
 |    somethingToCall(); | 
 |    return 0; | 
 |  } | 
 |  somethingToCall(); // no-warning | 
 |  return 1; | 
 | } | 
 | int test_const_expr_config_value_2() { | 
 |  if (!isConstExprConfigValue()) { | 
 |    somethingToCall(); // no-warning | 
 |    return 0; | 
 |  } | 
 |  somethingToCall(); | 
 |  return 1; | 
 | } | 
 |  | 
 | class Frodo { | 
 | public: | 
 |   static const bool aHobbit = true; | 
 | }; | 
 |  | 
 | void test_static_class_var() { | 
 |   if (Frodo::aHobbit) | 
 |     somethingToCall(); | 
 |   else | 
 |     somethingToCall(); // no-warning | 
 | } | 
 |  | 
 | void test_static_class_var(Frodo &F) { | 
 |   if (F.aHobbit) | 
 |     somethingToCall(); | 
 |   else | 
 |     somethingToCall(); // no-warning | 
 | } | 
 |  | 
 | void test_unreachable_for_null_increment() { | 
 |   for (unsigned i = 0; i < 10 ; ) // no-warning | 
 |     break; | 
 | } | 
 |  | 
 | void test_unreachable_forrange_increment() { | 
 |   int x[10] = { 0 }; | 
 |   for (auto i : x) { // expected-warning {{loop will run at most once (loop increment never executed)}} | 
 |     break; | 
 |   } | 
 | } | 
 |  | 
 | void calledFun() {} | 
 |  | 
 | // Test "silencing" with parentheses. | 
 | void test_with_paren_silencing(int x) { | 
 |   if (false) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}} | 
 |   if ((false)) calledFun(); // no-warning | 
 |  | 
 |   if (true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} | 
 |     calledFun(); | 
 |   else | 
 |     calledFun(); // expected-warning {{will never be executed}} | 
 |  | 
 |   if ((true)) | 
 |     calledFun(); | 
 |   else | 
 |     calledFun(); // no-warning | 
 |    | 
 |   if (!true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} | 
 |     calledFun(); // expected-warning {{code will never be executed}} | 
 |   else | 
 |     calledFun(); | 
 |    | 
 |   if ((!true)) | 
 |     calledFun(); // no-warning | 
 |   else | 
 |     calledFun(); | 
 |    | 
 |   if (!(true)) | 
 |     calledFun(); // no-warning | 
 |   else | 
 |     calledFun(); | 
 | } | 
 |  | 
 | void test_with_paren_silencing_impcast(int x) { | 
 |   if (0) calledFun(); // expected-warning {{will never be executed}} expected-note {{silence by adding parentheses to mark code as explicitly dead}} | 
 |   if ((0)) calledFun(); // no-warning | 
 |  | 
 |   if (1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} | 
 |     calledFun(); | 
 |   else | 
 |     calledFun(); // expected-warning {{will never be executed}} | 
 |  | 
 |   if ((1)) | 
 |     calledFun(); | 
 |   else | 
 |     calledFun(); // no-warning | 
 |    | 
 |   if (!1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}} | 
 |     calledFun(); // expected-warning {{code will never be executed}} | 
 |   else | 
 |     calledFun(); | 
 |    | 
 |   if ((!1)) | 
 |     calledFun(); // no-warning | 
 |   else | 
 |     calledFun(); | 
 |    | 
 |   if (!(1)) | 
 |     calledFun(); // no-warning | 
 |   else | 
 |     calledFun(); | 
 | } | 
 |  | 
 | void tautological_compare(bool x, int y) { | 
 |   if (x > 10)           // expected-note {{silence}} | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |   if (10 < x)           // expected-note {{silence}} | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |   if (x == 10)          // expected-note {{silence}} | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |  | 
 |   if (x < 10)           // expected-note {{silence}} | 
 |     calledFun(); | 
 |   else | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |   if (10 > x)           // expected-note {{silence}} | 
 |     calledFun(); | 
 |   else | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |   if (x != 10)          // expected-note {{silence}} | 
 |     calledFun(); | 
 |   else | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |  | 
 |   if (y != 5 && y == 5) // expected-note {{silence}} | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |  | 
 |   if (y > 5 && y < 4)   // expected-note {{silence}} | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |  | 
 |   if (y < 10 || y > 5)  // expected-note {{silence}} | 
 |     calledFun(); | 
 |   else | 
 |     calledFun();        // expected-warning {{will never be executed}} | 
 |  | 
 |   // TODO: Extend warning to the following code: | 
 |   if (x < -1) | 
 |     calledFun(); | 
 |   if (x == -1) | 
 |     calledFun(); | 
 |  | 
 |   if (x != -1) | 
 |     calledFun(); | 
 |   else | 
 |     calledFun(); | 
 |   if (-1 > x) | 
 |     calledFun(); | 
 |   else | 
 |     calledFun(); | 
 |  | 
 |   if (y == -1 && y != -1) | 
 |     calledFun(); | 
 | } |