]> granicus.if.org Git - clang/commitdiff
Static analyzer fix: <rdar://problem/5880430> Switch on enum should not consider...
authorTed Kremenek <kremenek@apple.com>
Thu, 9 Sep 2010 00:40:40 +0000 (00:40 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 9 Sep 2010 00:40:40 +0000 (00:40 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113457 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
include/clang/Checker/PathSensitive/GRCoreEngine.h
lib/Checker/GRExprEngine.cpp

index 48130becf3b5b6fd11540a3809f206f3b557f0fe..1f3a1bac971d0a36c2cd9b2bef615e7270c5ed55 100644 (file)
@@ -422,6 +422,10 @@ public:
   /// ParenExpr or ImplicitCastExprs, returning their operand.
   Expr *IgnoreParenImpCasts();
 
+  const Expr *IgnoreParenImpCasts() const {
+    return const_cast<Expr*>(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.
index 216ecac73653195c23748c6b10e6473545a6b221..bba59f587eeff11e0b68d1749be3a5525a680e59 100644 (file)
@@ -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<SwitchStmt>(Src->getTerminator());
+  }
+
   ExplodedNode* generateCaseStmtNode(const iterator& I, const GRState* State);
 
   ExplodedNode* generateDefaultCaseNode(const GRState* State,
index 1c8a2d61b9b5194a754cc75fa2dfd62a2a69e581..c11785a711ed68588add5cdaa13c5648a69fce3b 100644 (file)
@@ -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<EnumType>()) {
+    if (SS->isAllEnumCasesCovered())
+      return;
+  }
+
+  builder.generateDefaultCaseNode(DefaultSt);
 }
 
 void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) {