llvm-project/clang/test/Sema/warn-unreachable.c

505 lines
13 KiB
C

// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -Wunreachable-code-aggressive -Wno-unused-value -Wno-covered-switch-default -I %S/Inputs %s
// RUN: %clang_cc1 -fsyntax-only -fblocks -Wunreachable-code-aggressive -Wno-unused-value -Wno-covered-switch-default -fdiagnostics-parseable-fixits -I %S/Inputs %s 2>&1 | FileCheck %s
#include "warn-unreachable.h"
int halt(void) __attribute__((noreturn));
int live(void);
int dead(void);
void test1(void) {
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(void) {
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(void) {
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);
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(void) __attribute__((noreturn));
void warn_here(void);
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(void) {
raze();
return ((0)); // expected-warning {{'return' will never be executed}}
}
void trivial_dead_return_void(void) {
raze();
return; // expected-warning {{'return' will never be executed}}
}
MyEnum trivial_dead_return_enum(void) {
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(void) {
raze();
return ""; // expected-warning {{return' will never be executed}}
}
char trivial_dead_return_char(void) {
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(void) {
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(void) {
raze();
return; // no-warning
}
MyEnum trivial_dead_return_enum_SUPPRESSED(void) {
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();
}
// rdar://24570531
struct StructWithPointer {
void *p;
};
void emitJustOneWarningForOr(struct StructWithPointer *s) {
if (1 || !s->p) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:"/* DISABLES CODE */ ("
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:8-[[@LINE-2]]:8}:")"
emitJustOneWarningForOr(s); // expected-warning {{code will never be executed}}
}
void emitJustOneWarningForOrSilenced(struct StructWithPointer *s) {
if ((1) || !s->p)
return;
emitJustOneWarningForOrSilenced(s); // no warning
}
void emitJustOneWarningForOr2(struct StructWithPointer *s) {
if (1 || !s->p) // expected-warning {{code will never be executed}}
return; // expected-note@-1 {{silence by adding parentheses to mark code as explicitly dead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:7-[[@LINE-2]]:7}:"/* DISABLES CODE */ ("
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:8}:")"
}
void wrapOneInFixit(struct StructWithPointer *s) {
if (!s->p || 1) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"/* DISABLES CODE */ ("
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:17-[[@LINE-2]]:17}:")"
wrapOneInFixit(s); // expected-warning {{code will never be executed}}
}
void unaryOpNoFixit(void) {
if (~ 1)
return; // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
unaryOpNoFixit(); // expected-warning {{code will never be executed}}
}
void unaryOpStrictFixit(struct StructWithPointer *s) {
if (!(s->p && 0)) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:17-[[@LINE-1]]:17}:"/* DISABLES CODE */ ("
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:18-[[@LINE-2]]:18}:")"
unaryOpStrictFixit(s); // expected-warning {{code will never be executed}}
}
void unaryOpFixitCastSubExpr(int x) {
if (! (int)0) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
return; // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:7}:"/* DISABLES CODE */ ("
// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:15}:")"
unaryOpFixitCastSubExpr(x); // expected-warning {{code will never be executed}}
}
#define false 0
#define true 1
void testTrueFalseMacros(void) {
if (false) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
testTrueFalseMacros(); // expected-warning {{code will never be executed}}
if (!true) // expected-note {{silence by adding parentheses to mark code as explicitly dead}}
testTrueFalseMacros(); // expected-warning {{code will never be executed}}
}
int pr13910_foo(int x) {
if (x == 1)
return 0;
else
return x;
__builtin_unreachable(); // expected no warning
__builtin_assume(0); // expected no warning
}
int pr13910_bar(int x) {
switch (x) {
default:
return x + 1;
}
pr13910_foo(x); // expected-warning {{code will never be executed}}
}
int pr13910_bar2(int x) {
if (x == 1)
return 0;
else
return x;
pr13910_foo(x); // expected-warning {{code will never be executed}}
__builtin_unreachable(); // expected no warning
__builtin_assume(0); // expected no warning
pr13910_foo(x); // expected-warning {{code will never be executed}}
}
void pr13910_noreturn(void) {
raze();
__builtin_unreachable(); // expected no warning
__builtin_assume(0); // expected no warning
}
void pr13910_assert(void) {
myassert(0 && "unreachable");
return;
__builtin_unreachable(); // expected no warning
__builtin_assume(0); // expected no warning
}