aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/GRExprEngine.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-01-17 01:54:16 +0000
committerTed Kremenek <kremenek@apple.com>2009-01-17 01:54:16 +0000
commit72afb3739da0da02158242ae41a50cfe0bea78b4 (patch)
tree46868a01af0b45bb2c4cf5ad1c4e25fb5ecf56fb /lib/Analysis/GRExprEngine.cpp
parent69d993ad8418cf21a56cf5b16c0f1c3cd6f74b64 (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.cpp60
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);
}