From: Ted Kremenek Date: Thu, 9 Sep 2010 00:40:40 +0000 (+0000) Subject: Static analyzer fix: Switch on enum should not consider... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d3175c1e5a44251ea97b0c81e80f060629d9c08;p=clang Static analyzer fix: Switch on enum should not consider default case live if all enum values are covered git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113457 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 48130becf3..1f3a1bac97 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -422,6 +422,10 @@ public: /// ParenExpr or ImplicitCastExprs, returning their operand. Expr *IgnoreParenImpCasts(); + const Expr *IgnoreParenImpCasts() const { + return const_cast(this)->IgnoreParenImpCasts(); + } + /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index 216ecac736..bba59f587e 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -422,6 +422,10 @@ public: iterator begin() { return iterator(Src->succ_rbegin()+1); } iterator end() { return iterator(Src->succ_rend()); } + const SwitchStmt *getSwitch() const { + return llvm::cast(Src->getTerminator()); + } + ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State); ExplodedNode* generateDefaultCaseNode(const GRState* State, diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 1c8a2d61b9..c11785a711 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -1561,9 +1561,24 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) { } while (true); } - // If we reach here, than we know that the default branch is - // possible. - if (defaultIsFeasible) builder.generateDefaultCaseNode(DefaultSt); + if (!defaultIsFeasible) + return; + + // If we have switch(enum value), the default branch is not + // feasible if all of the enum constants not covered by 'case:' statements + // are not feasible values for the switch condition. + // + // Note that this isn't as accurate as it could be. Even if there isn't + // a case for a particular enum value as long as that enum value isn't + // feasible then it shouldn't be considered for making 'default:' reachable. + const SwitchStmt *SS = builder.getSwitch(); + const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts(); + if (CondExpr->getType()->getAs()) { + if (SS->isAllEnumCasesCovered()) + return; + } + + builder.generateDefaultCaseNode(DefaultSt); } void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) {