From: Ted Kremenek Date: Mon, 18 Feb 2008 22:57:02 +0000 (+0000) Subject: Added more assertions and checks in transfer function logic to check for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=692416c214a3b234236dedcf875735a9cc29e90b;p=clang 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 --- 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(GetValue(St, builder.getCondition())); + Expr* CondE = builder.getCondition(); + NonLValue CondV = cast(GetValue(St, CondE)); if (isa(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(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(Cond)); + + if (isa(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(Cond)); + + if (isa(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(X) && !isa(X)); + if (!isa(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(X) && !isa(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(X) && !isa(X)); + switch (X.getSubKind()) { case nonlval::ConcreteIntKind: return cast(X).EvalMinus(ValMgr, U); @@ -105,6 +111,9 @@ NonLValue GRSimpleVals::EvalMinus(ValueManager& ValMgr, UnaryOperator* U, } NonLValue GRSimpleVals::EvalComplement(ValueManager& ValMgr, NonLValue X) { + + assert (!isa(X) && !isa(X)); + switch (X.getSubKind()) { case nonlval::ConcreteIntKind: return cast(X).EvalComplement(ValMgr); @@ -119,11 +128,8 @@ NonLValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, NonLValue LHS, NonLValue RHS) { - if (isa(LHS) || isa(RHS)) - return cast(UnknownVal()); - - if (isa(LHS) || isa(RHS)) - return cast(UninitializedVal()); + assert (!isa(LHS) && !isa(LHS)); + assert (!isa(RHS) && !isa(RHS)); while(1) { @@ -169,6 +175,9 @@ RValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, LValue LHS, LValue RHS) { + assert (!isa(LHS) && !isa(LHS)); + assert (!isa(RHS) && !isa(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(LHS) && !isa(LHS)); + assert (!isa(RHS) && !isa(RHS)); + return cast(UnknownVal()); } @@ -194,6 +207,9 @@ LValue GRSimpleVals::EvalBinaryOp(ValueManager& ValMgr, NonLValue GRSimpleVals::EvalEQ(ValueManager& ValMgr, LValue LHS, LValue RHS) { + assert (!isa(LHS) && !isa(LHS)); + assert (!isa(RHS) && !isa(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(LHS) && !isa(LHS)); + assert (!isa(RHS) && !isa(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(LV)) return UnknownVal(); + assert (!isa(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(LV)); + assert (!isa(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(X) || isa(X)) + return X; + + return TF->EvalCast(ValMgr, X, CastExpr); } inline NonLValue EvalMinus(ValueManager& ValMgr, UnaryOperator* U, NonLValue X) { + if (isa(X) || isa(X)) + return X; + return TF->EvalMinus(ValMgr, U, X); } inline NonLValue EvalComplement(ValueManager& ValMgr, NonLValue X) { + if (isa(X) || isa(X)) + return X; + return TF->EvalComplement(ValMgr, X); } inline NonLValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, NonLValue LHS, NonLValue RHS) { + + if (isa(LHS) || isa(RHS)) + return cast(UninitializedVal()); + + if (isa(LHS) || isa(RHS)) + return cast(UnknownVal()); + return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS); } inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, LValue LHS, LValue RHS) { + + if (isa(LHS) || isa(RHS)) + return UninitializedVal(); + + if (isa(LHS) || isa(RHS)) + return UnknownVal(); + return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS); } inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, LValue LHS, NonLValue RHS) { + + if (isa(LHS) || isa(RHS)) + return UninitializedVal(); + + if (isa(LHS) || isa(RHS)) + return UnknownVal(); + return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS); } inline RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op, RValue LHS, RValue RHS) { + + if (isa(LHS) || isa(RHS)) + return UninitializedVal(); + + if (isa(LHS) || isa(RHS)) + return UnknownVal(); + return TF->EvalBinaryOp(ValMgr, Op, LHS, RHS); } };