From df4c4c09eeb747af3a42734a895879ed0289fa1a Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 8 Mar 2014 23:20:11 +0000 Subject: [PATCH] [-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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203363 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ReachableCode.cpp | 17 +++++++++++------ test/SemaCXX/warn-unreachable.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp index 9191958399..1210fcdd3a 100644 --- a/lib/Analysis/ReachableCode.cpp +++ b/lib/Analysis/ReachableCode.cpp @@ -189,7 +189,8 @@ static bool isExpandedFromConfigurationMacro(const Stmt *S) { /// "sometimes unreachable" code. Such code is usually not interesting /// to report as unreachable, and may mask truly unreachable code within /// those blocks. -static bool isConfigurationValue(const Stmt *S) { +static bool isConfigurationValue(const Stmt *S, + bool IncludeIntegers = true) { if (!S) return false; @@ -201,7 +202,7 @@ static bool isConfigurationValue(const Stmt *S) { const DeclRefExpr *DR = cast(S); const ValueDecl *D = DR->getDecl(); if (const EnumConstantDecl *ED = dyn_cast(D)) - return ED ? isConfigurationValue(ED->getInitExpr()) : false; + return isConfigurationValue(ED->getInitExpr()); if (const VarDecl *VD = dyn_cast(D)) { // As a heuristic, treat globals as configuration values. Note // that we only will get here if Sema evaluated this @@ -215,14 +216,18 @@ static bool isConfigurationValue(const Stmt *S) { return false; } case Stmt::IntegerLiteralClass: - return isExpandedFromConfigurationMacro(S); + return IncludeIntegers ? isExpandedFromConfigurationMacro(S) + : false; case Stmt::UnaryExprOrTypeTraitExprClass: return true; case Stmt::BinaryOperatorClass: { const BinaryOperator *B = cast(S); - return (B->isLogicalOp() || B->isComparisonOp()) && - (isConfigurationValue(B->getLHS()) || - isConfigurationValue(B->getRHS())); + // Only include raw integers (not enums) as configuration + // values if they are used in a logical or comparison operator + // (not arithmetic). + IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp()); + return isConfigurationValue(B->getLHS(), IncludeIntegers) || + isConfigurationValue(B->getRHS(), IncludeIntegers); } case Stmt::UnaryOperatorClass: { const UnaryOperator *UO = cast(S); diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index 0b7af0b1f4..49d26daa2f 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -175,3 +175,27 @@ 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}} +} + -- 2.40.0