diff options
Diffstat (limited to 'test/Sema/warn-unreachable.c')
-rw-r--r-- | test/Sema/warn-unreachable.c | 261 |
1 files changed, 258 insertions, 3 deletions
diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c index fd74b5c87175..31beff9cf1e0 100644 --- a/test/Sema/warn-unreachable.c +++ b/test/Sema/warn-unreachable.c @@ -1,4 +1,6 @@ -// RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code -Wno-unused-value -Wno-covered-switch-default +// 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(); @@ -107,7 +109,7 @@ int test_enum_cases(enum Cases C) { case C3: return 1; default: { - int i = 0; // expected-warning{{will never be executed}} + int i = 0; // no-warning ++i; return i; } @@ -134,10 +136,263 @@ void PR9774(int *s) { // Test case for <rdar://problem/11005770>. We should treat code guarded // by 'x & 0' and 'x * 0' as unreachable. -void calledFun(); +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(); +} |