diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp index 9191958399b689aeea7a9c70eff47618442d9c12..1210fcdd3ae936c2cc837244600005eb9add989b 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<DeclRefExpr>(S); const ValueDecl *D = DR->getDecl(); 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)) { // 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<BinaryOperator>(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<UnaryOperator>(S); diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index 0b7af0b1f446780af2201d36267385a5b2d78a49..49d26daa2f62ad0a2792931da21f4400ccbc3975 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}} +} +