[-Wunreachable-code] Tweak heuristic for configuration values to include arithmetic operations involving sizeof(), but not raw integers.
This case was motivated by a false positive with the llvm::AlignOf<> specialization in LLVM. llvm-svn: 203363
This commit is contained in:
parent
b97112e4bd
commit
c980afc578
|
@ -189,7 +189,8 @@ static bool isExpandedFromConfigurationMacro(const Stmt *S) {
|
||||||
/// "sometimes unreachable" code. Such code is usually not interesting
|
/// "sometimes unreachable" code. Such code is usually not interesting
|
||||||
/// to report as unreachable, and may mask truly unreachable code within
|
/// to report as unreachable, and may mask truly unreachable code within
|
||||||
/// those blocks.
|
/// those blocks.
|
||||||
static bool isConfigurationValue(const Stmt *S) {
|
static bool isConfigurationValue(const Stmt *S,
|
||||||
|
bool IncludeIntegers = true) {
|
||||||
if (!S)
|
if (!S)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -201,7 +202,7 @@ static bool isConfigurationValue(const Stmt *S) {
|
||||||
const DeclRefExpr *DR = cast<DeclRefExpr>(S);
|
const DeclRefExpr *DR = cast<DeclRefExpr>(S);
|
||||||
const ValueDecl *D = DR->getDecl();
|
const ValueDecl *D = DR->getDecl();
|
||||||
if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))
|
if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))
|
||||||
return ED ? isConfigurationValue(ED->getInitExpr()) : false;
|
return isConfigurationValue(ED->getInitExpr());
|
||||||
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
|
||||||
// As a heuristic, treat globals as configuration values. Note
|
// As a heuristic, treat globals as configuration values. Note
|
||||||
// that we only will get here if Sema evaluated this
|
// that we only will get here if Sema evaluated this
|
||||||
|
@ -215,14 +216,18 @@ static bool isConfigurationValue(const Stmt *S) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case Stmt::IntegerLiteralClass:
|
case Stmt::IntegerLiteralClass:
|
||||||
return isExpandedFromConfigurationMacro(S);
|
return IncludeIntegers ? isExpandedFromConfigurationMacro(S)
|
||||||
|
: false;
|
||||||
case Stmt::UnaryExprOrTypeTraitExprClass:
|
case Stmt::UnaryExprOrTypeTraitExprClass:
|
||||||
return true;
|
return true;
|
||||||
case Stmt::BinaryOperatorClass: {
|
case Stmt::BinaryOperatorClass: {
|
||||||
const BinaryOperator *B = cast<BinaryOperator>(S);
|
const BinaryOperator *B = cast<BinaryOperator>(S);
|
||||||
return (B->isLogicalOp() || B->isComparisonOp()) &&
|
// Only include raw integers (not enums) as configuration
|
||||||
(isConfigurationValue(B->getLHS()) ||
|
// values if they are used in a logical or comparison operator
|
||||||
isConfigurationValue(B->getRHS()));
|
// (not arithmetic).
|
||||||
|
IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp());
|
||||||
|
return isConfigurationValue(B->getLHS(), IncludeIntegers) ||
|
||||||
|
isConfigurationValue(B->getRHS(), IncludeIntegers);
|
||||||
}
|
}
|
||||||
case Stmt::UnaryOperatorClass: {
|
case Stmt::UnaryOperatorClass: {
|
||||||
const UnaryOperator *UO = cast<UnaryOperator>(S);
|
const UnaryOperator *UO = cast<UnaryOperator>(S);
|
||||||
|
|
|
@ -175,3 +175,27 @@ void raze(const A& x);
|
||||||
void test_with_unreachable_tmp_dtors(int x) {
|
void test_with_unreachable_tmp_dtors(int x) {
|
||||||
raze(x ? A() : A()); // no-warning
|
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}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue