| // RUN: %clang_cc1 %s -fsyntax-only -verify -fblocks -Wunreachable-code-aggressive -Wno-unused-value -Wno-covered-switch-default -I %S/Inputs |
| |
| #include "warn-unreachable.h" |
| |
| int halt() __attribute__((noreturn)); |
| int live(); |
| int dead(); |
| |
| void test1() { |
| goto c; |
| d: |
| goto e; // expected-warning {{will never be executed}} |
| c: ; |
| int i; |
| return; |
| goto b; // expected-warning {{will never be executed}} |
| goto a; // expected-warning {{will never be executed}} |
| b: |
| i = 1; |
| a: |
| i = 2; |
| goto f; |
| e: |
| goto d; |
| f: ; |
| } |
| |
| void test2() { |
| int i; |
| switch (live()) { |
| case 1: |
| halt(), |
| dead(); // expected-warning {{will never be executed}} |
| |
| case 2: |
| live(), halt(), |
| dead(); // expected-warning {{will never be executed}} |
| |
| case 3: |
| live() |
| + // expected-warning {{will never be executed}} |
| halt(); |
| dead(); |
| |
| case 4: |
| a4: |
| live(), |
| halt(); |
| goto a4; // expected-warning {{will never be executed}} |
| |
| case 5: |
| goto a5; |
| c5: |
| dead(); // expected-warning {{will never be executed}} |
| goto b5; |
| a5: |
| live(), |
| halt(); |
| b5: |
| goto c5; |
| |
| case 6: |
| if (live()) |
| goto e6; |
| live(), |
| halt(); |
| d6: |
| dead(); // expected-warning {{will never be executed}} |
| goto b6; |
| c6: |
| dead(); |
| goto b6; |
| e6: |
| live(), |
| halt(); |
| b6: |
| goto c6; |
| case 7: |
| halt() |
| + |
| dead(); // expected-warning {{will never be executed}} |
| - // expected-warning {{will never be executed}} |
| halt(); |
| case 8: |
| i |
| += // expected-warning {{will never be executed}} |
| halt(); |
| case 9: |
| halt() |
| ? // expected-warning {{will never be executed}} |
| dead() : dead(); |
| case 10: |
| ( // expected-warning {{will never be executed}} |
| float)halt(); |
| case 11: { |
| int a[5]; |
| live(), |
| a[halt() |
| ]; // expected-warning {{will never be executed}} |
| } |
| } |
| } |
| |
| enum Cases { C1, C2, C3 }; |
| int test_enum_cases(enum Cases C) { |
| switch (C) { |
| case C1: |
| case C2: |
| case C3: |
| return 1; |
| default: { |
| int i = 0; // no-warning |
| ++i; |
| return i; |
| } |
| } |
| } |
| |
| // Handle unreachable code triggered by macro expansions. |
| void __myassert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__)); |
| |
| #define myassert(e) \ |
| (__builtin_expect(!(e), 0) ? __myassert_rtn(__func__, __FILE__, __LINE__, #e) : (void)0) |
| |
| void test_assert() { |
| myassert(0 && "unreachable"); |
| return; // no-warning |
| } |
| |
| // Test case for PR 9774. Tests that dead code in macros aren't warned about. |
| #define MY_MAX(a,b) ((a) >= (b) ? (a) : (b)) |
| void PR9774(int *s) { |
| for (int i = 0; i < MY_MAX(2, 3); i++) // no-warning |
| s[i] = 0; |
| } |
| |
| // Test case for <rdar://problem/11005770>. We should treat code guarded |
| // by 'x & 0' and 'x * 0' as unreachable. |
| int calledFun(); |
| void test_mul_and_zero(int x) { |
| if (x & 0) calledFun(); // expected-warning {{will never be executed}} |
| if (0 & x) calledFun(); // expected-warning {{will never be executed}} |
| if (x * 0) calledFun(); // expected-warning {{will never be executed}} |
| if (0 * x) calledFun(); // expected-warning {{will never be executed}} |
| } |
| |
| void raze() __attribute__((noreturn)); |
| void warn_here(); |
| |
| int test_break_preceded_by_noreturn(int i) { |
| switch (i) { |
| case 1: |
| raze(); |
| break; // expected-warning {{'break' will never be executed}} |
| case 2: |
| raze(); |
| break; // expected-warning {{'break' will never be executed}} |
| warn_here(); // expected-warning {{will never be executed}} |
| case 3: |
| return 1; |
| break; // expected-warning {{will never be executed}} |
| default: |
| break; |
| break; // expected-warning {{will never be executed}} |
| } |
| return i; |
| } |
| |
| // Don't warn about unreachable 'default' cases, as that is covered |
| // by -Wcovered-switch-default. |
| typedef enum { Value1 = 1 } MyEnum; |
| void unreachable_default(MyEnum e) { |
| switch (e) { |
| case Value1: |
| calledFun(); |
| break; |
| case 2: // expected-warning {{case value not in enumerated type 'MyEnum'}} |
| calledFun(); |
| break; |
| default: |
| calledFun(); // no-warning |
| break; |
| } |
| } |
| void unreachable_in_default(MyEnum e) { |
| switch (e) { |
| default: |
| raze(); |
| calledFun(); // expected-warning {{will never be executed}} |
| break; |
| } |
| } |
| |
| // Don't warn about trivial dead returns. |
| int trivial_dead_return() { |
| raze(); |
| return ((0)); // expected-warning {{'return' will never be executed}} |
| } |
| |
| void trivial_dead_return_void() { |
| raze(); |
| return; // expected-warning {{'return' will never be executed}} |
| } |
| |
| MyEnum trivial_dead_return_enum() { |
| raze(); |
| return Value1; // expected-warning {{'return' will never be executed}} |
| } |
| |
| MyEnum trivial_dead_return_enum_2(int x) { |
| switch (x) { |
| case 1: return 1; |
| case 2: return 2; |
| case 3: return 3; |
| default: return 4; |
| } |
| |
| return 2; // expected-warning {{will never be executed}} |
| } |
| |
| const char *trivial_dead_return_cstr() { |
| raze(); |
| return ""; // expected-warning {{return' will never be executed}} |
| } |
| |
| char trivial_dead_return_char() { |
| raze(); |
| return ' '; // expected-warning {{return' will never be executed}} |
| } |
| |
| MyEnum nontrivial_dead_return_enum_2(int x) { |
| switch (x) { |
| case 1: return 1; |
| case 2: return 2; |
| case 3: return 3; |
| default: return 4; |
| } |
| |
| return calledFun(); // expected-warning {{will never be executed}} |
| } |
| |
| enum X { A, B, C }; |
| |
| int covered_switch(enum X x) { |
| switch (x) { |
| case A: return 1; |
| case B: return 2; |
| case C: return 3; |
| } |
| return 4; // no-warning |
| } |
| |
| // Test unreachable code depending on configuration values |
| #define CONFIG_CONSTANT 1 |
| int test_config_constant(int x) { |
| if (!CONFIG_CONSTANT) { |
| calledFun(); // no-warning |
| return 1; |
| } |
| if (!1) { // expected-note {{silence by adding parentheses to mark code as explicitly dead}} |
| calledFun(); // expected-warning {{will never be executed}} |
| return 1; |
| } |
| if (sizeof(int) > sizeof(char)) { |
| calledFun(); // no-warning |
| return 1; |
| } |
| if (x > 10) |
| return CONFIG_CONSTANT ? calledFun() : calledFun(); // no-warning |
| else |
| return 1 ? // expected-note {{silence by adding parentheses to mark code as explicitly dead}} |
| calledFun() : |
| calledFun(); // expected-warning {{will never be executed}} |
| } |
| |
| int sizeof_int(int x, int y) { |
| if (sizeof(long) == sizeof(int)) |
| return 1; // no-warning |
| if (sizeof(long) != sizeof(int)) |
| return 0; // no-warning |
| if (x && y && sizeof(long) < sizeof(char)) |
| return 0; // no-warning |
| return 2; // no-warning |
| } |
| |
| enum MyEnum2 { |
| ME_A = CONFIG_CONSTANT, |
| ME_B = 1 |
| }; |
| |
| int test_MyEnum() { |
| if (!ME_A) |
| return 1; // no-warning |
| if (ME_A) |
| return 2; // no-warning |
| if (ME_B) |
| return 3; |
| if (!ME_B) // expected-warning {{will never be executed}} |
| return 4; // expected-warning {{will never be executed}} |
| return 5; |
| } |
| |
| // Test for idiomatic do..while. |
| int test_do_while(int x) { |
| do { |
| if (x == calledFun()) |
| break; |
| ++x; |
| break; |
| } |
| while (0); // no-warning |
| return x; |
| } |
| |
| int test_do_while_nontrivial_cond(int x) { |
| do { |
| if (x == calledFun()) |
| break; |
| ++x; |
| break; |
| } |
| while (calledFun()); // expected-warning {{will never be executed}} |
| return x; |
| } |
| |
| // Diagnostic control: -Wunreachable-code-return. |
| |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wunreachable-code-return" |
| |
| void trivial_dead_return_void_SUPPRESSED() { |
| raze(); |
| return; // no-warning |
| } |
| |
| MyEnum trivial_dead_return_enum_SUPPRESSED() { |
| raze(); |
| return Value1; // no-warning |
| } |
| |
| #pragma clang diagnostic pop |
| |
| // Diagnostic control: -Wunreachable-code-break. |
| |
| #pragma clang diagnostic push |
| #pragma clang diagnostic ignored "-Wunreachable-code-break" |
| |
| int test_break_preceded_by_noreturn_SUPPRESSED(int i) { |
| switch (i) { |
| case 1: |
| raze(); |
| break; // no-warning |
| case 2: |
| raze(); |
| break; // no-warning |
| warn_here(); // expected-warning {{will never be executed}} |
| case 3: |
| return 1; |
| break; // no-warning |
| default: |
| break; |
| break; // no-warning |
| } |
| return i; |
| } |
| |
| #pragma clang diagnostic pop |
| |
| // Test "silencing" with parentheses. |
| void test_with_paren_silencing(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(); |
| } |