diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-01-17 01:54:16 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-01-17 01:54:16 +0000 |
commit | 72afb3739da0da02158242ae41a50cfe0bea78b4 (patch) | |
tree | 46868a01af0b45bb2c4cf5ad1c4e25fb5ecf56fb /lib/Analysis/GRExprEngine.cpp | |
parent | 69d993ad8418cf21a56cf5b16c0f1c3cd6f74b64 (diff) |
Fix analyzer crash found when scanning Wine sources where the analyzer used old logic to determine the value of a switch 'case' label.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62395 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 60 |
1 files changed, 25 insertions, 35 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 73df09a6f4..8656ef4a90 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -698,10 +698,8 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor /// nodes by processing the 'effects' of a switch statement. -void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { - - typedef SwitchNodeBuilder::iterator iterator; - +void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { + typedef SwitchNodeBuilder::iterator iterator; const GRState* St = builder.getState(); Expr* CondE = builder.getCondition(); SVal CondV = GetSVal(St, CondE); @@ -711,38 +709,32 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { UndefBranches.insert(N); return; } - - const GRState* DefaultSt = St; - - // While most of this can be assumed (such as the signedness), having it - // just computed makes sure everything makes the same assumptions end-to-end. - - unsigned bits = getContext().getTypeSize(CondE->getType()); - APSInt V1(bits, false); - APSInt V2 = V1; + const GRState* DefaultSt = St; bool DefaultFeasible = false; for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) { - CaseStmt* Case = cast<CaseStmt>(I.getCase()); - - // Evaluate the case. - if (!Case->getLHS()->isIntegerConstantExpr(V1, getContext(), 0, true)) { - assert (false && "Case condition must evaluate to an integer constant."); - return; - } - + + // Evaluate the LHS of the case value. + Expr::EvalResult V1; + bool b = Case->getLHS()->Evaluate(V1, getContext()); + + // Sanity checks. These go away in Release builds. + assert(b && V1.Val.isInt() && !V1.HasSideEffects + && "Case condition must evaluate to an integer constant."); + b = b; // silence unused variable warning + assert(V1.Val.getInt().getBitWidth() == + getContext().getTypeSize(CondE->getType())); + // Get the RHS of the case, if it exists. + Expr::EvalResult V2; if (Expr* E = Case->getRHS()) { - if (!E->isIntegerConstantExpr(V2, getContext(), 0, true)) { - assert (false && - "Case condition (RHS) must evaluate to an integer constant."); - return ; - } - - assert (V1 <= V2); + b = E->Evaluate(V2, getContext()); + assert(b && V2.Val.isInt() && !V2.HasSideEffects + && "Case condition must evaluate to an integer constant."); + b = b; // silence unused variable warning } else V2 = V1; @@ -752,12 +744,10 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { // This should be easy once we have "ranges" for NonLVals. do { - nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1)); - + nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt())); SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal); - // Now "assume" that the case matches. - + // Now "assume" that the case matches. bool isFeasible = false; const GRState* StNew = Assume(St, Res, true, isFeasible); @@ -783,11 +773,11 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { } // Concretize the next value in the range. - if (V1 == V2) + if (V1.Val.getInt() == V2.Val.getInt()) break; - ++V1; - assert (V1 <= V2); + ++V1.Val.getInt(); + assert (V1.Val.getInt() <= V2.Val.getInt()); } while (true); } |