aboutsummaryrefslogtreecommitdiff
path: root/test/SemaCXX/warn-unreachable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX/warn-unreachable.cpp')
-rw-r--r--test/SemaCXX/warn-unreachable.cpp302
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();
+}