aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-02-18 22:57:02 +0000
committerTed Kremenek <kremenek@apple.com>2008-02-18 22:57:02 +0000
commit692416c214a3b234236dedcf875735a9cc29e90b (patch)
tree32571c1bf44115b4ae1666f14e12cc3be674efdb
parent305762c08975cd6e0bebd684ca910fa208792483 (diff)
Added more assertions and checks in transfer function logic to check for
UninitializedVals and UnknownVals. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47288 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Analysis/GRExprEngine.cpp35
-rw-r--r--Analysis/GRSimpleVals.cpp31
-rw-r--r--Analysis/ValueState.cpp5
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h41
4 files changed, 97 insertions, 15 deletions
diff --git a/Analysis/GRExprEngine.cpp b/Analysis/GRExprEngine.cpp
index 4bcdd5fb70..d709eff99f 100644
--- a/Analysis/GRExprEngine.cpp
+++ b/Analysis/GRExprEngine.cpp
@@ -209,7 +209,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
typedef SwitchNodeBuilder::iterator iterator;
StateTy St = builder.getState();
- NonLValue CondV = cast<NonLValue>(GetValue(St, builder.getCondition()));
+ Expr* CondE = builder.getCondition();
+ NonLValue CondV = cast<NonLValue>(GetValue(St, CondE));
if (isa<UninitializedVal>(CondV)) {
NodeTy* N = builder.generateDefaultCaseNode(St, true);
@@ -221,7 +222,10 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
// 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(getContext().IntTy,SourceLocation());
+
+ unsigned bits = getContext().getTypeSize(CondE->getType(),
+ CondE->getExprLoc());
+
APSInt V1(bits, false);
APSInt V2 = V1;
@@ -258,7 +262,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
NonLValue Res = EvalBinaryOp(ValMgr, BinaryOperator::EQ, CondV, CaseVal);
// Now "assume" that the case matches.
- bool isFeasible;
+ bool isFeasible = false;
StateTy StNew = Assume(St, Res, true, isFeasible);
@@ -588,7 +592,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
// FIXME: Stop when dereferencing an uninitialized value.
// FIXME: Bifurcate when dereferencing a symbolic with no constraints?
- const RValue& V = GetValue(St, U->getSubExpr());
+ const RValue& V = GetValue(St, U->getSubExpr());
const LValue& L1 = cast<LValue>(V);
// After a dereference, one of two possible situations arise:
@@ -608,6 +612,9 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U,
GetValue(StNotNull, L1, &T)));
}
+ if (V.isUnknown())
+ return;
+
bool isFeasibleNull;
// "Assume" that the pointer is NULL.
@@ -868,8 +875,15 @@ void GRExprEngine::Visit(Stmt* S, GRExprEngine::NodeTy* Pred,
//===----------------------------------------------------------------------===//
GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, LValue Cond,
- bool Assumption,
- bool& isFeasible) {
+ bool Assumption,
+ bool& isFeasible) {
+
+ assert (!isa<UninitializedVal>(Cond));
+
+ if (isa<UnknownVal>(Cond)) {
+ isFeasible = true;
+ return St;
+ }
switch (Cond.getSubKind()) {
default:
@@ -901,6 +915,13 @@ GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, NonLValue Cond,
bool Assumption,
bool& isFeasible) {
+ assert (!isa<UninitializedVal>(Cond));
+
+ if (isa<UnknownVal>(Cond)) {
+ isFeasible = true;
+ return St;
+ }
+
switch (Cond.getSubKind()) {
default:
assert (false && "'Assume' not implemented for this NonLValue.");
@@ -936,7 +957,7 @@ GRExprEngine::StateTy GRExprEngine::Assume(StateTy St, NonLValue Cond,
GRExprEngine::StateTy
GRExprEngine::AssumeSymNE(StateTy St, SymbolID sym,
const llvm::APSInt& V, bool& isFeasible) {
-
+
// First, determine if sym == X, where X != V.
if (const llvm::APSInt* X = St.getSymVal(sym)) {
isFeasible = *X != V;
diff --git a/Analysis/GRSimpleVals.cpp b/Analysis/GRSimpleVals.cpp
index 58f0729a70..87b39b70c5 100644
--- a/Analysis/GRSimpleVals.cpp
+++ b/Analysis/GRSimpleVals.cpp
@@ -31,7 +31,7 @@ namespace clang {
CheckerState->setTransferFunctions(GRSV);
// Execute the worklist algorithm.
- Engine.ExecuteWorkList(200);
+ Engine.ExecuteWorkList(10000);
// Look for explicit-Null dereferences and warn about them.
for (GRExprEngine::null_iterator I=CheckerState->null_begin(),
@@ -57,6 +57,8 @@ namespace clang {
RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLValue X,
Expr* CastExpr) {
+ assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
+
if (!isa<nonlval::ConcreteInt>(X))
return UnknownVal();
@@ -74,6 +76,8 @@ RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, NonLValue X,
// Casts.
RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
+
+ assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
if (CastExpr->getType()->isPointerType())
return X;
@@ -96,6 +100,8 @@ RValue GRSimpleVals::EvalCast(ValueManager& ValMgr, LValue X, Expr* CastExpr) {
NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
NonLValue X) {
+ assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
+
switch (X.getSubKind()) {
case nonlval::ConcreteIntKind:
return cast<nonlval::ConcreteInt>(X).EvalMinus(ValMgr, U);
@@ -105,6 +111,9 @@ NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
}
NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) {
+
+ assert (!isa<UnknownVal>(X) && !isa<UninitializedVal>(X));
+
switch (X.getSubKind()) {
case nonlval::ConcreteIntKind:
return cast<nonlval::ConcreteInt>(X).EvalComplement(ValMgr);
@@ -119,11 +128,8 @@ NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS) {
- if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
- return cast<NonLValue>(UnknownVal());
-
- if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
- return cast<NonLValue>(UninitializedVal());
+ assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
+ assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
while(1) {
@@ -169,6 +175,9 @@ RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
LValue LHS, LValue RHS) {
+ assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
+ assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
+
switch (Op) {
default:
return UnknownVal();
@@ -186,6 +195,10 @@ RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
LValue LHS, NonLValue RHS) {
+
+ assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
+ assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
+
return cast<LValue>(UnknownVal());
}
@@ -194,6 +207,9 @@ LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr,
NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
+ assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
+ assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
+
switch (LHS.getSubKind()) {
default:
assert(false && "EQ not implemented for this LValue.");
@@ -249,6 +265,9 @@ NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) {
}
NonLValue GRSimpleVals::EvalNE(ValueManager& ValMgr, LValue LHS, LValue RHS) {
+
+ assert (!isa<UnknownVal>(LHS) && !isa<UninitializedVal>(LHS));
+ assert (!isa<UnknownVal>(RHS) && !isa<UninitializedVal>(RHS));
switch (LHS.getSubKind()) {
default:
diff --git a/Analysis/ValueState.cpp b/Analysis/ValueState.cpp
index 9b2ed9686a..016b070547 100644
--- a/Analysis/ValueState.cpp
+++ b/Analysis/ValueState.cpp
@@ -129,6 +129,8 @@ RValue ValueStateManager::GetValue(ValueState St, const LValue& LV,
if (isa<UnknownVal>(LV))
return UnknownVal();
+ assert (!isa<UninitializedVal>(LV));
+
switch (LV.getSubKind()) {
case lval::DeclValKind: {
ValueState::VarBindingsTy::TreeTy* T =
@@ -327,6 +329,9 @@ ValueStateManager::SetValue(ValueState St, Expr* E, bool isBlkExpr,
ValueState
ValueStateManager::SetValue(ValueState St, const LValue& LV, const RValue& V) {
+ assert (!isa<UnknownVal>(LV));
+ assert (!isa<UninitializedVal>(LV));
+
switch (LV.getSubKind()) {
case lval::DeclValKind:
return V.isKnown() // FIXME: Have DeclVal only contain VarDecl
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index a52a776a1d..ff9c26cf7c 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -308,36 +308,73 @@ public:
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst);
- inline RValue EvalCast(ValueManager& ValMgr, RValue R, Expr* CastExpr) {
- return TF->EvalCast(ValMgr, R, CastExpr);
+ inline RValue EvalCast(ValueManager& ValMgr, RValue X, Expr* CastExpr) {
+ if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
+ return X;
+
+ return TF->EvalCast(ValMgr, X, CastExpr);
}
inline NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U,
NonLValue X) {
+ if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
+ return X;
+
return TF->EvalMinus(ValMgr, U, X);
}
inline NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) {
+ if (isa<UnknownVal>(X) || isa<UninitializedVal>(X))
+ return X;
+
return TF->EvalComplement(ValMgr, X);
}
inline NonLValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
NonLValue LHS, NonLValue RHS) {
+
+ if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
+ return cast<NonLValue>(UninitializedVal());
+
+ if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
+ return cast<NonLValue>(UnknownVal());
+
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
LValue LHS, LValue RHS) {
+
+ if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
+ return UninitializedVal();
+
+ if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
+ return UnknownVal();
+
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
LValue LHS, NonLValue RHS) {
+
+ if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
+ return UninitializedVal();
+
+ if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
+ return UnknownVal();
+
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
RValue LHS, RValue RHS) {
+
+ if (isa<UninitializedVal>(LHS) || isa<UninitializedVal>(RHS))
+ return UninitializedVal();
+
+ if (isa<UnknownVal>(LHS) || isa<UnknownVal>(RHS))
+ return UnknownVal();
+
return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS);
}
};