diff options
Diffstat (limited to 'test/SemaCXX/warn-unreachable.cpp')
-rw-r--r-- | test/SemaCXX/warn-unreachable.cpp | 302 |
1 files changed, 301 insertions, 1 deletions
diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index dd071258e29d..b08467ab51e6 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -Wunreachable-code -Wno-unused-value +// 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(); @@ -107,3 +107,303 @@ template <> void funcToSpecialize<int>() { 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(); +} |